注意:
在插入和删除的操作中,一定要把链表的头和尾拿出来单独分析! 由于链表在第一次完整连接后(比如下面程序中的PushBack函数),每个节点在链表中的内存地址已经固定了下来,比如上图中,b里保存的指针始终就是指向c的next的地址,c中保存的指针始终就是指向d的next的地址,d中保存的指针始终是指向head的地址,所以即使在a,b间插入一个元素e,也不会影响b,c,d节点指针的指向。所以只要不是有关处理头尾元素的操作,都不需要从头到尾地把链表重新连接一遍!因为位置在第一次连接的时候就已经固定了!
1 //CircleList.h
2
3 #pragma once
4
5 #include <stdio.h>
6 #include <stdlib.h>
7
8 typedef struct Node
9 {
10 int element;
11 Node *next;
12 }Node;
13
14 typedef struct CircleList //单向循环链表
15 {
16 Node *head;
17 int length;
18 }CircleList;
19
20 void InitList(CircleList *cir); //创建循环链表
21
22 Node* GetPrev(CircleList *cir, Node* q); //获取节点q前驱元素的指针
23
24 Node* GetBack(CircleList *cir, Node* q); //获取节点q后继元素的指针
25
26 Node* BackElem(CircleList *cir); //返回指向尾节点的指针
27
28 void PushBack(CircleList *cir, int elem); //向链表尾部添加元素
29
30 void InsertElem(CircleList *cir, int position, int elem); //在position的前一个位置处插入元素
31
32 void DeleteElem(CircleList *cir, int position); //删除position位置处的元素
33
34 void ClearList(CircleList *cir); //清空循环链表
35
36 void PrintListFromFirst(CircleList *cir); //从第一个元素开始遍历循环链表
37
38 void PrintListFromPosition(CircleList *cir, int position); //从第position处的元素开始循环遍历整个链表
1 //CircleList.c
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include "CircleList.h"
6
7 void InitList(CircleList *cir) //创建循环链表
8 {
9 cir->length = 0;
10 cir->head = (Node*)malloc(sizeof(Node));
11 cir->head->next = NULL;
12 }
13
14 Node* GetPrev(CircleList *cir, Node* q) //获取节点q前驱元素的指针
15 {
16 if (cir->head->next == q)
17 {
18 printf("该节点没有前驱元素!\n");
19 return NULL;
20 }
21 Node *p = cir->head;
22 for (int i = 1; i <= cir->length; ++i)
23 {
24 p = p->next;
25 if (p->next == q)
26 return p;
27 }
28 }
29
30 Node* GetBack(CircleList *cir, Node* q) //获取节点q后继元素的指针
31 {
32 if (q == BackElem(cir))
33 {
34 printf("该节点没有后继元素!\n");
35 return NULL;
36 }
37 Node *p = cir->head;
38 for (int i = 1; i <= cir->length; ++i)
39 {
40 p = p->next;
41 if (q->next == p)
42 return p;
43 }
44 }
45
46 Node* BackElem(CircleList *cir) //返回指向尾节点的指针
47 {
48 Node *p = cir->head;
49 if (cir->length == 0)
50 return p;
51 for (int i = 1; i <= cir->length; ++i)
52 p = p->next;
53 return p;
54 }
55
56 void PushBack(CircleList *cir, int elem) //向链表尾部添加元素
57 {
58 Node *NewNode = (Node*)malloc(sizeof(Node));
59 NewNode->element = elem;
60 Node *p = BackElem(cir);
61 p->next = NewNode;
62 NewNode->next = cir->head->next;
63 ++cir->length;
64 }
65
66 void InsertElem(CircleList *cir, int position, int elem) //在position的前一个位置处插入元素(head的position为0)
67 {
68 if (position > cir->length + 1 || position < 1)
69 {
70 printf("插入失败!请在合理的范围内插入元素!\n");
71 return;
72 }
73 if (position == cir->length + 1 || position == 1)
74 {
75 Node *q = BackElem(cir);
76 Node *NewNode = (Node*)malloc(sizeof(Node));
77 NewNode->element = elem;
78 q->next = NewNode;
79 NewNode->next = cir->head->next;
80 if (position == 1)
81 cir->head->next = NewNode;
82 ++cir->length;
83 return;
84 }
85 Node *p = cir->head;
86 for (int i = 1; i <= position - 1; ++i)
87 p = p->next; //获取position前一个位置处的指针p
88 Node *NewNode = (Node*)malloc(sizeof(Node));
89 NewNode->element = elem;
90 NewNode->next = p->next;
91 p->next = NewNode;
92 ++cir->length;
93 return;
94 }
95
96
97 void DeleteElem(CircleList *cir, int position) //删除position位置处的元素
98 {
99 Node *p = cir->head;
100 if (position == 1)
101 {
102 p = p->next;
103 cir->head->next = p->next;
104 Node *q = BackElem(cir);
105 q->next = p->next;
106 free(p);
107 --cir->length;
108 return;
109 }
110 if (position == cir->length)
111 {
112 Node *q = BackElem(cir);
113 Node *p = GetPrev(cir, q); //令p指向倒数第二个元素
114 p->next = cir->head->next;
115 free(q);
116 --cir->length;
117 return;
118 }
119 for (int i = 1; i <= position - 1; ++i)
120 p = p->next; //获取position前一个位置处的指针p
121 Node *q = p->next;
122 p->next = q->next;
123 free(q);
124 --cir->length;
125 return;
126 }
127
128
129 void ClearList(CircleList *cir) //清空循环链表
130 {
131 int temp = cir->length; //删除过程中cir->length时刻变化,所以应该先将其原始值保存下来
132 for (int i = 1; i <= temp; ++i)
133 {
134 DeleteElem(cir, 1); //删除temp次1号节点,即可把整个链表清空
135 } //删除过程中length已经在一直自减,所以不需要添加额外的length自减语句
136 }
137
138 void PrintListFromFirst(CircleList *cir) //从第一个元素开始遍历循环链表
139 {
140 Node *p = cir->head;
141 for (int i = 1; i <= cir->length; ++i)
142 {
143 p = p->next;
144 printf("%d ", p->element);
145 }
146 }
147
148 void PrintListFromPosition(CircleList *cir, int position) //从第position处的元素开始循环遍历整个链表
149 {
150 Node *p = cir->head;
151 for (int i = 1; i <= position; ++i)
152 p = p->next; //获取position位置处的指针p
153
154 Node *org = p; //用org记录p的原始位置,用于作为循环遍历的终止条件
155 do
156 {
157 printf("%d ", p->element);
158 p = p->next;
159 } while (p != org);
160 }
1 //main.c
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include "CircleList.h"
6
7 int main()
8 {
9 CircleList cir;
10 InitList(&cir);
11 PushBack(&cir, 1);
12 PushBack(&cir, 2);
13 PushBack(&cir, 3);
14 PushBack(&cir, 4);
15 PushBack(&cir, 5);
16 PushBack(&cir, 6);
17 PushBack(&cir, 7);
18 PushBack(&cir, 8);
19 InsertElem(&cir,5,777);
20
21 // ClearList(&cir);
22 // InsertElem(&cir, 5, 666);
23 // DeleteElem(&cir,8);
24 Node *p = cir.head -> next;
25 // Node* p =BackElem(&cir);
26 printf("%d\n", p->element);
27 Node *q = GetBack(&cir, p);
28 printf("%d\n", q->element);
29 Node *q2 = GetPrev(&cir, q);
30 printf("%d\n", q2->element);
31 // DeleteElem(&cir,7);
32 // PrintListFromFirst(&cir);
33 // PrintListFromPosition(&cir,8);
34 // printf("%d", cir.length);
35
36 return 0;
37 }