雙鏈表:插入節點時和刪除節點時注意位置為0的節點。
圖:
繼承關系圖:
CircularList.h

/* * CirularList: 循環鏈表模板 * 成員變量: * * 成員函數: * last_to_first() 連接首尾節點 * bool insert(int pos,const T& obj) 插入節點 * bool remove(int pos) 刪除下標為pos的節點。分三步:頭節點與1節點,尾節點與1節點,刪除0節點 * bool set(int pos, const T& obj) * bool get(int pos, T& obj) const * int find(const T& obj) const * void clean() * * * */ #ifndef CIRCULARLIST_H #define CIRCULARLIST_H #include"LinkList.h" namespace DSL { template <typename T> class CircularList : public LinkList<T> { protected: typedef typename LinkList<T>::Node Node; void last_to_first() { Node* current = reinterpret_cast<Node*>(&this->m_header); for(int i = 0; i < this->m_length; i++) { current = current->next; } current->next = this->m_header.next; } public: bool insert(const T & obj) // 默認插入尾部 { return (this->insert(this->m_length,obj)); } bool insert(int pos, const T & obj) { bool ret = 1; pos = pos % (this->m_length + 1); if(pos == 0) // 插入鏈表頭部 { ret = LinkList<T>::insert(pos,obj); last_to_first(); } else // 插入鏈表中部 { ret = LinkList<T>::insert(pos,obj); } return ret; } bool remove(int pos) { bool ret = 1; pos = (this->m_length == 0 ? 0 : (pos % this->m_length)); if(pos == 0) // 刪除0節點 { Node* toDel = this->m_header.next; if(this->m_length > 0) // 節點0存在 { this->m_header.next = toDel->next; this->m_length--; if(this->m_length > 0) // 刪除0節點后下個節點存在 { last_to_first(); if(this->m_current == toDel) { this->m_current = toDel->next; } } else { this->m_header.next == NULL; this->m_current = NULL; } this->destroy(toDel); } else { this->m_header.next == NULL; this->m_current = NULL; } } else // 刪除中間節點 { ret = LinkList<T>::remove(pos); } return ret; } bool set(int pos, const T& obj) { pos = (this->m_length == 0 ? 0 : (pos % this->m_length)); return LinkList<T>::set(pos,obj); } T get(int pos) { pos = (this->m_length == 0 ? 0 : (pos % this->m_length)); return LinkList<T>::get(pos); } bool get(int pos, T& obj) const { pos = (this->m_length == 0 ? 0 : (pos % this->m_length)); return LinkList<T>::get(pos,obj); } int find(const T& obj) const { int ret = -1; Node* slider = this->m_header.next; for(int i = 0; i < this->m_length; i++) { if(slider->value == obj) { ret = i; break; } slider = slider->next; } } void clean() { for(int i = this->m_length; i > 0; i--) { if( this->m_length > 1) // 刪除中間節點 { remove(1); } else // 刪除頭節點 { Node* toDel = this->m_header.next; this->m_header.next = NULL; this->m_current = NULL; this->m_length = 0; this->destroy(toDel); } } } bool move(int pos) { pos = (this->m_length == 0 ? 0 : (pos % this->m_length)); return LinkList<T>::move(pos); } bool end() { return ((this->m_length == 0) || (this->m_current == NULL)); } ~CircularList() { clean(); } }; } /* 約瑟夫環 num: 總人數 start: 報數起始位置 step: 報數個數 void Josephus(int num, int start, int step) { CircularList<int> cl; for(int i = 1; i <= num; i++) { cl.insert(i); } cl.move(start - 1); // 循環鏈表下標從0開始 while(cl.length() > 0) { cl.next(step - 1); cout << cl.current() << endl; cl.remove(cl.find(cl.current())); } } */ #endif
移植Linux內核的鏈表,/include/linux/List.h
LinuxList.h

