c語言鏈表升級
阿新 • • 發佈:2017-08-09
logs ++ reat length 清空 str lib 指針變量 h+
之前的鏈表就是一個普通的帶頭的單向鏈表,我們不自覺的會發現這樣的鏈表有缺陷,有關鏈表的刪除新增查找跟鏈表的結構體內容耦合性太強
什麽意思呢?
比如我們之前的鏈表的結構體
typedef struct _Teacher { int age; struct _Teacher *next; }Teacher;
我們有關鏈表所有的操作都跟這個結構體緊密的相連,如果此刻我們有另一個結構體,裏面的字段都跟這個不一樣,那麽,我們可能還需要對這個新的結構體寫一套鏈表操作?
相當於下面的圖,呵呵,有點醜
那麽我們的解決方案是什麽呢?,我們能不能關於不同結構體的所有操作都有一套公共方法呢?
當然是可以的!
在這之前我們必須有一個概念,結構體中的第一個元素的地址就是代表結構體的地址。
我們設計一個單純代表數據結構的結構體,這個結構體只有下個對象的地址的指針成員
typedef struct _tag_LinkListNode { void * next; }LinkListNode;
比如此刻我們有一個教師結構體,那麽我們只需要在結構體的第一個成員是上面的LinkListNode對象。
形成下面的數據結構:
typedef struct _Teacher { LinkListNode listNode; int age; char name[50]; }Teacher;
那麽,此刻我們只要在我們的對鏈表的操作將傳過來的Teacher * 指針強轉為LinkListNode *類型,查詢出來的LinkListNode * 指針變量再強轉為Teacher * 對象,從而對LinkListNode形成一套插入刪除查詢的api就可以了
以下是實現的代碼:
接口:
#ifndef _MYLINKLIST_H_ #define _MYLINKLIST_H_ typedef void LinkList; typedef struct _tag_LinkListNode { struct _tag_LinkListNode* next; }LinkListNode; LinkList* LinkList_Create(); void LinkList_Destroy(LinkList* list); void LinkList_Clear(LinkList* list); int LinkList_Length(LinkList* list); int LinkList_Insert(LinkList* list, LinkListNode* node, int pos); LinkListNode* LinkList_Get(LinkList* list, int pos); LinkListNode* LinkList_Delete(LinkList* list, int pos); #endif
實現:
#include "stdio.h" #include "stdlib.h" #include "linklist.h" typedef struct _tag_LinkList { //頭節點 LinkListNode header; int length; }TLinkList; /************************************************************************/ /* 創建list並初始化一個頭節點 */ /************************************************************************/ LinkList* LinkList_Create() { TLinkList *tlist = (TLinkList *)malloc(sizeof(TLinkList)); if (tlist == NULL) { return NULL; } tlist->length = 0; tlist->header.next = NULL; return tlist; } void LinkList_Destroy(LinkList* list) { if (list == NULL) { return; } free(list); } /************************************************************************/ /* 清空list鏈表 */ /************************************************************************/ void LinkList_Clear(LinkList* list) { if (list == NULL) { return; } TLinkList *tlinkList = (TLinkList *)list; tlinkList->length = 0; tlinkList->header.next = NULL; } int LinkList_Length(LinkList* list) { if (list == NULL) { return 0; } TLinkList *tlinkList = (TLinkList *)list; return tlinkList->length; } int LinkList_Insert(LinkList* list, LinkListNode* node, int pos) { LinkListNode *pre, *cur; int i; if (list == NULL || node == NULL) { return -1; } //校驗下標 if (pos<0) { return -2; } TLinkList *tlinkList = (TLinkList *)list; if (pos>tlinkList->length - 1) { pos = tlinkList->length; } pre = (LinkListNode *)list;//初始化指向頭節點 cur = tlinkList->header.next;//初始化指向第一個節點,如果空鏈表指向空 for (i = 0; i < pos; i++) { pre = cur; cur = cur->next;//最終讓當前指針指向要插入的位置 } pre->next = node; node->next = cur; tlinkList->length++; return 0; } LinkListNode* LinkList_Get(LinkList* list, int pos) { LinkListNode *pre, *cur; int i; if (list == NULL) { return NULL; } TLinkList *tlinkList = (TLinkList *)list; //校驗下標 if (pos >= tlinkList->length || pos < 0) { return NULL; } cur = tlinkList->header.next;//初始化指向第一個節點,如果空鏈表指向空 for (i = 0; i < pos; i++) { cur = cur->next; } return cur; } LinkListNode* LinkList_Delete(LinkList* list, int pos) { LinkListNode *pre, *cur; int i; if (list == NULL) { return NULL; } TLinkList *tlinkList = (TLinkList *)list; //校驗下標 if (pos >= tlinkList->length || pos < 0) { return NULL; } pre = (LinkListNode *)list;//初始化指向頭節點 cur = tlinkList->header.next;//初始化指向第一個節點,如果空鏈表指向空 for (i = 0; i < pos; i++) { pre = cur; cur = cur->next; } pre->next = cur->next; LinkListNode* curnode = cur; tlinkList->length--; return curnode; }
測試代碼
#include "stdio.h" #include "stdlib.h" #include "linklist.h" typedef struct _Teacher { LinkListNode listNode; int age; char name[50]; }Teacher; void main() { LinkList* linkList; Teacher t1, t2, t3; int len; int i; linkList = LinkList_Create(); t1.age = 11; t2.age = 22; t3.age = 33; LinkList_Insert(linkList, (LinkListNode*)&t1, 0); LinkList_Insert(linkList, (LinkListNode*)&t2, 0); LinkList_Insert(linkList, (LinkListNode*)&t3, 0); len = LinkList_Length(linkList); for (i = 0; i < len; i++) { Teacher * t = (Teacher *)LinkList_Get(linkList, i); printf("cur teacher age=%d\n", t->age); } LinkList_Delete(linkList, 0); LinkList_Delete(linkList, 1); len = LinkList_Length(linkList); for (i = 0; i < len; i++) { Teacher * t = (Teacher *)LinkList_Get(linkList, i); printf("cur teacher age=%d\n", t->age); } system("pause"); }
接下來,如果我們有新的結構體,只要在測試代碼那邊做修改,而不需要動我們的核心代碼了。
c語言鏈表升級