標籤:each 結構體 define efi com div header class 指標成員
之前的鏈表就是一個普通的帶頭的單向鏈表,我們不自覺的會發現這樣的鏈表有缺陷,有關鏈表的刪除新增尋找跟鏈表的結構體內容耦合性太強
什麼意思呢?
比如我們之前的鏈表的結構體
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語言鏈表升級