单链表存在一定的弊端,就是查找数据和删除数据的时候比较麻烦,而双链表的出现就是为了解决它的弊端:
双链表的引入是为了解决单链表的不足:
(1)双链表可以往前遍历,也可以往后遍历,具有两个方向
双链表的节点 = 有效数据 + 两个指针(分别指向前一个节点和后一个节点)
单向,双向链表的图形结构描述:
struct single_list
{
数据域;
指针域(后向指针) ;
};
struct double_list
{
数据域;
指针域(前向指针) ;
指针域(后向指针) ;
};
双向链表的基本操作和单向链表原理一致,所以这篇省略了注释[具体参见上一篇:
单向链表节点的建立,头尾插,打印,删除及逆序],双向链表在删除节点时并不必另设指针保存被删除节点的前一节点,较为方便
1 #include<stdio.h>
2 #include<string.h>
3 #include<stdlib.h>
4
5 struct double_list {
6 int data;
7 struct double_list* prev;
8 struct double_list* next;
9 };
10 typedef struct double_list DL;
11 //创建节点
12 DL* make_node(int data)
13 {
14 DL* p = (DL*)malloc(sizeof(DL));
15 if (NULL == p)
16 {
17 printf("fail to malloc
");
18 return NULL;
19 }
20 memset(p, 00, sizeof(DL));
21 p->data = data;;
22 p->prev = NULL;
23 p->next = NULL;
24 }
25 //尾插节点
26 void tail_add(DL* ph, DL* new1)
27 {
28 DL* a = ph;
29 while (NULL != a->next)
30 {
31 a = a->next;
32 }
33 a->next = new1;
34 new1->prev = a;
35 new1->next = NULL;
36 }
37 //头插节点
38 void top_add(DL* ph, DL* new1)
39 {
40 ph->next->prev = new1;
41 new1->next = ph->next;
42 new1->prev = ph;
43 }
44 //删除节点
45 int delete_node(DL* ph, int data)
46 {
47 DL* a = ph;
48 while (NULL != a->next)
49 {
50 a = a->next;
51 if (data == a->data)
52 {
53 //两种情况
54 if (NULL != a->next) //下一个节点不为空
55 {
56 a->prev->next = a->next;
57 a->next->prev = a->prev;
58 free(a);
59 }
60 else//下一个节点为空
61 {
62 a->prev->next = NULL;
63 free(a);
64 }
65 printf("Successfully delete!
");
66 return 0;
67 }
68
69 }
70 printf("NOT FOUND!N");
71 return -1;
72
73 }
74
75 //正向遍历链表
76 void list_positive_traversal(DL* ph)
77 {
78 DL* a = ph;
79 while (NULL != a->next)
80 {
81 a = a->next;
82 printf("%d ", a->data);
83 }
84 printf("
");
85 }
86
87 //反向遍历链表
88 void list_reverse_traversal(DL* ph)
89 {
90 DL* a = ph;
91 while (NULL != a->next)
92 {
93 a = a->next;
94 }
95 while (NULL != a->prev)
96 {
97 printf("%d ", a->data);
98 a = a->prev;
99 }
100 printf("
");
101 }
102 int main()
103 {
104 int data;
105 DL* header = make_node(0);
106
107 int N = 0;
108 printf("How many numbers do you want?
");
109 scanf("%d", &N);
110 getchar();
111 for (int i = 0; i < N; i++)//创建出N个节点并实现尾插
112 {
113 printf("<%d>", i + 1);
114 scanf("%d", &data);
115 getchar();
116 tail_add(header, make_node(data));
117 }
118 printf("list:
");
119 list_positive_traversal(header);
120
121 printf("Do you want to delete node? [1--yes;0--no]
");
122 int r;
123 scanf("%d", &r);
124 getchar();
125 while (r)
126 {
127 printf("Which number will you delete?
");
128 int n;
129 scanf("%d", &n);
130 getchar();
131 delete_node(header, n);
132 printf("Do you want to delete node? [1--yes;0--no]
");
133 scanf("%d", &r);
134 }
135
136 printf("positive traversal:
");
137 list_positive_traversal(header);
138
139 printf("reverse traversal:
");
140 list_reverse_traversal(header);
141
142 free(header);
143 return 0;
144 }
测试结果如下: