Skip to content

Commit 26caada

Browse files
双向链表的实现
1 parent bdb7440 commit 26caada

File tree

5 files changed

+421
-1
lines changed

5 files changed

+421
-1
lines changed

da-hua-shu-ju-jie-gou/03-list/README.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,72 @@ Status UnionCircularLinkList(CircularLinkList *list, CircularLinkList *anotherLi
509509
}
510510
```
511511
512+
## 双向链表
513+
**在单链表的每个节点中,再设置一个指向其前驱节点的指针域,称为双线链表(double link list)**
514+
515+
### 双向链表的插入
516+
```c
517+
/**
518+
向双向链表第 i 个位置插入元素
519+
520+
@param L 双向链表, 必须存在
521+
@param i 要插入的位置标号, 1 ≤ i ≤ ListLength(L)
522+
@param e 要插入的元素
523+
@return 操作结果 OK/ERROR
524+
*/
525+
Status DuLinkListInsert(DuLinkList *L, int i, ElemType e) {
526+
DuLinkList p = *L;
527+
int j = 1;
528+
529+
while (p && j<i) {
530+
p = p->next;
531+
++j;
532+
}
533+
// 第 i 个元素不存在
534+
if (!p || j >i) return ERROR;
535+
536+
// 生成一个新节点
537+
DuLinkList s = (DuLinkList)malloc(sizeof(DulNode));
538+
539+
// 插入元素
540+
s->data = e;
541+
s->prior = p;
542+
s->next = p->next;
543+
if(p->next != NULL) p->next->prior = s;
544+
p->next = s;
545+
546+
return OK;
547+
}
548+
```
549+
### 双向链表的删除
550+
```c
551+
/**
552+
移除双向链表的第 i 个位置的元素
553+
554+
@param L 双向链表,必须存在
555+
@param i 要移除元素的位置标号, 1 ≤ i ≤ ListLength(L)
556+
@param e 要删除的元素返回
557+
@return 操作结果 OK/ERROR
558+
*/
559+
Status DuLinkListDelete(DuLinkList *L, int i, ElemType *e) {
560+
DuLinkList p = (*L)->next;
561+
int j = 1;
562+
while (p && j < i) {
563+
p = p->next;
564+
++j;
565+
}
566+
// 第 i 个节点不存在
567+
if (!p || j > i) return ERROR;
568+
569+
*e = p->data;
570+
if(p->prior) p->prior->next = p->next;
571+
if(p->next) p->next->prior = p->prior;
572+
573+
free(p);
574+
575+
return OK;
576+
}
577+
```
512578
513579
514580

da-hua-shu-ju-jie-gou/03-list/list/list.xcodeproj/project.pbxproj

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
DA48D11021EE193A006A240B /* SqList.c in Sources */ = {isa = PBXBuildFile; fileRef = DA48D10F21EE193A006A240B /* SqList.c */; };
1313
DA67B4AF21EF7AFA002D3947 /* LinkList.c in Sources */ = {isa = PBXBuildFile; fileRef = DA67B4AE21EF7AFA002D3947 /* LinkList.c */; };
1414
DA8512712220DE23007A250C /* CircularList.c in Sources */ = {isa = PBXBuildFile; fileRef = DA8512702220DE23007A250C /* CircularList.c */; };
15+
DADA334A22256A2F00C8B33A /* DuList.c in Sources */ = {isa = PBXBuildFile; fileRef = DADA334922256A2F00C8B33A /* DuList.c */; };
1516
/* End PBXBuildFile section */
1617

1718
/* Begin PBXCopyFilesBuildPhase section */
@@ -38,6 +39,8 @@
3839
DA67B4AE21EF7AFA002D3947 /* LinkList.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = LinkList.c; sourceTree = "<group>"; };
3940
DA85126F2220DE23007A250C /* CircularList.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CircularList.h; sourceTree = "<group>"; };
4041
DA8512702220DE23007A250C /* CircularList.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = CircularList.c; sourceTree = "<group>"; };
42+
DADA334822256A2F00C8B33A /* DuList.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DuList.h; sourceTree = "<group>"; };
43+
DADA334922256A2F00C8B33A /* DuList.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = DuList.c; sourceTree = "<group>"; };
4144
/* End PBXFileReference section */
4245

4346
/* Begin PBXFrameworksBuildPhase section */
@@ -84,6 +87,7 @@
8487
DA67B4AC21EF7AEE002D3947 /* linkList */,
8588
DA054119221AD6BC004519F5 /* staticList */,
8689
DA85126E2220DE08007A250C /* cicularList */,
90+
DADA3347222569F900C8B33A /* duList */,
8791
DA48D10721EE11D6006A240B /* main.c */,
8892
);
8993
path = list;
@@ -116,6 +120,15 @@
116120
path = cicularList;
117121
sourceTree = "<group>";
118122
};
123+
DADA3347222569F900C8B33A /* duList */ = {
124+
isa = PBXGroup;
125+
children = (
126+
DADA334822256A2F00C8B33A /* DuList.h */,
127+
DADA334922256A2F00C8B33A /* DuList.c */,
128+
);
129+
path = duList;
130+
sourceTree = "<group>";
131+
};
119132
/* End PBXGroup section */
120133

121134
/* Begin PBXNativeTarget section */
@@ -174,6 +187,7 @@
174187
files = (
175188
DA48D10821EE11D6006A240B /* main.c in Sources */,
176189
DA8512712220DE23007A250C /* CircularList.c in Sources */,
190+
DADA334A22256A2F00C8B33A /* DuList.c in Sources */,
177191
DA05411C221AD6DC004519F5 /* StaticList.c in Sources */,
178192
DA67B4AF21EF7AFA002D3947 /* LinkList.c in Sources */,
179193
DA48D11021EE193A006A240B /* SqList.c in Sources */,
Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
//
2+
// DuList.c
3+
// list
4+
//
5+
// Created by 王俊 on 2019/2/26.
6+
// Copyright © 2019 王俊. All rights reserved.
7+
//
8+
9+
#include "DuList.h"
10+
#include <stdlib.h>
11+
#include <time.h>
12+
13+
14+
#pragma mark - test
15+
16+
void DuLinkListTest(void) {
17+
printf("======================================\n");
18+
printf("=========== DuLinkListTest ===========\n");
19+
20+
DuLinkList L = NULL;
21+
22+
InitDulLinkList(&L);
23+
24+
int len = DuLinkListLength(L);
25+
printf("DuLinkListLength: %i\n", len);
26+
27+
Status s = DuLinkListInsert(&L, 1, 13);
28+
printf("DuLinkListInsert: %i\n", s);
29+
30+
s = DuLinkListInsert(&L, 2, 15);
31+
printf("DuLinkListInsert: %i\n", s);
32+
33+
len = DuLinkListLength(L);
34+
printf("DuLinkListLength: %i\n", len);
35+
36+
ElemType e = 0;
37+
s = GetDuLinkListElem(L, 2, &e);
38+
printf("GetDuLinkListElem: status: %i elem: %i\n", s, e);
39+
40+
e=0;
41+
s = DuLinkListDelete(&L, 1, &e);
42+
printf("DuLinkListDelete: status: %i elem: %i\n", s, e);
43+
44+
int index = LocateDuLinkListElem(L, 15);
45+
printf("LocateDuLinkListElem: %i \n", index);
46+
47+
s = DuLinkListIsEmpty(L);
48+
printf("DuLinkListIsEmpty: %i \n", s);
49+
50+
s = ClearDuLinkList(&L);
51+
printf("ClearDuLinkList: %i \n", s);
52+
53+
s = DuLinkListIsEmpty(L);
54+
printf("DuLinkListIsEmpty: %i \n", s);
55+
}
56+
57+
58+
#pragma mark - functions
59+
60+
/**
61+
初始化一个双向链表
62+
63+
@param L 初始化的链表返回
64+
@return 操作结果 OK/ERROR
65+
*/
66+
Status InitDulLinkList(DuLinkList *L) {
67+
DuLinkList link = (DuLinkList)malloc(sizeof(DulNode));
68+
link->next = NULL;
69+
link->prior = NULL;
70+
link->data = 0;
71+
*L = link;
72+
73+
return OK;
74+
return OK;
75+
}
76+
77+
78+
/**
79+
向双向链表第 i 个位置插入元素
80+
81+
@param L 双向链表, 必须存在
82+
@param i 要插入的位置标号, 1 ≤ i ≤ ListLength(L)
83+
@param e 要插入的元素
84+
@return 操作结果 OK/ERROR
85+
*/
86+
Status DuLinkListInsert(DuLinkList *L, int i, ElemType e) {
87+
DuLinkList p = *L;
88+
int j = 1;
89+
90+
while (p && j<i) {
91+
p = p->next;
92+
++j;
93+
}
94+
// 第 i 个元素不存在
95+
if (!p || j >i) return ERROR;
96+
97+
// 生成一个新节点
98+
DuLinkList s = (DuLinkList)malloc(sizeof(DulNode));
99+
100+
// 插入元素
101+
s->data = e;
102+
s->prior = p;
103+
s->next = p->next;
104+
if(p->next != NULL) p->next->prior = s;
105+
p->next = s;
106+
107+
return OK;
108+
}
109+
110+
111+
/**
112+
移除双向链表的第 i 个位置的元素
113+
114+
@param L 双向链表,必须存在
115+
@param i 要移除元素的位置标号, 1 ≤ i ≤ ListLength(L)
116+
@param e 要删除的元素返回
117+
@return 操作结果 OK/ERROR
118+
*/
119+
Status DuLinkListDelete(DuLinkList *L, int i, ElemType *e) {
120+
DuLinkList p = (*L)->next;
121+
int j = 1;
122+
while (p && j < i) {
123+
p = p->next;
124+
++j;
125+
}
126+
// 第 i 个节点不存在
127+
if (!p || j > i) return ERROR;
128+
129+
*e = p->data;
130+
if(p->prior) p->prior->next = p->next;
131+
if(p->next) p->next->prior = p->prior;
132+
133+
free(p);
134+
135+
return OK;
136+
}
137+
138+
139+
/**
140+
获取双向链表第i 个位置的元素
141+
142+
@param L 双向链表, 必须存在
143+
@param i 要获取元素的位置标号 1 ≤ i ≤ ListLength(L)
144+
@param e 返回元素
145+
@return 操作是结果 OK/ERROR
146+
*/
147+
Status GetDuLinkListElem(DuLinkList L, int i, ElemType *e) {
148+
DuLinkList p = L->next;
149+
int j = 1;
150+
151+
while (p && j<i) {
152+
p = p->next;
153+
++j;
154+
}
155+
if (!p || j > i) {
156+
return ERROR;
157+
}
158+
*e = p->data;
159+
return OK;
160+
}
161+
162+
163+
/**
164+
获取一个双向链表的长度
165+
166+
@param L 双向链表, 必须存在
167+
@return 双向链表长度
168+
*/
169+
int DuLinkListLength(DuLinkList L) {
170+
DuLinkList p = L->next;
171+
int len = 0;
172+
173+
while (p) {
174+
p = p->next;
175+
len++;
176+
}
177+
178+
return len;
179+
}
180+
181+
182+
/**
183+
判断一个双向链表是否为空
184+
185+
@param L 双向链表, 必须存在
186+
@return 链表是否为空 TRUE/FALSE
187+
*/
188+
Status DuLinkListIsEmpty(DuLinkList L) {
189+
return DuLinkListLength(L) == 0 ? TRUE : FALSE;
190+
}
191+
192+
/**
193+
查找元素在双向链表中的编号
194+
195+
@param L 双向链表, 必须存在
196+
@param e 要查找的元素
197+
@return 查找结果, 该元素在双向链表中的位置编号, 0 表示不存在
198+
*/
199+
int LocateDuLinkListElem(DuLinkList L, ElemType e) {
200+
int index = 0;
201+
DuLinkList p = L->next;
202+
203+
while (p) {
204+
index ++;
205+
if (p->data == e) {
206+
break;
207+
}
208+
p = p->next;
209+
}
210+
211+
return index;
212+
}
213+
214+
215+
/**
216+
清空双向链表
217+
218+
@param L 双向链表, 必须存在
219+
@return 操作结果 OK/ERROR
220+
*/
221+
Status ClearDuLinkList(DuLinkList *L) {
222+
DuLinkList p = (*L)->next;
223+
while (p) {
224+
DuLinkList q = p->next;
225+
free(p);
226+
p=q;
227+
}
228+
(*L)->next = NULL;
229+
return OK;
230+
}

0 commit comments

Comments
 (0)