双向链表比单链表有更好的灵活性,其大部分操作与线性表相同。下面总结双向链表与单链表之间的不同之处及我在实现过程中所遇到的问题。
1.双向链表的建立
双向链表在初始化时,要给首尾两个节点分配内存空间。成功分配后,要将首节点的prior指针和尾节点的next指针指向NULL,这是十分关键的一步,因为这是之后用来判断空表的条件。同时,当链表为空时,要将首节点的next指向尾节点,尾节点的prior指向首节点。
2.双向链表的插入操作
由于定义双向链表时指针域中多了一个prior指针,插入操作相应变得复杂,但基本操作也并不难理解。只需记住在处理前驱和后继指针与插入节点的关系时,应始终把握好“有序原则”,即若将插入节点与两个已存在的节点构成三角形,则应先处理“向上”的指针,再处理“向下”的指针。下面用代码描述其过程:
?
1
2
3
4
|
pinsert->prior=p;
pinsert->next=p->next;
p->next->prior=pinsert;
p->next=pinsert;
|
3.双向链表的删除操作
理解了双向链表的插入操作后,删除操作便十分容易理解。下面用代码描述其过程:
?
1
2
3
|
p->prior->next=p->next;
p->next->prior=p->prior;
free (p);
|
双向链表的其他操作与单链表类似,在此不再赘述,完整的代码如下:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
|
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int status;
typedef int elemtype;
typedef struct node{
elemtype data;
struct node * next;
struct node * prior;
}node;
typedef struct node* dlinklist;
status visit(elemtype c){
printf ( "%d " ,c);
}
/*双向链表初始化*/
status initdlinklist(dlinklist * head,dlinklist * tail){
(*head)=(dlinklist) malloc ( sizeof (node));
(*tail)=(dlinklist) malloc ( sizeof (node));
if (!(*head)||!(*tail))
return ERROR;
/*这一步很关键*/
(*head)->prior=NULL;
(*tail)->next=NULL;
/*链表为空时让头指向尾*/
(*head)->next=(*tail);
(*tail)->prior=(*head);
}
/*判定是否为空*/
status emptylinklist(dlinklist head,dlinklist tail){
if (head->next==tail)
return TRUE;
else
return FALSE;
}
/*尾插法创建链表*/
status createdlinklisttail(dlinklist head,dlinklist tail,elemtype data){
dlinklist pmove=tail,pinsert;
pinsert=(dlinklist) malloc ( sizeof (node));
if (!pinsert)
return ERROR;
pinsert->data=data;
pinsert->next=NULL;
pinsert->prior=NULL;
tail->prior->next=pinsert;
pinsert->prior=tail->prior;
pinsert->next=tail;
tail->prior=pinsert;
}
/*头插法创建链表*/
status createdlinklisthead(dlinklist head,dlinklist tail,elemtype data){
dlinklist pmove=head,qmove=tail,pinsert;
pinsert=(dlinklist) malloc ( sizeof (node));
if (!pinsert)
return ERROR;
else {
pinsert->data=data;
pinsert->prior=pmove;
pinsert->next=pmove->next;
pmove->next->prior=pinsert;
pmove->next=pinsert;
}
}
/*正序打印链表*/
status traverselist(dlinklist head,dlinklist tail){
/*dlinklist pmove=head->next;
while(pmove!=tail){
printf("%d ",pmove->data);
pmove=pmove->next;
}
printf("\\n");
return OK;*/
dlinklist pmove=head->next;
while (pmove!=tail){
visit(pmove->data);
pmove=pmove->next;
}
printf ( "\\n" );
}
/*返回第一个值为data的元素的位序*/
status locateelem(dlinklist head,dlinklist tail,elemtype data){
dlinklist pmove=head->next;
int pos=1;
while (pmove&&pmove->data!=data){
pmove=pmove->next;
pos++;
}
return pos;
}
/*返回表长*/
status listlength(dlinklist head,dlinklist tail){
dlinklist pmove=head->next;
int length=0;
while (pmove!=tail){
pmove=pmove->next;
length++;
}
return length;
}
/*逆序打印链表*/
status inverse(dlinklist head,dlinklist tail){
dlinklist pmove=tail->prior;
while (pmove!=head){
visit(pmove->data);
pmove=pmove->prior;
}
printf ( "\\n" );
}
/*删除链表中第pos个位置的元素,并用data返回*/
status deleteelem(dlinklist head,dlinklist tail, int pos,elemtype *data){
int i=1;
dlinklist pmove=head->next;
while (pmove&&i<pos){
pmove=pmove->next;
i++;
}
if (!pmove||i>pos){
printf ( "输入数据非法\\n" );
return ERROR;
}
else {
*data=pmove->data;
pmove->next->prior=pmove->prior;
pmove->prior->next=pmove->next;
free (pmove);
}
}
/*在链表尾插入元素*/
status inserttail(dlinklist head,dlinklist tail,elemtype data){
dlinklist pinsert;
pinsert=(dlinklist) malloc ( sizeof (node));
pinsert->data=data;
pinsert->next=NULL;
pinsert->prior=NULL;
tail->prior->next=pinsert;
pinsert->prior=tail->prior;
pinsert->next=tail;
tail->prior=pinsert;
return OK;
}
int main( void ){
dlinklist head,tail;
int i=0;
elemtype data=0;
initdlinklist(&head,&tail);
if (emptylinklist(head,tail))
printf ( "链表为空\\n" );
else
printf ( "链表不为空\\n" );
printf ( "头插法创建链表\\n" );
for (i=0;i<10;i++){
createdlinklisthead(head,tail,i);
}
traverselist(head,tail);
for (i=0;i<10;i++){
printf ( "表中值为%d的元素的位置为" ,i);
printf ( "%d位\\n" ,locateelem(head,tail,i));
}
printf ( "表长为%d\\n" ,listlength(head,tail));
printf ( "逆序打印链表" );
inverse(head,tail);
for (i=0;i<10;i++){
deleteelem(head,tail,1,&data);
printf ( "被删除的元素为%d\\n" ,data);
}
traverselist(head,tail);
if (emptylinklist(head,tail))
printf ( "链表为空\\n" );
else
printf ( "链表不为空\\n" );
printf ( "尾插法创建链表\\n" );
for (i=0;i<10;i++){
//inserttail(head,tail,i);
createdlinklisttail(head,tail,i);
}
traverselist(head,tail);
printf ( "逆序打印链表" );
inverse(head,tail);
}
|
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
相关文章
猜你喜欢
- ASP.NET自助建站系统的域名绑定与解析教程 2025-06-10
- 个人服务器网站搭建:如何选择合适的服务器提供商? 2025-06-10
- ASP.NET自助建站系统中如何实现多语言支持? 2025-06-10
- 64M VPS建站:如何选择最适合的网站建设平台? 2025-06-10
- ASP.NET本地开发时常见的配置错误及解决方法? 2025-06-10
TA的动态
- 2025-07-10 怎样使用阿里云的安全工具进行服务器漏洞扫描和修复?
- 2025-07-10 怎样使用命令行工具优化Linux云服务器的Ping性能?
- 2025-07-10 怎样使用Xshell连接华为云服务器,实现高效远程管理?
- 2025-07-10 怎样利用云服务器D盘搭建稳定、高效的网站托管环境?
- 2025-07-10 怎样使用阿里云的安全组功能来增强服务器防火墙的安全性?
快网idc优惠网
QQ交流群
您的支持,是我们最大的动力!
热门文章
-
2025-05-25 28
-
2025-05-27 28
-
2025-05-29 100
-
2025-05-27 95
-
2025-05-29 64
热门评论