数据结构(三)——双链表、循环链表

线性表——双链表、循环链表

双链表概念

​ 双链表是链表的一种,也叫双向链表,因为双链表的每个物理节点增加一个指向后继节点的指针域和一个指向前驱节点的指针域

循环链表概念

​ 循环链表也是链表的一种,他与单链表唯一的区别就是,循环链表的最后一个节点将指向头节点

双链表定义

​ 根据概念不难理解,双链表即在单链表的基础上,增加一个指向前驱节点的指针域,这里用 prior 表示

1
2
3
4
5
typedef struct DLinkList{
int data;
DLinkList *prior;//指向前驱节点
DLinkList *next;//指向后继节点
}DLinkList;

头插法创建双链表

​ 头插法创建双链表的思路很简单,和单链表的思路几乎一致,不同在于除了需要不停的修改头节点的 next 指针以外,还要不断让新加入节点的前驱节点 prior 指向头节点,通过 while 循环来实现这一过程,就实现了头插法创建双链表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
DLinkList *CreateListF() {
//头插法创建双链表
DLinkList *L;
L = (DLinkList*)malloc(sizeof(DLinkList));
L->prior = NULL;
L->next = NULL;
DLinkList *s;
int d;
cout << "输入整形数据,以 0 结束" << endl;
cin >> d;
while (d != 0) {
s = (DLinkList*)malloc(sizeof(DLinkList));
s->data = d;
s->next = L->next;
if (L->next != NULL)
L->next->prior = s;
L->next = s;
s->prior = L;
cout << "输入下一个数据" << endl;
cin >> d;
}
return L;
}

尾插法创建双链表

​ 尾插法创建双链表也和单链表尾插法创建时的思路很像,先定义双链表的头尾两个指针,这里如果理解了单链表的尾插法,就不难理解之后通过尾指针不断“前移”(其实是通过这种方法来让新插入的节点被插入在老节点之前),实现尾插法创建双链表,并能与头节点相连

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
DLinkList *CreateListT() {
//尾插法创建双链表
DLinkList *s, *r, *L;
int d;
L = (DLinkList *)malloc(sizeof(DLinkList));
r = L;
cout << "输入整形数据,以 0 结束" << endl;
cin >> d;
while (d != 0) {
s = (DLinkList *)malloc(sizeof(DLinkList));
s->data = d;
r->next = s;
s->prior = r;
r = s;
cout << "输入下一个数据" << endl;
cin >> d;
}
r->next = NULL;
return L;
}

双链表的插入

​ 双链表的插入方法要定义一个 p 节点用来查找插入位置的前一个节点,即他的直接前驱节点,再定义一个 s 节点用来存放新加的数据,通过改变 p 节点的 next 和 p->next 的 prior 来将 s 节点插入在 p 节点之后

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
bool ListInsert(DLinkList *L, int pos, int d) {
int i = 0;
DLinkList *p = L;
DLinkList *s;
while (i < pos - 1 && p != NULL) {
i++;
p = p->next;
}
if (p == NULL)
return false;
else {
s = (DLinkList *)malloc(sizeof(DLinkList));
s->data = d;
s->next = p->next;
if (p->next != NULL)
p->next->prior = s;
s->prior = p;
p->next = s;
return true;
}
}

双链表的删除

​ 删除操作大体上和插入操作十分相似,先查找到删除位置的直接前驱节点,先改变直接前驱节点的 next 和要删除节点的 next 的 prior 来将要删除的节点隔离,再释放掉他的资源,就删除了这个节点,这里插入和删除操作都需要注意表头和表尾的处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
bool ListDelete(DLinkList *L, int pos) {
int i = 0;
DLinkList *p = L;
DLinkList *q;
while (i < pos - 1 && p != NULL) {
i++;
p = p->next;
}
if (p == NULL)
return false;
else {
q = p->next;
if (q == NULL)
return false;
p->next = q->next;
if (p->next != NULL)
p->next->prior = p;
free(q);
return true;
}
}

双链表遍历

​ 通过循环直接遍历双链表

1
2
3
4
5
6
7
8
9
10
void PrintList(DLinkList *L) {
DLinkList *p;
if (L->next == NULL)
return;
p = L->next;
while (p != NULL) {
cout << p->data << endl;
p = p->next;
}
}

循环链表的定义、创建、增、删、查等操作

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
//定义
typedef struct LoopLinkList {
int data;
LoopLinkList *next;
}LoopLinkList;
//创建(头插)
LoopLinkList *CreateLoopList() {
LoopLinkList *head, *p;
int d;
head = (LoopLinkList *)malloc(sizeof(LoopLinkList));
if (head == NULL)
return NULL;
head->next = NULL;
cout << "输入数据,0结束" << endl;
cin >> d;
while (d != 0) {
if (head->next == NULL) {
p = (LoopLinkList *)malloc(sizeof(LoopLinkList));
if (p == NULL)
return NULL;
else {
p->data = d;
head->next = p;
p->next = head;
cin >> d;
}
}
else {
p = (LoopLinkList *)malloc(sizeof(LoopLinkList));
if (p == NULL)
return NULL;
else {
p->data = d;
p->next = head->next;
head->next = p;
cin >> d;
}
}
}
return head;
}
//插入节点
void InsertList(LoopLinkList *head, int pos, int d) {
LoopLinkList *p = head;
int i = 0;
while (i < pos - 1 && p != NULL) {
i++;
p = p->next;
}
if (p == NULL)
return;
LoopLinkList *r;
r = (LoopLinkList *)malloc(sizeof(LoopLinkList));
r->data = d;
r->next = p->next;
p->next = r;
}
//删除节点
void DeleteList(LoopLinkList *head, int pos) {
LoopLinkList *p = head;
int i = 0;
while (i < pos - 1 && p != NULL) {
i++;
p = p->next;
}
if (p == NULL)
return;
LoopLinkList *r;
r = p->next;
p->next = r->next;
free(r);
}
//查找节点
int SearchList(LoopLinkList *head, int pos) {
LoopLinkList *p = head;
int i = 0;
while (i < pos - 1 && p != NULL) {
i++;
p = p->next;
}
if (p == NULL)
return 0;
return p->next->data;
}
//输出循环链表
void PrintList(LoopLinkList *L) {
LoopLinkList *p;
if (L->next == NULL)
return;
p = L->next;
cout << "数据如下" << endl;
while (p != NULL) {
cout << p->data << endl;
p = p->next;
if (p->data == -842150451)
return;
}
}
-------------本文结束感谢您的阅读-------------