带头节点的线性链表类型[原创]
1
/*========带头节点的线性链表类型=========*/
2
/*=======================================*/
3
4
5
/*===============包含头文件以及类型定义==============*/
6
#include <stdio.h>
7
#include <malloc.h>
8
#define NULL 0
9
#define NODE_NUM 10
10
11
12
typedef struct lnode{
13
char data;
14
struct lnode *next;
15
}*link,*position;
16
17
18
typedef struct{
19
link head,tail;
20
int len;
21
}linklist;
22
23
24
/*======================================================*/
25
/*=======一些在其他函数定义中会调用的函数===============*/
26
/*======================================================*/
27
28
int compare(char a,char b){ /*---compare---比较两个元素的大小关系*/
29
return a-b;
30
}
31
32
33
int visit(link p){
34
if(p->data>=65&&p->data<=97)/*---visit---判断结点的元素是否为大写元素*/
35
return 1;
36
else
37
return 0;
38
39
}
40
41
42
int length(link s){ /*---length---求链的长度*/
43
int i=0;/*i不赋初值,编译错误“可能在i定义以前使用了它在length函数中”*/
44
link p=NULL;
45
p=s;
46
while(p->next!=NULL){
47
p=p->next;
48
i++;
49
}
50
return i;
51
}
52
53
54
void print(linklist l){ /*---print---在屏幕上输出链表的所有元素*/
55
link p=NULL;
56
p=l.head;
57
if(!p->next){
58
printf("\nThe linklist is empty.\n\n");
59
return ;
60
}
61
printf("The list:");
62
while(p){
63
printf("%c-",p->data);
64
p=p->next;
65
}
66
}
67
68
69
70
/*======================================================*/
71
/*==========对带头结点的单链线性表进行操作的函数的定义==================*/
72
/*======================================================*/
73
74
position makenode(char e){ /*---分配由p指向的结点并赋值为e---*/
75
link p=NULL;
76
p=(link)malloc(sizeof(struct lnode));
77
/*---struct lnode 才能表示一个结构体类型并可用于分配空间的元素类型定义-*/
78
if(p){
79
p->data=e;
80
p->next=NULL;
81
}
82
else return;
83
return p;
84
}
85
86
87
void freenode(link p){ /*---释放p所指向的结点-*/
88
free(p);
89
}
90
91
92
93
int initlist(linklist *l){ /*---构造一个由l指向的空的线性表-*/
94
l->head=makenode('L');
95
l->head->next=NULL;/*不是l->head=NULL*/
96
l->tail=l->head;
97
l->len=0;
98
return 1;
99
}
100
101
102
position priorpos(linklist l,link p){ /*---返回p所指结点的直接前驱的位置-*/
103
link q;
104
q=l.head;
105
if(q->next==p) return 0;
106
while(q->next!=p) q=q->next;
107
return q;
108
}
109
110
111
int insfirst(linklist *l,link s){ /*---将s指向的结点插入线性链表的第一个结点之前-*/
112
s->next=l->head->next;
113
if(!l->head->next) l->tail=s;/*当向一个空的线性表执行该操作时*/
114
l->head->next=s;
115
l->len++;
116
117
}
118
119
120
int append(linklist *l,link s){ /*---将指针s所的一串结点链接在线性表L的最后一个结点-*/
121
link q;
122
q=l->head;
123
if(!l->tail){/*考虑到链表为空的情况*/
124
l->head->next=s;
125
while(q->next) q=q->next;/*尾结点的处理*/
126
l->tail=q;
127
}
128
l->tail->next=q=s;
129
while(q->next) q=q->next;/*不能忘了对尾结点的处理*/
130
l->tail=q;
131
l->len+=length(s);
132
133
}
134
135
position delfirst(linklist *l,link q){ /*---删除表中第一个结点并以q返回-*/
136
if(!l->head->next){
137
printf("\nThe linklist is empty,can not delete..\n");
138
return 0;
139
}
140
q=l->head->next;
141
l->head->next=l->head->next->next;
142
return q;
143
}
144
145
146
position remonode(linklist *l,link q){ /*---删除线性表l中的尾结点-*/
147
if(!l->tail){
148
printf("\nthe linklist is empty,can not remonde..\n");
149
return 0;
150
}
151
q=l->tail; /*用书上函数名remove时,编译错误“调用参数个数出错”*/
152
l->tail=priorpos(*l,q);
153
l->tail->next=NULL;
154
return q;
155
}
156
157
158
int insbefore(linklist *l,link p,link s){ /*---将s所指向结点插入在p所指结点之前-*/
159
link q;
160
q=priorpos(*l,p);
161
s->next=p;
162
q->next=s;
163
}
164
165
166
int insafter(link p,link s){ /*---将s所指向结点插入在p所指结点之后-*/
167
s->next=p->next;
168
p->next=s;
169
}
170
171
172
int setcurelem(link p,char e){ /*---用e更新p所指向的当前结点-*/
173
p->data=e;
174
}
175
176
177
char getcurelem(link p){ /*---返回p所指结点中元素的值-*/
178
return p->data;
179
}
180
181
182
int listempty(linklist l){ /*---若线性表为空表则返回1,否则返回0-*/
183
if(l.head==l.tail) return 1;
184
return 0;
185
}
186
187
188
int listlength(linklist l){ /*---返回线性表中元素个数-*/
189
return l.len;
190
}
191
192
193
position gethead(linklist l){ /*---返回线性表l中头结点的位置-*/
194
return l.head;
195
}
196
197
198
position getlast(linklist l){ /*-----返回线性表l中最后一个结点的位置-------*/
199
return l.tail;
200
}
201
202
203
position nextpos(link p){ /*-----返回p所指结点的直接后继的位置-------*/
204
link q;
205
q=p->next;
206
return q;
207
}
208
209
210
position locatepos(linklist l,int i,link p){ /*-----用p返回线性表l中第i个结点的位置,并返回ok-------*/
211
p=l.head;
212
if(i<=0||i>listlength(l)) return 0;
213
while(i){
214
p=p->next;
215
i--;
216
}
217
return p;
218
}
219
220
221
int locatelem(linklist l,char e){ /*----返回表中第一个与e满足一定函数关系的结点次序位置--------*/
222
int i=0;
223
link p;
224
p=l.head->next;
225
while(compare(p->data,e)&&p){
226
p=p->next;
227
++i;
228
}
229
if(!p){/*考虑到查找不到指定元素的情况*/
230
printf("\nthere's no '%c' in this linklist.",e);
231
return 0;
232
}
233
return i;
234
}
235
236
237
int listraverse(linklist l){ /*----用一个函数遍历表中所有结点-------*/
238
link p;
239
p=l.head;
240
while(!visit(p)) p=p->next;
241
if(p!=l.tail) return 0;
242
243
}
244
245
246
247
248
249
int clearlist(linklist*l){ /*----?------将线性表l置为空表,并释放原链表的结点?*/
250
link p;
251
p=(*l).tail;
252
while(p!=(*l).head){
253
p=priorpos(*l,p);
254
freenode(p->next);
255
}
256
freenode((*l).head);
257
258
}
259
260
int destroylist(linklist *l){ /*----------销毁由l指向的线性表---------*/
261
link p;
262
p=(*l).tail;
263
while(p!=(*l).head){
264
p=priorpos(*l,p);
265
freenode(p->next);
266
}
267
freenode((*l).head);
268
}
269
270
271
272
273
274
/*=======================================================*/
275
/*==================主函数部分===================*/
276
/*=======================================================*/
277
main(){
278
int i;
279
char temp='a';
280
linklist *l,*la=NULL,*lb,*lc=NULL;
281
link s,s_nodes,q,p,n;
282
283
284
initlist(l);
285
/*调用初始化函数,构造一个由l指向的线性链表*/
286
printf("l->head->data:%c ",l->head->data);
287
print(*l);
288
289
for(i=1;i<=5;i++){
290
s=makenode(temp++);/*每次插入结点都要重新分配空间,否则无限循环*/
291
insfirst(l,s);
292
/*将s指向的结点插入在以(*l).head为头结点的链表的第一个元素之前*/
293
}
294
printf("insfirst(l,s)*5, ");
295
print(*l);
296
297
s_nodes=s=makenode(temp++);/*_1_*/
298
printf("\ns_nodes:");
299
for(i=1;i<=NODE_NUM;i++){
300
s->next=makenode(temp++);/*_2_*/
301
printf("%c ",s->data);
302
s=s->next;
303
}/*构造了一串由s_nodes指向的链,并为其中的数据项赋值*/
304
305
append(l,s_nodes);
306
/*将由s_nodes指向的一串结点附加到l指向的链表的后面*/
307
printf("\nappend(l,s_nodes), ");
308
print(*l);
309
310
q=delfirst(l,q);/*---*/
311
/*删除以(*l).head为头结点的链表中的第一个结点并以q返回*/
312
printf("\ndelfirst(l,q), ");
313
print(*l);
314
printf("\nthe deleted element:%c",q->data);
315
316
q=remonode(l,q);
317
/*删除l指向的线性表的尾结点并以q返回*/
318
printf("\nremonode(l,q), ");
319
print(*l);
320
printf("\nthe removed element:%c\n",q->data);
321
322
323
p=l->head;
324
for(i=1;i<=5;++i){
325
p=p->next;
326
}/*移动指针p使其指向链表中的第六个结点*/
327
printf("\np->data:%c, ",p->data);
328
329
s=makenode(temp++);
330
printf("s->data:%c",s->data);
331
insbefore(l,p,s);
332
/*将s指向的结点插入到p指向的结点之前*/
333
printf("\ninsbefore(l,p,s), ");
334
print(*l);
335
336
337
printf("\np->data:%c, ",p->data);
338
s=makenode(temp++);
339
printf("\ns->data:%c",s->data);
340
insafter(p,s);
341
/*将s指向的结点插入到p指向的结点之后*/
342
printf("\ninsafter(p,s),");
343
print(*l);
344
345
setcurelem(p,temp++);
346
/*将p指向的结点的数据项赋值为temp*/
347
printf("\np->data:%c, ",p->data);
348
printf("setcurelem(p,temp++),");
349
print(*l);
350
351
n=s;
352
printf("\ncurrent element:%c\n",getcurelem(n));
353
/*在printf函数中调用getcurelem函数,返回n指向的结点的值*/
354
printf("the listlinks'length:%d\n",listlength(*l));
355
/*在pringf函数中调用listlength函数,返回当前链表的元素个数*/
356
357
printf("priorpos(list,p):%c\n",priorpos(*l,p)->data);
358
/*返回p所指结点的直接前驱的位置*/
359
360
printf("\nnextpos(p):%c\n",nextpos(p)->data);
361
/*返回p所指结点的直接后继的位置*/
362
363
print(*l);
364
printf("\nthe element 'e' located at position %d\n",locatelem(*l,'e'));
365
/*返回l所指向的链表中元素值为e的结点的位置*/
366
printf("the element 'i' located at position %d\n",locatelem(*l,'i'));
367
/*返回l所指向的链表中元素值为e的结点的位置*/
368
369
p=locatepos(*l,6,p);
370
printf("the 6th element:%c",p->data);
371
372
if(!listraverse(*l))
373
printf("\nthere are all Lowercase letters\n");
374
/*判断l指向的链表中是否全都不是大写字母*/
375
376
377
/*=========表间操作=========*/
378
379
380
381
382
383
getch();
384
}
385
386
387
/*========带头节点的线性链表类型=========*/2
/*=======================================*/3

