数据结构之双端(通用)链表的实现
2016-03-30 07:20
525 查看
从单链表可以了解到,若是要添加一个链表元素除第一个元素外其他都必须将链表遍历一遍才可以添加;当数据量比较大时向尾部添加元素就比较麻烦,于是就出现了双端链表; 双端链表和单链表相比多了一个指向尾节点的指针,对于进行尾部插入方便了很多;
以下是双端链表的实现:
双端链表的链表控制信息及其链表节点信息:
#ifndef _DLIST_H_ #define _DLIST_H_ #include "tools.h" #define TRUE (1) #define FALSE (0) #define ZERO (0) #define ONE (1) typedef void (*Print_func)(void *value); //回调函数 //链表节点类型 typedef struct Dlist_node{ struct Dlist_node *prev; //前驱 struct Dlist_node *next; //后继 void *data; //可以接收任意类型的指针(达到通用的效果) }Dlist_node; //链表控制信息 typedef struct Dlist{ struct Dlist_node *head; //头结点 struct Dlist_node *tail; //尾节点 int count; //数量 //data所指向内容的释放策略 void (*free)(void *ptr); //释放任意指针的空间(函数指针) //data所指向内容的相等策略 Boolean (*match)(void *value1, void *value2); //data所指向内容的拷贝策略 void *(*copy_node)(void *value); }Dlist;
双端链表的接口:
Dlist *init_dlist(void) ; //双端链表初始化 void destroy_dlist(Dlist **dlist) ; //双端链表的销毁 Boolean push_front(Dlist *dlist, void *value) ; //头部插入 Boolean push_back(Dlist *dlist, void *value) ; //尾部插入 Boolean pop_front(Dlist *dlist) ; //头部删除 Boolean pop_back(Dlist *dlist) ; //头部删除 Dlist_node *find_node(Dlist *dlist, void *value) ; Boolean insert_prev(Dlist *dlist, Dlist_node *node, void *value); //插入到指定节点前边 Boolean insert_next(Dlist *dlist, Dlist_node *node, void *value); //插入到指定节点后边 Boolean remove_dlist_node(Dlist *dlist, Dlist_node *node) ; //删除指定节点 void print_dlist(Dlist *dlist, Print_func print) ; //链表的打印 Boolean get_front(Dlist *dlist, void **value) ; //得到头结点的data Boolean get_tail(Dlist *dlist, void **value) ; //得到尾节点的data int get_dlist_count(Dlist *dlist) ; //得到链表的数量
双端链表的接口实现:
#include <stdio.h> #include <stdlib.h> #include <strings.h> #include "dlist.h" Dlist *init_dlist(void) //双端链表初始化 { Dlist *dlist = NULL; dlist = (Dlist *)Malloc(sizeof(Dlist)); bzero(dlist, sizeof(Dlist)); return dlist; } void destroy_dlist(Dlist **dlist) //双端链表的销毁 { Dlist_node *p_node = NULL; if(dlist == NULL || *dlist == NULL){ return ; } #if 0 p_node = (*dlist)->head; while((*dlist)->head != NULL){ (*dlist)->head = p_node->next; if((*dlist)->free != NULL){ (*dlist)->free(p_node->data); } free(p_node); p_node = (*dlist)->head; } #endif while((*dlist)->count){ pop_front(*dlist); } free(*dlist); *dlist = NULL; } static Dlist_node *create_node(void); //生成链表节点 static Dlist_node *create_node(void) { Dlist_node *result = NULL; result = (Dlist_node *)Malloc(sizeof(Dlist_node)); bzero(result, sizeof(Dlist_node)); return result; } Boolean push_front(Dlist *dlist, void *value) //头部插入 { //*value记录数据的地址 Dlist_node *p_node = NULL; if(dlist == NULL || value == NULL){ return FALSE; } //生成链表节点 p_node = create_node(); p_node->data = value; if(dlist->count == ZERO){ //插入前无元素 dlist->head = dlist->tail = p_node; }else{ //插入前有元素 p_node->next = dlist->head; dlist->head->prev = p_node; dlist->head = p_node; } dlist->count++; return TRUE; } Boolean push_back(Dlist *dlist, void *value) //尾部插入 { Dlist_node *p_node = NULL; if(dlist == NULL || value == NULL){ p_node->prev = dlist->tail; return FALSE; } p_node = create_node(); p_node->data = value; if(dlist->count == ZERO){ //插入前无元素 dlist->head = dlist->tail = p_node; }else{ //插入前有元素 dlist->tail->next = p_node; p_node->prev = dlist->tail; dlist->tail = p_node; } dlist->count++; return TRUE; } Boolean pop_front(Dlist *dlist) //头部删除 { Dlist_node *p_node = NULL; if(dlist == NULL || dlist->count == ZERO){ return FALSE; } p_node = dlist->head; if(dlist->count == ONE){ dlist->head = dlist->tail = NULL; }else{ dlist->head = p_node->next; dlist->head->prev = NULL; } //释放节点,要对free指针作判断(data指向为堆还是栈) if(dlist->free != NULL){ //堆上(才可用free函数) dlist->free(p_node->data); } free(p_node); //栈上 dlist->count--; return TRUE; } Boolean pop_back(Dlist *dlist) //头部删除 { Dlist_node *p_node = NULL; if(dlist == NULL || dlist->count == ZERO){ return FALSE; } p_node = dlist->tail; if(dlist->count == ONE){ //只有一个元素 dlist->head = dlist->tail = NULL; }else{ //多个元素 dlist->tail = p_node->prev; dlist->tail->next = NULL; } if(dlist->free != NULL){ dlist->free(p_node->data); } free(p_node); dlist->count--; return TRUE; } Dlist_node *find_node(Dlist *dlist, void *value) { Dlist_node *p_node = NULL; if(dlist == NULL || value == NULL){ return NULL; } #if 0 for(p_node = dlist->head; p_node; p_node = p_node->next){ if(dlist->match){ //用户指定相等条件 if(!dlist->match(p_node->data, value)){ return p_node; } }else{ if(p_node->data == value){ return p_node; } } } #endif if(dlist->match){ for(p_node = dlist->head; p_node; p_node = p_node->next){ if(!dlist->match(p_node->data, value)){ return p_node; } } }else{ for(p_node = dlist->head; p_node; p_node = p_node->next){ if(p_node->data == value){ return p_node; } } } return p_node; } Boolean insert_prev(Dlist *dlist, Dlist_node *node, void *value) //插入到指定节点前边 { Dlist_node *p_node = NULL; if(dlist == NULL || node == NULL || value == NULL){ return FALSE; } p_node = create_node(); p_node->data = value; p_node->next = node; p_node->prev = node->prev; if(node->prev == NULL){ dlist->head = p_node; }else{ node->prev->next = p_node; } node->prev = p_node; dlist->count++; return TRUE; } Boolean insert_next(Dlist *dlist, Dlist_node *node, void *value) //插入到指定节点后边 { Dlist_node *p_node = NULL; if(dlist == NULL || node == NULL || value == NULL){ return FALSE; } p_node = create_node(); p_node->data = value; p_node->prev = node; p_node->next = node->next; if(node->next == NULL){ dlist->tail = p_node; }else{ node->next->prev = p_node; } node->next = p_node; dlist->count++; return TRUE; } Boolean remove_dlist_node(Dlist *dlist, Dlist_node *node) //删除指定节点 { //被删除节点的位置1.头删2.尾删3.中间删 if(dlist == NULL || node == NULL ){ return FALSE; } if(node->next == NULL){ //尾删 pop_back(dlist); }else if(node->prev == NULL){ //头删 pop_front(dlist); }else{ //中间删 node->prev->next = node->next; node->next->prev = node->prev; if(dlist->free != NULL){ dlist->free(node->data); } free(node); dlist->count--; } return TRUE; } void print_dlist(Dlist *dlist, Print_func print) //链表的打印 { Dlist_node *p_node = NULL; if(dlist == NULL || print == NULL || dlist->count == ZERO){ return ; } p_node = dlist->head; while(p_node){ print(p_node->data); //print由使用者选择是哪种类型 p_node = p_node->next; } printf("\n"); } Boolean get_front(Dlist *dlist, void **value) //得到头结点的data { if(dlist == NULL || value == NULL || dlist->count == ZERO){ return FALSE; } *value = dlist->head->data; return TRUE; } Boolean get_tail(Dlist *dlist, void **value) //得到尾节点的data { if(dlist == NULL || dlist->count == ZERO || value == NULL){ return FALSE; } *value = dlist->tail->data; return TRUE; } int get_dlist_count(Dlist *dlist) //得到链表的数量 { if(dlist == NULL){ return -1; } return dlist->count; }
双端链表的测试代码及其用到的包裹函数的实现:
包裹函数的实现
#ifndef _TOOLS_H_ #define _TOOLS_H_ //定义布尔类型 #define TRUE (1) #define FALSE (0) typedef unsigned char Boolean; //定义接口 void *Malloc(size_t size); #endif
#include <stdio.h> #include <stdlib.h> #include "tools.h" void *Malloc(size_t size) { void *result = malloc(size); if(result == NULL){ fprintf(stderr, "the memory is full!\n"); exit(1); } return result; }
测试代码
#include <stdio.h> #include <stdlib.h> #include "dlist.h" void print_int(void *ptr); void print_int(void *ptr) { printf("%d ", *(int *)ptr); } //指向栈空间的不需释放,指向堆空间的要释放 int main(int ac, char **av) { Dlist *dlist = init_dlist(); //链表的初始化 int array[] = {12, 34, 545, 65, 76, 67}; int length = sizeof(array) / sizeof(array[0]); int i = 0; for(i = 0; i < length; ++i){ push_front(dlist, &array[i]); } print_dlist(dlist, print_int); destroy_dlist(&dlist); //链表的销毁 return 0; }
测试结果如下:
[root@localhost doulist]# gcc dlist.c tools.c main.c -o main [root@localhost doulist]# ./main 67 76 65 545 34 12
相关文章推荐
- 数据结构与算法学习(九)(续二)
- 干货分享-数据结构
- 数据结构之单链表的实现
- 两个链表实现集合的运算
- 单链表的逆置操作
- 【数据结构与算法】插入排序
- 【数据结构和算法】选择排序
- 【数据结构与算法】冒泡排序
- 数据结构(java语言描述)——串数组(n阶魔方)
- 大话数据结构读书笔记系列(四)栈与队列
- 重学数据结构系列之——堆及堆排序
- Java数据结构——优先级队列
- HDU 3065 AC自动机模版题
- HDU 2896 AC自动机模版题
- Java数据结构——队列
- 如何理解数据结构中的引用参数 &
- 数据结构 用单链表表示集合的并交差运算
- FFMPEG中重要的数据结构的挖掘
- FFmpeg的一些关键的数据结构(二)
- FFmpeg的一些关键的数据结构(一)