一、双向链表的概念
双向链表基于单链表。单链表是单向的,有一个头结点,一个尾结点,要访问任何结点,都必须知道头结点,不能逆着进行。而双链表添加了一个指针域,通过两个指针域,分别指向结点的前结点和后结点。这样的话,可以通过双链表的任何结点,访问到它的前结点和后结点。
在双向链表中,结点除含有数据域外,还有两个链域,一个存储直接后继结点的地址,一般称为右链域;一个存储直接前驱结点地址,一般称之为左链域。
双向链表结构示意图
表头为空,表头的后继节点为"节点10"(数据为10的节点);"节点10"的后继节点是"节点20"(数据为10的节点),"节点20"的前继节点是"节点10";"节点20"的后继节点是"节点30","节点30"的前继节点是"节点20";...;末尾节点的后继节点是表头。
双链表删除节点
删除"节点30"
删除之前:"节点20"的后继节点为"节点30","节点30" 的前继节点为"节点20"。"节点30"的后继节点为"节点40","节点40" 的前继节点为"节点30"。
删除之后:"节点20"的后继节点为"节点40","节点40" 的前继节点为"节点20"。
双链表添加节点
在"节点10"与"节点20"之间添加"节点15"
添加之前:"节点10"的后继节点为"节点20","节点20" 的前继节点为"节点10"。
添加之后:"节点10"的后继节点为"节点15","节点15" 的前继节点为"节点10"。"节点15"的后继节点为"节点20","节点20" 的前继节点为"节点15"。
二、C语言实现双向链表
2.1 头文件

1 #pragma once 2 //新建双向链表。成功返回链表头,否则,返回NULL 3 extern int create_dLink(); 4 //撤销双向链表,成功返回0,否则返回-1 5 extern int destory_dLink(); 6 //双向列表是否为空,为空返回1,否则返回0 7 extern int is_empty_dLink(); 8 //双向链表的大小 9 extern int dLink_size(); 10 //获取索引index位置的元素,成功返回节点指针,否则返回NULL 11 extern void* dLink_get(int index); 12 //获取双向链表中第一个元素,成功返回节点指针,否则返回NULL 13 extern void* dLink_getFirst(); 14 //获取双向链表中最后一个元素,成功返回节点指针,否则返回NULL 15 extern void* dLink_getTail(); 16 /* 17 链表中增加 18 */ 19 //在Index位置插值value,成功返回0,否则返回-1; 20 extern int dLink_insert(int index,void * pVal); 21 //在表头插入值 22 extern int dLink_insert_head(void *pVal); 23 //在表尾插入值 24 extern int dLink_insert_tail(void *pVal); 25 /* 26 链表中删除 27 */ 28 //在index处删除 29 extern int dLink_delete(int index); 30 //删除第一个节点 31 extern int dLink_delete_first(); 32 //闪电湖第二个节点 33 extern int dLink_delete_tail();

1 #include<stdio.h>
2 #include "double_link.h"
3 #include<malloc.h>
4
5 //双向链表节点
6 typedef struct My_node
7 {
8 struct My_node *prev;
9 struct My_node *pNext;
10 void * p;
11 }my_node;
12 //b表头不存放元素值
13 my_node *phead = NULL;
14 //节点的个数
15 int node_count = 0;
16 //创建节点,成功返回节点指针,否则,返回NULL
17 my_node* create_node(void *pVal)
18 {
19 my_node *pnode = NULL;
20 pnode = (my_node*)malloc(sizeof(My_node));
21 if (!pnode)
22 {
23 printf("create pnode error\n");
24 return NULL;
25 }
26 //默认的,pnode的前一节点和后一节点都指向他自己
27 pnode->prev = pnode->pNext = pnode;
28 //节点的值为pVal
29 pnode->p = pVal;
30 return pnode;
31 }
32
33 //新建双向链表 成功返回0 否则返回-1
34 int create_dLink()
35 {
36 phead = create_node(NULL);
37 if (!phead)
38 return -1;
39 //设置节点的个数
40 node_count = 0;
41 return 0;
42 }
43
44 int destory_dLink()
45 {
46 if (!phead)
47 {
48 printf("%s failed! dlink is null!\n", __func__);
49 return -1;
50 }
51 My_node*pnode = phead->pNext;
52 my_node* ptmp = NULL;
53 if (pnode!=phead)
54 {
55 ptmp = pnode;
56 pnode = pnode->pNext;
57 free(pnode);
58 }
59 free(phead);
60 phead = NULL;
61 node_count = 0;
62 return 0;
63 }
64
65 int is_empty_dLink()
66 {
67 return node_count==0;
68 }
69
70 int dLink_size()
71 {
72 return node_count;
73 }
74 //获取双向链表中第Index位置的节点
75 my_node* get_node(int index)
76 {
77 if (index<0 || index >= node_count)
78 {
79 printf("%s failed ! index out of bound\n", __func__);
80 return NULL;
81 }
82 //正向查找
83 if (index <= (node_count / 2))
84 {
85 int i = 0;
86 my_node *pnode = phead->pNext;
87 while ((i++)<index)
88 {
89 pnode = pnode->pNext;
90 }
91 return pnode;
92 }
93 //反向查找
94 int j = 0;
95 int rindex = node_count - index - 1;
96 my_node *rnode = phead->prev;
97 while ((j++)<rindex)
98 {
99 rnode = rnode->prev;
100 }
101 return rnode;
102 }
103 void * dLink_get(int index)
104 {
105 my_node *pindex = get_node(index);
106 if (!pindex)
107 {
108 printf("%s failed!\n", __func__);
109 return NULL;
110 }
111 return pindex->p;
112 }
113
114 //获取第一个节点
115 void * dLink_getFirst()
116 {
117 return get_node(0) ;
118 }
119 //获取最后一个节点
120 void * dLink_getTail()
121 {
122 return get_node(node_count-1);
123 }
124 //将值插入到index位置,成功返回0;否则 返回-1
125 int dLink_insert(int index, void * pVal)
126 {
127 //插入表头
128 if (index == 0)
129 return dLink_insert_head(pVal);
130 //获取要插入位置对应的节点
131 my_node* pindex = get_node(index);
132 if (!pindex)
133 return -1;
134 //创建节点
135 my_node* pnode = create_node(pVal);
136 if (!pnode)
137 return -1;
138 pnode->prev = pindex->prev;
139 pnode->pNext = pindex;
140 pindex->prev->pNext = pnode;
141 pindex->prev = pnode;
142 node_count++;
143 return 0;
144 }
145 //数值插入表头
146 int dLink_insert_head(void * pVal)
147 {
148 my_node* pnode = create_node(pVal);
149 if (!pnode)
150 return -1;
151 pnode->prev = phead;
152 pnode->pNext = phead->pNext;
153
154 phead->pNext->prev = pnode;
155 phead->pNext = pnode;
156 node_count++;
157 return 0;
158 }
159
160 int dLink_insert_tail(void * pVal)
161 {
162 my_node* pnode = create_node(pVal);
163 if (!pnode)
164 return -1;
165 pnode->pNext = phead;
166 pnode->prev = phead->prev;
167 phead->prev->pNext = pnode;
168 phead->prev = pnode;
169 return 0;
170 }
171
172 int dLink_delete(int index)
173 {
174 my_node* pindex = get_node(index);
175 if (!pindex)
176 {
177 printf("%s failed! the index in out of bound\n",__func__);
178 return -1;
179 }
180 pindex->pNext->prev = pindex->prev;
181 pindex->prev->pNext = pindex->pNext;
182 free(pindex);
183 node_count--;
184 return 0;
185 }
186
187 int dLink_delete_first()
188 {
189 return dLink_delete(0);
190 }
191
192 int dLink_delete_tail()
193 {
194 return dLink_delete(node_count-1);
195 }
2.3 test测试代码