4

5
/*===============包含头文件以及类型定义==============*/6
#include <stdio.h>7
#include <malloc.h>8
#define NULL 09
#define NODE_NUM 1010

11

12
typedef struct lnode{13
char data;14
struct lnode *next;15
}*link,*position;16

17

18
typedef struct{19
link head,tail;20
int len;21
}linklist;22

23

24
/*======================================================*/25
/*=======一些在其他函数定义中会调用的函数===============*/26
/*======================================================*/27

28
int compare(char a,char b){ /*---compare---比较两个元素的大小关系*/29
return a-b;30
}31

32

33
int visit(link p){34
if(p->data>=65&&p->data<=97)/*---visit---判断结点的元素是否为大写元素*/35
return 1;36
else37
return 0;38

39
}40

41

42
int length(link s){ /*---length---求链的长度*/43
int i=0;/*i不赋初值,编译错误“可能在i定义以前使用了它在length函数中”*/44
link p=NULL;45
p=s;46
while(p->next!=NULL){47
p=p->next;48
i++;49
}50
return i;51
}52

53

54
void print(linklist l){ /*---print---在屏幕上输出链表的所有元素*/55
link p=NULL;56
p=l.head;57
if(!p->next){58
printf("\nThe linklist is empty.\n\n");59
return ;60
}61
printf("The list:");62
while(p){63
printf("%c-",p->data);64
p=p->next;65
}66
}67

