数据结构2.(双向链表,循环链表及内核链表)
1.双向链表
1.1双向链表的节点定义
//节点存放数据的类型 typedef int datatype;/* 节点类型 */typedef struct node
{datatype data; //存放数据空间
struct node *ppre; //存放前一个节点地址
struct node *pnext; //存放下一个节点地址
}linknode;
1.2双向链表的创建
申请节点空间,对pnext和ppre赋值为NULL, 返回空白节点地址。
linknode *create_empty_linklist(void){linknode *ptmpnode = NULL;ptmpnode = malloc(sizeof(linknode));if (NULL == ptmpnode){perror("fail to malloc");return NULL;}ptmpnode->ppre = NULL;ptmpnode->pnext = NULL;return ptmpnode;}
1.3双向链表头插法
1)申请节点
2)存放数据
3)pnext赋值为phead->pnext
4)ppre赋值为phead的地址
5)phead->pnext赋值为新申请节点地址
6)如果有后一个节点,需要让后一个节点的ppre指向该节点
//双向链表头插
void insert_head_linklist(linknode *phead, datatype tmpdata)
{ linknode *ptmpnode = NULL;ptmpnode = malloc(sizeof(linknode));if (NULL == ptmpnode){perror("fail to malloc");return;}ptmpnode->data = tmpdata;ptmpnode->pnext = phead->pnext;ptmpnode->ppre = phead;phead->pnext = ptmpnode;if (ptmpnode->pnext != NULL){ptmpnode->pnext->ppre = ptmpnode;}return;
}
1.4双向链表的销毁
与单向链表相同
void destroy_linklist(linknode **pphead)//销毁需要传递二级指针,因为要将外部指针指向空
{linknode *pfreenode = NULL;linknode *ptmpnode = NULL;ptmpnode = *pphead;pfreenode = *pphead;while(ptmpnode != NULL){ptmpnode = ptmpnode->pnext;free(pfreenode);pfreenode = ptmpnode;}*pphead = NULL;
}
1.5双向链表的遍历
与单向链表无异
void show_linklist(linknode *phead){linknode *ptmpnode = NULL;ptmpnode = phead->pnext;while (ptmpnode != NULL)//判断下一个节点是不是空{printf("%d ", ptmpnode->data);ptmpnode = ptmpnode->pnext;}printf("\n");return;}
1.6双向链表的查找
与单向链表相同
//数返回链表中第一个指定元素节点的地址void find_linklist(linknode *phead, datatype tmpdata){linknode *ptmpnode = NULL;linknode *pprenode = NULL;pprenode = phead;ptmpnode = pprenode->pnext;while (ptmpnode != NULL){if (ptmpnode->data == tmpdata){printf("%p\n",&pprenode->pnext);break;}else{ptmpnode = ptmpnode->pnext;pprenode = pprenode->pnext;}}return;}
1.7双向链表的修改
与双向链表一致
//将链表中指定元素的值更新为新值void update_linklist(linknode *phead, datatype olddata, datatype newdata){linknode *ptmpnode = NULL;ptmpnode = phead;while (ptmpnode != NULL){if (ptmpnode->data == olddata){ptmpnode->data = newdata;}ptmpnode = ptmpnode->pnext;}return;}
1.8双向链表的删除
//删除链表中所有的某一指定元素
void delete_linklist(linknode *phead, datatype tmpdata)
{linknode *ptmpnode = NULL;linknode *pfreenode;ptmpnode = phead->pnext;while (ptmpnode != NULL){if (ptmpnode->data == tmpdata){ptmpnode->ppre->pnext = ptmpnode->pnext;if(ptmpnode->pnext!=NULL){ptmpnode->pnext->ppre=ptmpnode->ppre;}pfreenode = ptmpnode;ptmpnode = ptmpnode->pnext;free(pfreenode);}else {ptmpnode = ptmpnode->pnext;}}return;
}
1.9双向链表的尾插法
1)申请节点
2)将节点的pnext赋值为NULL
3)找到链表最后一个节点
4)将节点的ppre赋值为最后一个节点地址
5)将最后一个节点的pnext赋值为新申请节点
int insert_tail_linklist(linknode *phead, datatype tmpdata)
{linknode *ptmpnode = NULL;linknode *plastnode = NULL;ptmpnode = malloc(sizeof(linknode));if (NULL == ptmpnode){perror("fail to malloc");return -1;}plastnode = phead;while (plastnode->pnext != NULL){plastnode = plastnode->pnext;}ptmpnode->data = tmpdata;ptmpnode->pnext = NULL;ptmpnode->ppre = plastnode;plastnode->pnext = ptmpnode;return 0;
}
2.循环链表
2.1循环链表的创建
// 创建空链表
linknode *create_empty_linklist(void)
{linknode *ptmpnode = NULL;ptmpnode = malloc(sizeof(linknode));if (NULL == ptmpnode){perror("fail to malloc");return NULL;}ptmpnode->pnext = ptmpnode->ppre = ptmpnode;return ptmpnode;
}
2.2循环链表头插法
原理图解:
//头插法
void insert_head_linklist(linknode *phead, datatype tmpdata)
{linknode *ptmpnode = NULL;ptmpnode = malloc(sizeof(linknode));//申请节点if (NULL == ptmpnode){perror("fail to malloc");return;}ptmpnode->data = tmpdata;//存放数据ptmpnode->pnext = phead->pnext;ptmpnode->ppre = phead;phead->pnext = ptmpnode;ptmpnode->pnext->ppre = ptmpnode;return;
}
2.3循环链表尾插法
原理图解:
//尾插法
void insert_tail_linklist(linknode *phead, datatype tmpdata)
{linknode *ptmpnode = NULL;ptmpnode = malloc(sizeof(linknode));if (NULL == ptmpnode){perror("fail to malloc");return;}ptmpnode->data = tmpdata;ptmpnode->pnext = phead;ptmpnode->ppre = phead->ppre;phead->ppre->pnext = ptmpnode;phead->ppre = ptmpnode;return;
}
2.4循环链表的遍历
与单向和双向链表不同,其ptmpnod在所有需要遍历的使用场景中,其判定条件均由(ptmpnode!=null)变为了(ptmpnode != phead);
void show_linklist(linknode *phead)
{linknode *ptmpnode = NULL;ptmpnode = phead->pnext;while (ptmpnode != phead){printf("%d ", ptmpnode->data);ptmpnode = ptmpnode->pnext;}printf("\n");return;
}
2.5循环链表元素的查找
与单向链表相同,仅循环判断条件改变
// 链表的查找
linknode *find_linklist(linknode *phead, datatype tmpdata)
{linknode *ptmpnode = NULL;ptmpnode = phead->pnext;while (ptmpnode != phead){if (ptmpnode->data == tmpdata){return ptmpnode;}ptmpnode = ptmpnode->pnext;}return NULL;
}
2.6循环链表元素修改
与单向链表相同,仅循环判断条件改变
// 链表的修改
int update_linklist(linknode *phead, datatype olddata, datatype newdata)
{linknode *ptmpnode = NULL;ptmpnode = phead->pnext;while (ptmpnode != phead){if (ptmpnode->data == olddata){ptmpnode->data = newdata;}ptmpnode = ptmpnode->pnext;}return 0;
}
2.7循环链表元素的删除
与单向链表相同,仅循环判断条件改变
// 链表节点的删除
int delete_linklist(linknode *phead, datatype tmpdata)
{linknode *ptmpnode = NULL;linknode *pfreenode = NULL;ptmpnode = phead->pnext;while (ptmpnode != phead){if (ptmpnode->data == tmpdata){ptmpnode->ppre->pnext = ptmpnode->pnext;ptmpnode->pnext->ppre = ptmpnode->ppre;pfreenode = ptmpnode;ptmpnode = ptmpnode->pnext;free(pfreenode);}else{ptmpnode = ptmpnode->pnext;}}return 0;
}
2.8循环链表的销毁
与单向链表相同,仅循环判断条件改变
// 链表的销毁
int destroy_linklist(linknode **pphead)
{linknode *ptmpnode = NULL;linknode *pfreenode = NULL;ptmpnode = (*pphead)->pnext;pfreenode = ptmpnode;while (ptmpnode != *pphead){ptmpnode = ptmpnode->pnext;free(pfreenode);pfreenode = ptmpnode;}free(*pphead);*pphead = NULL;return 0;
}
3.内核链表
参考list.h中关于内核链表的常见操作:
/**/Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>This file is part of GlusterFS.This file is licensed to you under your choice of the GNU LesserGeneral Public License, version 3 or any later version (LGPLv3 orlater), or the GNU General Public License, version 2 (GPLv2), in allcases as published by the Free Software Foundation.#ifndef _LLIST_H#define _LLIST_H/* 内核链表中的节点类型 */struct list_head {struct list_head *next;struct list_head *prev;};/* 初始化空白头结点 */#define INIT_LIST_HEAD(head) do {
\(head)->next = (head)->prev = head; \} while (0)/* 头插法 */static inline voidlist_add (struct list_head *new, struct list_head *head){new->prev = head;new->next = head->next;new->prev->next = new;new->next->prev = new;
}/* 尾插法 */static inline voidlist_add_tail (struct list_head *new, struct list_head *head){new->next = head;new->prev = head->prev;new->prev->next = new;new->next->prev = new;}/* 按指定顺序插入 *//* This function will insert the element to the list in a order.Order will be based on the compare function provided as a input.If element to be inserted in ascending order compare should return:0: if both the arguments are equal>0: if first argument is greater than second argument<0: if first argument is less than second argument */static inline voidlist_add_order (struct list_head *new, struct list_head *head,int (*compare)(struct list_head *, struct list_head *)){struct list_head *pos = head->prev;while ( pos != head ) {if (compare(new, pos) >= 0)break;/* Iterate the list in the reverse order. This will
havebetter efficiency if the elements are inserted in
theascending order */pos = pos->prev;}list_add (new, pos);}/* 将节点移出所属的链表 */static inline voidlist_del (struct list_head *old){old->prev->next = old->next;old->next->prev = old->prev;old->next = (void *)0xbabebabe;old->prev = (void *)0xcafecafe;}/* 将节点移出所属的链表,并初始化 */static inline voidlist_del_init (struct list_head *old){343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687old->prev->next = old->next;old->next->prev = old->prev;old->next = old;old->prev = old;}/* 将节点移动到另一个链表的头部 */static inline voidlist_move (struct list_head *list, struct list_head *head){list_del (list);list_add (list, head);}/* 将节点移动到另一个链表的尾部 */static inline voidlist_move_tail (struct list_head *list, struct list_head *head){list_del (list);list_add_tail (list, head);}/* 判断链表是否为空 */static inline intlist_empty (struct list_head *head){return (head->next == head);}/* 将list链表所有元素拼到head链表的前面 */static inline void__list_splice (struct list_head *list, struct list_head *head){(list->prev)->next = (head->next);(head->next)->prev = (list->prev);(head)->next = (list->next);(list->next)->prev = (head);}/* 将list链表所有元素拼到head链表的前面 */static inline voidlist_splice (struct list_head *list, struct list_head *head){if (list_empty (list))return;__list_splice (list, head);}/* 将list链表所有元素拼到head链表的前面,并初始化list头结点 *//* Splice moves @list to the head of the list at @head. */static inline voidlist_splice_init (struct list_head *list, struct list_head *head){888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143if (list_empty (list))return;__list_splice (list, head);INIT_LIST_HEAD (list);}/* 将list链表所有元素追加到head链表的后面 */static inline void__list_append (struct list_head *list, struct list_head *head){(head->prev)->next = (list->next);(list->next)->prev = (head->prev);(head->prev) = (list->prev);(list->prev)->next = head;}/* 将list链表所有元素追加到head链表的后面 */static inline voidlist_append (struct list_head *list, struct list_head *head){if (list_empty (list))return;__list_append (list, head);}/* 将list链表所有元素追加到head链表的后面,并初始化list *//* Append moves @list to the end of @head */static inline voidlist_append_init (struct list_head *list, struct list_head *head){if (list_empty (list))return;__list_append (list, head);INIT_LIST_HEAD (list);}/* 判断当前节点是否为最后一个节点 */static inline intlist_is_last (struct list_head *list, struct list_head *head){return (list->next == head);}/* 判断链表是否只有一个节点 */static inline intlist_is_singular(struct list_head *head){return !list_empty(head) && (head->next == head->prev);}/* 将旧节点用新节点替换 *//*** list_replace - replace old entry by new one144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199* @old : the element to be replaced* @new : the new element to insert** If @old was empty, it will be overwritten.*/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;}/* 将旧节点用新节点替换,并初始化旧节点 */static inline void list_replace_init(struct list_head *old,struct list_head *new){list_replace(old, new);INIT_LIST_HEAD(old);}/* 内核链表左旋 *//*** list_rotate_left - rotate the list to the left* @head: the head of the list*/static inline void list_rotate_left (struct list_head *head){struct list_head *first;if (!list_empty (head)) {first = head->next;list_move_tail (first, head);}}/* 根据链表节点地址找到数据元素首地址 */#define list_entry(ptr, type, member) \((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->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)/* 找到下一个数据元素地址 */#define list_next_entry(pos, member) \list_entry((pos)->member.next, typeof(*(pos)), member)/* 找到上一个数据元素地址 */#define list_prev_entry(pos, member) \list_entry((pos)->member.prev, typeof(*(pos)), member)200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
/* 遍历链表节点元素地址 */#define list_for_each(pos, head)
\for (pos = (head)->next; pos != (head); pos = pos->next)/* 遍历所有数据元素首地址 */#define list_for_each_entry(pos, head, member) \for (pos = list_entry((head)->next, typeof(*pos), member); \&pos->member != (head); \pos = list_entry(pos->member.next, typeof(*pos), member))/* 遍历所有数据元素首地址(可以在遍历过程中修改数据元素指针) */#define list_for_each_entry_safe(pos, n, head, member) \for (pos = list_entry((head)->next, typeof(*pos), member), \n = list_entry(pos->member.next, typeof(*pos), member); \&pos->member != (head); \pos = n, n = list_entry(n->member.next, typeof(*n), member))/* 倒着遍历所有数据元素首地址 */#define list_for_each_entry_reverse(pos, head, member)
\for (pos = list_entry((head)->prev, typeof(*pos), member); \&pos->member != (head); \pos = list_entry(pos->member.prev, typeof(*pos), member))/* 倒着遍历所有数据元素首地址(可以在遍历过程中修改数据元素指针) */#define list_for_each_entry_safe_reverse(pos, n, head, member)
\for (pos = list_entry((head)->prev, typeof(*pos), member), \n = list_entry(pos->member.prev, typeof(*pos), member); \&pos->member != (head); \pos = n, n = list_entry(n->member.prev, typeof(*n), member))/** This list implementation has some advantages, but one disadvantage:
you* can't use NULL to check whether you're at the head or tail. Thus,
the* address of the head has to be an argument for these macros.*//* 获得下一个数据元素空间首地址,如果没有返回NULL */#define list_next(ptr, head, type, member) \(((ptr)->member.next == head) ? NULL \: list_entry((ptr)->member.next, type,
member))/* 获得上一个数据元素空间首地址,如果没有返回NULL */#define list_prev(ptr, head, type, member) \(((ptr)->member.prev == head) ? NULL \: list_entry((ptr)->member.prev, type,
member))#endif /* _LLIST_H */