/* * LinuxList.h: 移植Linux4.9的雙向循環鏈表/include/linux/list.h,兼容g++/gcc編譯器。 * * 接口函數: * list_head: 鏈表節點,通過內嵌到其他數據結構使用。(頭節點的數據域並未使用) * * INIT_LIST_HEAD: 初始化鏈表頭,將鏈表頭的next,prev指針都指向自己,此狀態表示鏈表為空 * list_add: 鏈表頭節點和第二個節點中間插入 * list_add_tail: 鏈表頭節點和尾節點中間插入 * list_del: 刪除節點,刪除當前傳入的節點 * list_empty: 鏈表是否為空,頭節點的next和prev指針指向自己則為空。 * list_for_each_entry: 頭節點開始,正向遍歷鏈表 * list_for_each_entry_reverse: 頭節點開始,逆向遍歷鏈表 * * contain_of 通過結構體成員指針,結構體成員名,結構體類型獲取 結構體首地址 * list_entry 通過父級結構體的內嵌成員list_head的成員指針,成員名,結構體類型獲取 父級結構體的首地址 */ #ifndef LINUXLIST_H #define LINUXLIST_H struct list_head { struct list_head *next, *prev; }; #define LIST_HEAD_INIT(name) { &(name), &(name) } #define LIST_HEAD(name) (struct list_head name = LIST_HEAD_INIT(name)) /* params: * list_head 頭父級數據結構的鏈表節點 */ static void INIT_LIST_HEAD(struct list_head *list) { list->next = list->prev = list; } static void __list_add(struct list_head *entry, struct list_head *prev, struct list_head *next) { next->prev = entry; entry->next = next; entry->prev = prev; prev->next = entry; } /* params: * entry 內嵌到父級數據結構的鏈表節點 * head 頭父級數據結構中的鏈表節點 */ static void list_add(struct list_head *entry, struct list_head *head) { __list_add(entry, head, head->next); } static void list_add_tail(struct list_head *entry, struct list_head *head) { __list_add(entry, head->prev, head); } static void __list_del(struct list_head *prev, struct list_head *next) { next->prev = prev; prev->next = next; } /* params: * 要刪除父級數據結構中的鏈表頭 */ static void list_del(struct list_head *entry) { __list_del(entry->prev, entry->next); } static void list_del_init(struct list_head *entry) { __list_del(entry->prev, entry->next); INIT_LIST_HEAD(entry); } static void list_move_tail(struct list_head *list, struct list_head *head) { __list_del(list->prev, list->next); list_add_tail(list, head); } #ifdef __cplusplus // C語言沒有bool類型 static bool list_empty(struct list_head *head) { return head->next == head; } #else static int list_empty(struct list_head *head) { return head->next == head; } #endif #ifndef container_of #define container_of(ptr, type, member) (type *)((char *)(ptr) - (char *)&((type *)0)->member) #endif #define list_entry(ptr, type, member) container_of(ptr, type, member) #define list_first_entry(ptr, type, member) list_entry((ptr)->next, type, member) #define list_last_entry(ptr, type, member) list_entry((ptr)->prev, type, member) #ifdef __cplusplus // C++類型檢查要強一些 #define __container_of(ptr, sample, member) container_of((ptr), typeof(*(sample)), member) #else #define __container_of(ptr, sample, member) (void *)container_of((ptr), typeof(*(sample)), member) #endif /* params: * pos 用作游標的父級數據結構 * head 頭父級數據結構的鏈表節點(鏈表頭) * member 父級數據結構中定義的list_head的變量名 */ #define list_for_each_entry(pos, head, member) \ for (pos = __container_of((head)->next, pos, member); \ &pos->member != (head); \ pos = __container_of(pos->member.next, pos, member)) #define list_for_each_entry_safe(pos, tmp, head, member) \ for (pos = __container_of((head)->next, pos, member), \ tmp = __container_of(pos->member.next, pos, member); \ &pos->member != (head); \ pos = tmp, tmp = __container_of(pos->member.next, tmp, member)) #define list_for_each_entry_reverse(pos, head, member) \ for (pos = __container_of((head)->prev, pos, member); \ &pos->member != (head); \ pos = __container_of(pos->member.prev, pos, member)) #define list_for_each_entry_continue(pos, head, member) \ for (pos = __container_of(pos->member.next, pos, member); \ &pos->member != (head); \ pos = __container_of(pos->member.next, pos, member)) #define list_for_each_entry_continue_reverse(pos, head, member) \ for (pos = __container_of(pos->member.prev, pos, member); \ &pos->member != (head); \ pos = __container_of(pos->member.prev, pos, member)) #define list_for_each_entry_from(pos, head, member) \ for (; \ &pos->member != (head); \ pos = __container_of(pos->member.next, pos, member)) #endif /* TEST main.cpp: #include<iostream> #include"LinuxList.h" #include<cstdio> using namespace std; int main(void) { struct Node { int value; struct list_head head; }; Node *m_list = (Node *)malloc(sizeof(Node)); struct list_head *m_head = &m_list->head; Node *m_slider = NULL; // 游標 INIT_LIST_HEAD(m_head); for(int i=0; i<10; i++) { Node *temp_node = (Node *)malloc(sizeof(Node)); temp_node->value = i; list_add_tail(&temp_node->head, m_head); cout << temp_node->value << endl; } list_for_each_entry(m_slider, m_head, head) { int i = m_slider->value; cout << i << endl; } return 0; } */
內核鏈表真的厲害,同一個簡單的代碼包含了所有情況下的插入,刪除,可能這就是真正的代碼復用吧,而不是語法糖。