68

69

70
/*======================================================*/71
/*==========对带头结点的单链线性表进行操作的函数的定义==================*/72
/*======================================================*/73

74
position makenode(char e){ /*---分配由p指向的结点并赋值为e---*/75
link p=NULL;76
p=(link)malloc(sizeof(struct lnode));77
/*---struct lnode 才能表示一个结构体类型并可用于分配空间的元素类型定义-*/78
if(p){79
p->data=e;80
p->next=NULL;81
}82
else return;83
return p;84
}85

86

87
void freenode(link p){ /*---释放p所指向的结点-*/88
free(p);89
}90

91

92

93
int initlist(linklist *l){ /*---构造一个由l指向的空的线性表-*/94
l->head=makenode('L');95
l->head->next=NULL;/*不是l->head=NULL*/96
l->tail=l->head;97
l->len=0;98
return 1;99
}100

101

102
position priorpos(linklist l,link p){ /*---返回p所指结点的直接前驱的位置-*/103
link q;104
q=l.head;105
if(q->next==p) return 0;106
while(q->next!=p) q=q->next;107
return q;108
}109

110

111
int insfirst(linklist *l,link s){ /*---将s指向的结点插入线性链表的第一个结点之前-*/112
s->next=l->head->next;113
if(!l->head->next) l->tail=s;/*当向一个空的线性表执行该操作时*/114
l->head->next=s;115
l->len++;116

117
}118

