【 聲明:著作權,歡迎轉載,請勿用於商業用途。 聯絡信箱:feixiaoxing @163.com】
在軟體開發中,我想鏈表是除了數組之外,用的最多的一種資料結構。但是,如何把鏈表結構和資料本身能夠完美地融合在一起,這本身確是一件複雜的事情。但是linux kernel在這方面為我們做出了示範,讓我們在充分地享受方便的同時,無需考慮鏈表的一些具體操作。那麼,在linux kernel下面,鏈表是怎麼做到的呢?我們可以自己編寫一個代碼示範一下,基本原理都是一樣的,可能在實現方式上略有不同。
(1)定義鏈表的基本結構
typedef struct _LINK_NODE{struct _LINK_NODE* prev;struct _LINK_NODE* next;}LINK_NODE;
(2)定義鏈表的基本操作
void link_init(struct _LINK_NODE* pNode){ASSERT(NULL != pNode);pNode->prev = NULL;pNode->next = NULL;}void link_add(struct _LINK_NODE* pNode, struct _LINK_NODE* head){ASSERT(NULL != pNode && NULL != head);pNode->next = head->next;pNode->prev = head;head->next = pNode;if(pNode->next)pNode->next->prev = pNode;}void link_del(struct _LINK_NODE* pNode){ASSERT(NULL != pNode);pNode->prev->next = pNode->next;if(pNode->next)pNode->next->prev = pNode->prev;}
這裡定義了鏈表的三個基本操作,即初始化、添加和刪除。我們在這裡設計的時候,為了說明方便,考慮的情況比較簡單。這裡編寫的代碼其實是有三個基本前提的:鏈表存在一個head節點,這個節點永遠不刪除;鏈表添加的資料都是放在head後面的;鏈表雖然是雙向鏈表,但本身並不是迴圈鏈表。
(3)在資料中嵌套使用LINK_NODE
typedef struct _DATA_TYPE{LINK_NODE head;int value;}DATA_TYPE;
這裡定義了一個簡單的資料類型,即為DATA_TYPE。可是,我們記得前面定義的操作都是 關於 LINK_NODE的,那麼我們如何才能利用LINK_NODE資料本身訪問到DATA_TYPE資料本身呢?其實不難,轉化一下資料即可。
(4)利用pNode訪問pData
現在假設存在這樣的一個節點pNode,它的地址就是在DATA_TYPE中head的地址,那麼怎麼才能進行轉化呢?我們看看下面的代碼是怎麼做的?大家也可以自己在編譯器上試一試?
#define GET_DATA_ADDRESS(pNode, DATA, head) \(DATA*)((char*)(pNode) - (&((DATA*)(0))->head))
這是一個宏,如果需要實際運算的話,應該這麼做。
DATA_TYPE* pData = GET_DATA_ADDRESS(pNode, DATA_TYPE, head);
這中間其實存在一個技巧。那就是我們既然知道pNode的地址,那麼只需要知道pNode和pData之間的位移值就可以了。兩者相減一下,獲得值就是pData的數值,所以,這裡可以利用(&((DATA*)(0))->head)擷取這個位移值,就是這麼簡單。
(5)利用pNode遍曆pData
因為這裡的pNode是一個鏈表,所以利用pNode遍曆pData就十分方便了。根據上面開發的思路,我們這裡依然可以利用宏的方法實現pData和pNode之間的自動轉換。
#define FOR_EACH_DATA(pNode, pData, DATA, head) \for(; \ pNode && (pData = GET_DATA_ADDRESS(pNode, DATA, head));\pNode = pNode->next)
使用的話依然十分簡單,簡單輸入資料和資料結構類型即可,
FOR_EACH_DATA(pNode, pData, DATA_TYPE, head){printf("pData->value = %d\n", pData->value);}
(6)其他
通常為了使用方便,鏈表還會引申出更多的功能,比如自訂head節點,添加list的統計函數,或者是修改添加的方式、刪除的方式等等。這些功能朋友們自己根據需要可以獨立完成。當然,如果大家的思維再發散一下,也可以把這種方法推廣到二叉樹、平衡二叉樹或者是紅/黑樹狀結構上面。總之一句話,鏈表是我們在編程中使用得最多地一種技巧方法,希望朋友們可以多多掌握。