C语言双向链表讲解

一、双向链表的概念

    双向链表基于单链表。单链表是单向的,有一个头结点,一个尾结点,要访问任何结点,都必须知道头结点,不能逆着进行。而双链表添加了一个指针域,通过两个指针域,分别指向结点的前结点和后结点。这样的话,可以通过双链表的任何结点,访问到它的前结点和后结点。

    在双向链表中,结点除含有数据域外,还有两个链域,一个存储直接后继结点的地址,一般称为右链域;一个存储直接前驱结点地址,一般称之为左链域。

    双向链表结构示意图

    

表头为空,表头的后继节点为"节点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();
View Code
2.2 .c
  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 }
View Code

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 }
View Code

2.34结果显示

posted on 2019-08-29 22:55  lfylcj  阅读(2033)  评论(0编辑  收藏  举报

导航