119

120
int append(linklist *l,link s){ /*---将指针s所的一串结点链接在线性表L的最后一个结点-*/121
link q;122
q=l->head;123
if(!l->tail){/*考虑到链表为空的情况*/124
l->head->next=s;125
while(q->next) q=q->next;/*尾结点的处理*/126
l->tail=q;127
}128
l->tail->next=q=s;129
while(q->next) q=q->next;/*不能忘了对尾结点的处理*/130
l->tail=q;131
l->len+=length(s);132

133
}134

135
position delfirst(linklist *l,link q){ /*---删除表中第一个结点并以q返回-*/136
if(!l->head->next){137
printf("\nThe linklist is empty,can not delete..\n");138
return 0;139
}140
q=l->head->next;141
l->head->next=l->head->next->next;142
return q;143
}144

145

146
position remonode(linklist *l,link q){ /*---删除线性表l中的尾结点-*/147
if(!l->tail){148
printf("\nthe linklist is empty,can not remonde..\n");149
return 0;150
}151
q=l->tail; /*用书上函数名remove时,编译错误“调用参数个数出错”*/152
l->tail=priorpos(*l,q);153
l->tail->next=NULL;154
return q;155
}156

157

158
int insbefore(linklist *l,link p,link s){ /*---将s所指向结点插入在p所指结点之前-*/159
link q;160
q=priorpos(*l,p);161
s->next=p;162
q->next=s;163
}164

165

166
int insafter(link p,link s){ /*---将s所指向结点插入在p所指结点之后-*/167
s->next=p->next;168
p->next=s;169
}170

171

172
int setcurelem(link p,char e){ /*---用e更新p所指向的当前结点-*/173
p->data=e;174
}175

176

177
char getcurelem(link p){ /*---返回p所指结点中元素的值-*/178
return p->data;179
}180

181

182
int listempty(linklist l){ /*---若线性表为空表则返回1,否则返回0-*/183
if(l.head==l.tail) return 1;184
return 0;185
}186

187

188
int listlength(linklist l){ /*---返回线性表中元素个数-*/189
return l.len;190
}191

192

193
position gethead(linklist l){ /*---返回线性表l中头结点的位置-*/194
return l.head;195
}196

197

198
position getlast(linklist l){ /*-----返回线性表l中最后一个结点的位置-------*/199
return l.tail;200
}201

202

203
position nextpos(link p){ /*-----返回p所指结点的直接后继的位置-------*/204
link q;205
q=p->next;206
return q;207
}208

209

210
position locatepos(linklist l,int i,link p){ /*-----用p返回线性表l中第i个结点的位置,并返回ok-------*/211
p=l.head;212
if(i<=0||i>listlength(l)) return 0;213
while(i){214
p=p->next;215
i--;216
}217
return p;218
}219
220

221
int locatelem(linklist l,char e){ /*----返回表中第一个与e满足一定函数关系的结点次序位置--------*/222
int i=0;223
link p;224
p=l.head->next;225
while(compare(p->data,e)&&p){226
p=p->next;227
++i;228
}229
if(!p){/*考虑到查找不到指定元素的情况*/230
printf("\nthere's no '%c' in this linklist.",e);231
return 0;232
}233
return i;234
}235

236

237
int listraverse(linklist l){ /*----用一个函数遍历表中所有结点-------*/238
link p;239
p=l.head;240
while(!visit(p)) p=p->next;241
if(p!=l.tail) return 0;242

243
}244

245

246

247

248

