順序存儲:
typedef struct _tag_LinkNode { int length; int capacity; void **node; }Link;
用以上結構體表達,length表示線性表目前有多少元素,capacity表示整個線性表的容量(創建之時已固定)
而這個node,最不容易理解,可以抽象為一個指針數組.每個元素都指向一個業務節點的內存地址,在創建之時必須與capacity動態綁定,代表可以容納多少個業務節點.
在封裝內部方法時,核心思想是業務層將業務節點轉換成void *傳遞進來.保存在**node數組指針中,(unsigned int)類型也可以保存指針值.
內部再提供一個方法,將數組指針的某一個指針返回給業務層,業務層再根據實際情況進行指針轉換,拿到數據進行操作.
鏈式存儲:
typedef struct _tag_LinkListNode //h頭文件 { struct _tag_LinkListNode* next; }LinkListNode; typedef struct _tag_LinkList //內部封裝 { //這個句柄里面,需要保存所有節點信息。需要有一個起始點 //就是帶頭節點的鏈表。。。 LinkListNode header; int length; }TLinkList; typedef struct Teacher //上層業務 { LinkListNode node; char name[64]; int age; }Teacher;
如代碼所示,頭文件定義的這個節點,是所有實現的核心,內部封裝需要包含它,業務節點也需要包含它,但均要將其放在第一個域中,
用圖來表示
TLinklist其實就是左邊最大的那個,與我以前所學習的不一樣.以前學習的只是定義一個節點,將指針域放在其中,而這里,定義的是個鏈表,不包含業務數據,將業務數據與鏈表算法分離開來,實現低耦合,其技術的精華之處在以下代碼
int LinkList_Insert(LinkList* list, LinkListNode* node, int pos) { int i = 0; TLinkList *tList = NULL; LinkListNode *current = NULL; tList = (TLinkList *)list; //准備環境讓輔助指針變量 指向鏈表頭節點 current = &tList->header; for (i=0; i<pos &&(current->next!=NULL); i++) { current = current->next; } //讓node節點鏈接后續鏈表 node->next = current->next ; //讓前邊的鏈表。鏈接node current->next = node; tList->length ++; return 0; }
在17行的node->next = current->next ,這個node就是業務層傳遞進來的業務節點,將其轉換成了LinkListNode,
關鍵來了,在業務節點里,node在第一個域,以前學習過->,.其實就是尋址操作(然后自動加*號取值)
而使用第一個域node,對於業務節點,只偏移了四個字節,前面說過,node就
是業務層傳遞進來的業務節點,雖然類型發生了變化,但里面的內容沒變,偏移的四個字節剛好只是訪問了業務節點中的node域,進而實現的業務節點的串連
17行的這個node就是間接地操作業務節點中的node