myList.h
#ifndef MYLIST_H_INCLUDED #define MYLIST_H_INCLUDED /* 仿照linux的链表操作的实现 */ #undef NULL #ifdef __cplusplus #define NULL 0 #else #define NULL ((void *)0) #endif struct list_head { struct list_head *next; struct list_head *prev; }; #define LIST_HEAD_INIT(name) { &(name), &(name) } #define LIST_HEAD(name) \ struct list_head name = LIST_HEAD_INIT(name) //在(TYPE*)结构体中找到(MEMBER)成员的位置 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) //找到type的开始位置 #define list_entry(ptr, type, member) \ (type *)((char *)ptr - offsetof(type,member)) //向后遍历链表。pos为当前位置,head为开始位置 #define list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next) #define list_for_each_safe(pos, n, head) \ for (pos = (head)->next, n = pos->next; pos != (head); pos = n, n = pos->next) //向前遍历链表。pos为当前位置,head为开始位置 #define list_for_each_prev(pos, head) \ for (pos = (head)->prev; pos != (head); pos = pos->prev) #define list_for_each_prev_safe(pos, n, head) \ for (pos = (head)->prev, n = pos->prev; pos != (head); pos = n, n = pos->prev) //??? #define list_first_entry(ptr, type, member) \ list_entry((ptr)->next, type, member) //初始化链表(链表头) static inline void INIT_LIST_HEAD(struct list_head *list) { list->next = list; list->prev = list; } //添加一个节点到链表中的基本操作 static inline void __list_add(struct list_head *new, struct list_head *prev, struct list_head *next) { next->prev = new; new->next = next; new->prev = prev; prev->next = new; } //在链表头之后增加一个新节点。如1->2->3,增加4之后为1->4->2->3 static inline void list_add(struct list_head *new, struct list_head *head) { __list_add(new, head, head->next); } //在链表的尾部增加一个新节点,如1->2->3,增加4之后为1->2->3->4 static inline void list_add_tail(struct list_head *new, struct list_head *head) { __list_add(new, head->prev, head); } //删除一个链表中的节点,基本操作 static inline void __list_del(struct list_head * prev, struct list_head * next) { next->prev = prev; prev->next = next; } //删除一个链表中的节点,*entry为从链表找中摘除的节点,如果有内存申请则需要手动释放 static inline void list_del(struct list_head *entry) { __list_del(entry->prev, entry->next); entry->next = NULL; entry->prev = NULL; } //删除一个链表中的节点并把删除的节点初始化,*entry为从链表找中摘除的节点,如果有内存申请则需要手动释放 static inline void list_del_init(struct list_head *entry) { __list_del(entry->prev, entry->next); INIT_LIST_HEAD(entry); } //使用new替换链表中的old static inline void list_replace(struct list_head *old, struct list_head *new) { new->next = old->next; new->next->prev = new; new->prev = old->prev; new->prev->next = new; } //使用new替换链表中的old并且把old初始化,如果old是链表头则相当于清空链表 static inline void list_replace_init(struct list_head *old, struct list_head *new) { list_replace(old, new); INIT_LIST_HEAD(old); } //将list从链表中取出,然后移动到head的之后的位置。如果head是链表头则是移动到链表的第一个位置 static inline void list_move(struct list_head *list, struct list_head *head) { __list_del(list->prev, list->next); list_add(list, head); } //将list从链表中取出,然后移动到head的最后一个位置。如果head是链表头则是移动到链表的尾部 static inline void list_move_tail(struct list_head *list, struct list_head *head) { __list_del(list->prev, list->next); list_add_tail(list, head); } //判断链表是否为空 static inline int list_empty(const struct list_head *head) { return head->next == head; } //判断链表是否为空。条件更加充足 static inline int list_empty_careful(const struct list_head *head) { struct list_head *next = head->next; return (next == head) && (next == head->prev); } /*******************************不常用的操作*********************************/ //判断list是否为链表最后一个节点 static inline int list_is_last(const struct list_head *list, const struct list_head *head) { return list->next == head; } //判断链表中是否只有一个节点 static inline int list_is_singular(const struct list_head *head) { return !list_empty(head) && (head->next == head->prev); } //将一个链表拆分为两条链表的基本操作 static inline void __list_cut_position(struct list_head *list, struct list_head *head, struct list_head *entry) { struct list_head *new_first = entry->next; list->next = head->next; list->next->prev = list; list->prev = entry; entry->next = list; head->next = new_first; new_first->prev = head; } /* 将一个链表拆分成两条 *list为拆分后的新链表的头,*head为被拆分链表的头,*entry为拆分位置 拆分后list->next = entry, head->next = entry->next 既是entry后面的节点被加到list的后面,原链表保留entry之前的节点 head->1->2->3->10->20->30,entry->10.拆分后:head->10->20->30, list->1->2->3 */ static inline void list_cut_position(struct list_head *list, struct list_head *head, struct list_head *entry) { if (list_empty(head)) return; if (list_is_singular(head) && (head->next != entry && head != entry)) return; if (entry == head) INIT_LIST_HEAD(list); else __list_cut_position(list, head, entry); } //合并两条聊表的基本操作 static inline void __list_splice(const struct list_head *list, struct list_head *prev, struct list_head *next) { struct list_head *first = list->next; struct list_head *last = list->prev; first->prev = prev; prev->next = first; last->next = next; next->prev = last; } /* 合并两条链表 将list链表加入到head的后面 list->1->2->3,head->10->20->30。合并后:head->1->2->3->10->20->30 */ static inline void list_splice(const struct list_head *list, struct list_head *head) { if (!list_empty(list)) __list_splice(list, head, head->next); } /* 合并两条链表 将list链表加入到head的后面,list为必须为链表头,合并后将其初始化 list->1->2->3,head->10->20->30。合并后:head->1->2->3->10->20->30 */ static inline void list_splice_init(struct list_head *list, struct list_head *head) { if (!list_empty(list)) { __list_splice(list, head, head->next); INIT_LIST_HEAD(list); } } /* 合并两条链表 将list链表加入到head的链表尾部 list->1->2->3,head->10->20->30。合并后:head->10->20->30->1->2->3 */ static inline void list_splice_tail(struct list_head *list, struct list_head *head) { if (!list_empty(list)) __list_splice(list, head->prev, head); } /* 合并两条链表 将list链表加入到head的链表尾部。list必须是头节点,合并后初始化list list->1->2->3,head->10->20->30。合并后:head->10->20->30->1->2->3 */ static inline void list_splice_tail_init(struct list_head *list, struct list_head *head) { if (!list_empty(list)) { __list_splice(list, head->prev, head); INIT_LIST_HEAD(list); } } #endif // MYLIST_H_INCLUDED
main.c
#include#include #include "myList.h" #include "memory.h" #define RETURN_OK 0 #define RETURN_ERROR -1 //结构体的定义需要放在头文件中,此处做了简便处理 typedef struct tag_myList { int data; struct list_head stListNode; //该指针一般放在结构体定义的开头 }myList; struct list_head g_stListHead; //全局变量,作为链表的头 //申请一个节点 myList* newNode() { myList *pstTemp = NULL; //为节点申请内存 pstTemp = (myList*)malloc(sizeof(myList)); if (NULL == pstTemp) { return NULL; } INIT_LIST_HEAD(&(pstTemp->stListNode)); pstTemp->data = 0; return pstTemp; } int main() { int i; struct list_head stTempHead; //作为拆分或者合并的链表的头节点 struct list_head *pstEntry = NULL; myList* pstTemp = NULL; struct list_head *pos = NULL; struct list_head *n = NULL; //初始化 INIT_LIST_HEAD(&g_stListHead); INIT_LIST_HEAD(&stTempHead); for (i = 0; i < 5; i++) { pstTemp = newNode(); if (NULL == pstTemp) { exit(0); //内存申请失败则退出,简单的处理 } pstTemp->data = i; //将节点加入链表头部 list_add(&pstTemp->stListNode, &g_stListHead); } for (i = 5; i < 10; i++) { pstTemp = newNode(); if (NULL == pstTemp) { exit(0); //内存申请失败则退出,简单的处理 } pstTemp->data = i; //将节点加入链表尾部 list_add_tail(&pstTemp->stListNode, &g_stListHead); } //遍历链表 list_for_each(pos, &g_stListHead) { //通过偏移找到结构体开始的位置,list_entry已经将偏移后的指针强制转换为该结构体 pstTemp = list_entry(pos, myList, stListNode); printf("%d\t", pstTemp->data); if (0 == pstTemp->data) { pstEntry = &pstTemp->stListNode; //将0所在的位置作为拆分或者合并的节点位置 } } printf("\n"); list_cut_position(&stTempHead, &g_stListHead, pstEntry); printf("cut node after g_stListHead:"); list_for_each(pos, &g_stListHead) { //通过偏移找到结构体开始的位置,list_entry已经将偏移后的指针强制转换为该结构体 pstTemp = list_entry(pos, myList, stListNode); printf("%d\t", pstTemp->data); } printf("\n"); printf("cut node after stTempHead:"); list_for_each(pos, &stTempHead) { //通过偏移找到结构体开始的位置,list_entry已经将偏移后的指针强制转换为该结构体 pstTemp = list_entry(pos, myList, stListNode); printf("%d\t", pstTemp->data); } printf("\n"); list_splice_init(&g_stListHead, &stTempHead); //list_splice在遍历的时候就会有问题 printf("splice node after stTempHead:\t"); list_for_each(pos, &stTempHead) { //通过偏移找到结构体开始的位置,list_entry已经将偏移后的指针强制转换为该结构体 pstTemp = list_entry(pos, myList, stListNode); printf("%d\t", pstTemp->data); } printf("\n"); printf("splice node after g_stListHead:\t"); list_for_each(pos, &g_stListHead) { //通过偏移找到结构体开始的位置,list_entry已经将偏移后的指针强制转换为该结构体 pstTemp = list_entry(pos, myList, stListNode); printf("%d\t", pstTemp->data); } return 0; }