249
int clearlist(linklist*l){ /*----?------将线性表l置为空表,并释放原链表的结点?*/250
link p;251
p=(*l).tail;252
while(p!=(*l).head){253
p=priorpos(*l,p);254
freenode(p->next);255
}256
freenode((*l).head);257

258
}259

260
int destroylist(linklist *l){ /*----------销毁由l指向的线性表---------*/261
link p;262
p=(*l).tail;263
while(p!=(*l).head){264
p=priorpos(*l,p);265
freenode(p->next);266
}267
freenode((*l).head);268
}269

270

271

272

273

274
/*=======================================================*/275
/*==================主函数部分===================*/276
/*=======================================================*/277
main(){278
int i;279
char temp='a';280
linklist *l,*la=NULL,*lb,*lc=NULL;281
link s,s_nodes,q,p,n;282

283

284
initlist(l);285
/*调用初始化函数,构造一个由l指向的线性链表*/286
printf("l->head->data:%c ",l->head->data);287
print(*l);288

289
for(i=1;i<=5;i++){290
s=makenode(temp++);/*每次插入结点都要重新分配空间,否则无限循环*/291
insfirst(l,s);292
/*将s指向的结点插入在以(*l).head为头结点的链表的第一个元素之前*/293
}294
printf("insfirst(l,s)*5, ");295
print(*l);296

297
s_nodes=s=makenode(temp++);/*_1_*/298
printf("\ns_nodes:");299
for(i=1;i<=NODE_NUM;i++){300
s->next=makenode(temp++);/*_2_*/301
printf("%c ",s->data);302
s=s->next;303
}/*构造了一串由s_nodes指向的链,并为其中的数据项赋值*/304

305
append(l,s_nodes);306
/*将由s_nodes指向的一串结点附加到l指向的链表的后面*/307
printf("\nappend(l,s_nodes), ");308
print(*l);309

310
q=delfirst(l,q);/*---*/311
/*删除以(*l).head为头结点的链表中的第一个结点并以q返回*/312
printf("\ndelfirst(l,q), ");313
print(*l);314
printf("\nthe deleted element:%c",q->data);315

316
q=remonode(l,q);317
/*删除l指向的线性表的尾结点并以q返回*/318
printf("\nremonode(l,q), ");319
print(*l);320
printf("\nthe removed element:%c\n",q->data);321

322

323
p=l->head;324
for(i=1;i<=5;++i){325
p=p->next;326
}/*移动指针p使其指向链表中的第六个结点*/327
printf("\np->data:%c, ",p->data);328

329
s=makenode(temp++);330
printf("s->data:%c",s->data);331
insbefore(l,p,s);332
/*将s指向的结点插入到p指向的结点之前*/333
printf("\ninsbefore(l,p,s), ");334
print(*l);335

336

337
printf("\np->data:%c, ",p->data);338
s=makenode(temp++);339
printf("\ns->data:%c",s->data);340
insafter(p,s);341
/*将s指向的结点插入到p指向的结点之后*/342
printf("\ninsafter(p,s),");343
print(*l);344

345
setcurelem(p,temp++);346
/*将p指向的结点的数据项赋值为temp*/347
printf("\np->data:%c, ",p->data);348
printf("setcurelem(p,temp++),");349
print(*l);350

351
n=s;352
printf("\ncurrent element:%c\n",getcurelem(n));353
/*在printf函数中调用getcurelem函数,返回n指向的结点的值*/354
printf("the listlinks'length:%d\n",listlength(*l));355
/*在pringf函数中调用listlength函数,返回当前链表的元素个数*/356

357
printf("priorpos(list,p):%c\n",priorpos(*l,p)->data);358
/*返回p所指结点的直接前驱的位置*/359

360
printf("\nnextpos(p):%c\n",nextpos(p)->data);361
/*返回p所指结点的直接后继的位置*/362

363
print(*l);364
printf("\nthe element 'e' located at position %d\n",locatelem(*l,'e'));365
/*返回l所指向的链表中元素值为e的结点的位置*/366
printf("the element 'i' located at position %d\n",locatelem(*l,'i'));367
/*返回l所指向的链表中元素值为e的结点的位置*/368

369
p=locatepos(*l,6,p);370
printf("the 6th element:%c",p->data);371

372
if(!listraverse(*l))373
printf("\nthere are all Lowercase letters\n");374
/*判断l指向的链表中是否全都不是大写字母*/375

376

377
/*=========表间操作=========*/378

379

380

381

382

383
getch();384
}385

386

387




浙公网安备 33010602011771号