1 #include<stdio.h>
2 #include"double_link.h"
3 //1.双向链表操作数为int
4 void int_test()
5 {
6 int arr[10] = {11,55,67,90,21,45,23,59,79,10};
7 printf("xxxxxxxxxxxxxxxxx\n");
8 create_dLink(); //创建链表
9 dLink_insert(0, &arr[0]); //双向链表表头插入
10 dLink_insert(0, &arr[1]); //双向链表表头插入
11 dLink_insert(0, &arr[2]); //双向链表表头插入
12 dLink_insert(0, &arr[3]); //双向链表表头插入
13 dLink_insert(0, &arr[4]); //双向链表表头插入
14 dLink_insert(0, &arr[5]); //双向链表表头插入
15 printf("is_empty_dLink()=%d\n",is_empty_dLink()); //双向链表是否为空
16 printf("dLink_size()=%d\n", dLink_size()); //双向链表的大小
17 //遍历双向链表
18 int i ;
19 int * p ;
20 int sz = dLink_size();
21 for ( i = 0; i < sz; i++)
22 {
23 p = (int*)dLink_get(i);
24 printf("dLink_get(%d)=%d\n",i,*p);
25 }
26 destory_dLink();
27 }
28
29 //2.操作数为字符串
30 void string_test()
31 {
32 char* str[] = {"one","two","three","four","five"};
33 create_dLink(); //创建链表
34 dLink_insert(0, str[0]); //双向链表表头插入
35 dLink_insert(0, str[1]); //双向链表表头插入
36 dLink_insert(0, str[2]); //双向链表表头插入
37 printf("is_empty_dLink()=%d\n", is_empty_dLink()); //双向链表是否为空
38 printf("dLink_size()=%d\n", dLink_size()); //双向链表的大小
39 //遍历双向链表
40 int i ;
41 char * p ;
42 int sz = dLink_size();
43 for (i = 0; i < sz; i++)
44 {
45 p = (char*)dLink_get(i);
46 printf("dLink_get(%d)=%s\n", i, p);
47 }
48 destory_dLink();
49 }
50 //3.双向链表为结构体
51 typedef struct MyStruct
52 {
53 int id;
54 char name[20];
55 } stu;
56 stu arr_stu[] =
57 {
58 {1000,"lii"},
59 { 1001,"mike" },
60 { 1002,"lucky" },
61 { 1003,"eric" },
62 };
63 #define arr_stu_size ((sizeof(arr_stu))/(sizeof(arr_stu[0])))
64 void stuc_test()
65 {
66 create_dLink(); //创建链表
67 dLink_insert(0, &arr_stu[0]); //双向链表表头插入
68 dLink_insert(0, &arr_stu[1]); //双向链表表头插入
69 dLink_insert(0, &arr_stu[2]); //双向链表表头插入
70 printf("is_empty_dLink()=%d\n", is_empty_dLink()); //双向链表是否为空
71 printf("dLink_size()=%d\n", dLink_size()); //双向链表的大小
72 //遍历双向链表
73 int i ;
74 stu * p ;
75 int sz = dLink_size();
76 for (i = 0; i < sz; i++)
77 {
78 p = (stu*)dLink_get(i);
79 printf("dLink_get(%d)=[%d,%s]\n", i, p->id,p->name);
80 }
81 destory_dLink();
82 }
83 int main()
84 {
85 int_test();
86 string_test();
87 stuc_test();
88
89 return 0;
90 }
2.34结果显示




