双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。本章中的双端链表为通用双端链表,其数据域类型为void *,可以接收任意类型的指针,达到通用的效果。首先我们来看dlist.h文件中结构体的声明和接口的声明:
//链表节点类型
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); //得到链表数量
typedef void (*Print_func)(void * value);
#endif
在dlist.h中同样声明了链表节点的结构体和链表控制信息的结构体,同时还使用了函数指针,函数指针可以使该指针指向同类型的函数(返回值类型和参数列表相同);Print_func为一种类型,其类型指向返回值为void,参数为void *的函数。
接下来我们在dlist.c中对于接口进行实现:
#include <stdio.h> #include <stdlib.h> #include <strings.h> #include "dlist.h" #include "tools.h" Dlist *init_dlist(void) //双端链表的初始化 { Dlist *dlist = (Dlist *)Malloc(sizeof(Dlist)); bzero(dlist,sizeof(Dlist)); return dlist; } void destroy_dlist(Dlist **dlist) //双端链表的销毁 { if(dlist == NULL || *dlist == NULL){ return ; } //销毁步骤: //1.先销毁链表节点(头删) while((*dlist) -> count){ pop_front(*dlist); } //2.再销毁链表的控制信息 free(*dlist); *dlist = NULL; } Boolean push_front(Dlist *dlist,void *value) //头插 { Dlist_node * p_node = NULL; if(dlist == NULL || value == NULL){ return FALSE; } p_node = (Dlist_node *)Malloc(sizeof(Dlist_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){ return FALSE; } p_node = (Dlist_node *)Malloc(sizeof(Dlist_node)); p_node ->data = value; p_node ->next = NULL; 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 = dlist ->head ->next; dlist ->head ->prev = NULL; }
tools.h :
<pre name="code" class="plain">#ifndef _TOOLS_H_ #define _TOOLS_H_ //定义布尔类型 #define TRUE (1) #define FALSE (0) typedef unsigned char Boolean; //定义接口 void *Malloc(size_t size); void print_int(void *value); #endif
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include "tools.h" 4 5 void *Malloc(size_t size) 6 { 7 void *result = malloc(size); 8 if(result == NULL){ 9 fprintf(stderr,"the memory is full!\n"); 10 exit(1); 11 } 12 return result; 13 } 14 15 void print_int(void *value) 16 { 17 int *p = (int *)value; 18 printf("%5d",*p); 19 } ~ </strong></span>
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include "dlist.h" 4 #include "tools.h" 5 6 int main(int argc, char **argv) 7 { 8 Dlist *dlist = init_dlist(); //双端链表的初始化 9 int array[] = {12, 23, 34, 45, 56, 67, 78, 89}; 10 int length = sizeof(array) / sizeof(array[0]); 11 int i = 0; 12 13 for(i = 0; i < length; ++i){ 14 push_front(dlist, &array[i]); 15 } 16 17 print_dlist(dlist, print_int);//打印链表信息 18 19 destroy_dlist(&dlist); //链表的销毁 20 return 0; 21 }