循环单链表(链表)
双链表:插入节点时和删除节点时注意位置为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; } */
内核链表真的厉害,同一个简单的代码包含了所有情况下的插入,删除,可能这就是真正的代码复用吧,而不是语法糖。