一、循环链表的定义
循环链表是一种特殊类型的链表,其中最后一个节点指向第一个节点,形成一个循环。
二、循环链表的特点
(1)链表中的最后一个节点指向第一个节点,形成循环。
(2)节点间的连接是双向的,即每个节点有两个指针,一个指向前一个节点,另一个指向后一个节点。
(3)可以在链表的任意位置插入和删除节点,操作灵活。
三、循环链表的实现
(1)内存分配
首先需要分配一段内存空间用于存储循环链表,这段内存空间中包含多个节点的信息,每个节点包含数据域和指针域。
(2)创建循环链表
创建循环链表时,需要将最后一个节点的指针指向第一个节点,形成一个环状结构。
(3)查找某元素的位置
在循环链表中查找某个元素的位置可以使用线性搜索算法,从头节点开始依次遍历每个节点,直到找到目标元素或遍历到最后一个节点。
四、循环链表的应用
(1)存储数据:循环链表可以用来存储大量的数据,这些数据可以是有序的,也可以是无序的。
(2)遍历数据:对于存储在循环链表中的数据,我们可以使用不同的遍历算法来对其进行遍历,比如前序遍历、中序遍历和后序遍历等。
(3)处理数据:循环链表可以用来对数据进行各种处理,比如插入、删除、修改等操作。
五、循环链表的基本操作
1. 创建新的节点
创建节点是循环链表实现的第一步。每个节点包含两个部分:数据部分和指针部分。数据部分用于存储元素,指针部分用于指向下一个节点。
下面是一个创建节点的示例代码:
typedef struct Node {
int data;
struct Node* next;
} Node;.
2. 定义循环链表
循环链表是由多个节点组成的,每个节点都指向下一个节点,最后一个节点指向第一个节点。
下面是一个创建循环链表的示例代码:
typedef struct CircularLinkedList {
Node* head;
Node* tail;
int length;
} CircularLinkedList;
3. 初始化循环链表
循环链表的初始化需要定义一个链表节点结构体,包含数据域和指针域(分别指向前一个节点和后一个节点),然后定义循环链表结构体。
下面是一个添加元素的示例代码:
void initList(CircularLinkedList* list) {
list->head = NULL;
list->tail = NULL;
list->length = 0;
}
4. 循环链表的插入
(1)中间节点插入
中间节点插入是指将一个新的节点插入到循环链表中间的任意位置。
// 在任意i位置处插入元素x
void addPos(CircularLinkedList* list, int x, int i) {
Node* new_node = (Node*)malloc(sizeof(Node));
new_node->data = x;
new_node->next = NULL;
if (i == 0) {
new_node->next = list->head;
list->head = new_node;
if (list->tail == NULL) {
list->tail = new_node;
}
} else {
Node* temp = list->head;
int count = 0;
while (temp != NULL && count < i-1) {
temp = temp->next;
count++;
}
if (temp == NULL) {
new_node->next = list->tail;
list->tail->next = new_node;
list->tail = new_node;
} else {
new_node->next = temp->next;
temp->next = new_node;
}
}
list->length++;
}
(2)尾节点插入
尾节点插入是指将一个新的节点插入到循环链表的尾部,即链表的最后一个节点。
// 在尾部插入节点
void addBottom(CircularLinkedList* list, int data) {
Node* new_node = (Node*)malloc(sizeof(Node));
new_node->data = data;
new_node->next = NULL;
if (is_empty(list)) {
list->head = new_node;
list->tail = new_node;
list->length++;
} else {
list->tail->next = new_node;
list->tail = new_node;
list->length++;
}
}
5、循环链表的删除
(1)删除其它节点
} else { // 删除其他节点
previous->next = current->next;
if (list->length == 1) {
list->tail = previous;
}
}
free(current);
list->length--;
}
(2)删除指定值得节点
//删除指定值得节点
void deletes(CircularLinkedList* list, int data) {
Node* current = list->head;
Node* previous = NULL;
while (current != NULL && current->data != data) {
previous = current;
current = current->next;
}
if (current == NULL) { // 没有找到要删除的节点
printf("Element not found.\n");
return;
}
6、循环链表的查询
// 查找指定值x所在的位置i
int find(CircularLinkedList* list, int x) {
Node* current = list->head;
int position = 0;
while (current != NULL) {
if (current->data == x) {
return position;
}
current = current->next;
position++;
}
return -1; // 没有找到要查找的元素就让他在前移
}
7、循环链表的输出
void printList(CircularLinkedList* list) {
Node* node = list->head;
int i;
for (i = 0; i < list->length; i++) {
printf("%d ", node->data);
node = node->next;
if (node == list->head) break; // 循环链表结束,退出循环
}
printf("\n");
}
六、完整的代码
#include <stdio.h>
#include <stdlib.h>
#include<cstring>
typedef struct Node {
int data;
struct Node* next;
} Node;
typedef struct CircularLinkedList {
Node* head;
Node* tail;
int length;
} CircularLinkedList;
//初始化
void initList(CircularLinkedList* list) {
list->head = NULL;
list->tail = NULL;
list->length = 0;
}
// 判断循环链表是否为空
int is_empty(CircularLinkedList* list) {
return list->length == 0;
}
// 在尾部插入节点
void addBottom(CircularLinkedList* list, int data) {
Node* new_node = (Node*)malloc(sizeof(Node));
new_node->data = data;
new_node->next = NULL;
if (is_empty(list)) {
list->head = new_node;
list->tail = new_node;
list->length++;
} else {
list->tail->next = new_node;
list->tail = new_node;
list->length++;
}
}
// 在位置i处插入元素x
void addPos(CircularLinkedList* list, int x, int i) {
Node* new_node = (Node*)malloc(sizeof(Node));
new_node->data = x;
new_node->next = NULL;
if (i == 0) { // Insertion at the start
new_node->next = list->head;
list->head = new_node;
if (list->tail == NULL) { // If list is empty, update tail pointer as well
list->tail = new_node;
}
} else { // Insertion in the middle or at the end
Node* temp = list->head;
int count = 0;
while (temp != NULL && count < i-1) {
temp = temp->next;
count++;
}
if (temp == NULL) { // Insertion at the end
new_node->next = list->tail;
list->tail->next = new_node;
list->tail = new_node;
} else { // Insertion in the middle
new_node->next = temp->next;
temp->next = new_node;
}
}
list->length++; // Increment list length
}
// 返回循环链表长度
int length(CircularLinkedList* list) {
return list->length;
}
//删除指定值得节点
void deletes(CircularLinkedList* list, int data) {
Node* current = list->head;
Node* previous = NULL;
while (current != NULL && current->data != data) {
previous = current;
current = current->next;
}
if (current == NULL) { // 没有找到要删除的节点
printf("Element not found.\n");
return;
}
if (previous == NULL) { // 删除头节点
list->head = current->next;
if (list->length == 1) {
list->tail = NULL;
}
} else { // 删除其他节点
previous->next = current->next;
if (list->length == 1) {
list->tail = previous;
}
}
free(current);
list->length--;
}
// 查找指定值x所在的位置i
int find(CircularLinkedList* list, int x) {
Node* current = list->head;
int position = 0;
while (current != NULL) {
if (current->data == x) {
return position;
}
current = current->next;
position++;
}
return -1; // 没有找到要查找的元素
}
// 打印循环链表
void printList(CircularLinkedList* list) {
Node* node = list->head;
int i;
for (i = 0; i < list->length; i++) {
printf("%d ", node->data);
node = node->next;
if (node == list->head) break; // 循环链表结束,退出循环
}
printf("\n");
}
int main() {
char welcome[] = "太难了(T▽T)(T▽T)(T▽T)(ㄒoㄒ)(ㄒoㄒ)(ㄒoㄒ)";
int i = 0;
int m = 0;
int n = 0;
for(i=0;i<strlen(welcome);i++)
{
printf("%c",welcome[i]);
for(m=0;m<10000;m++)
for(n=0;n<1000;n++)
{
;
}
}
printf("\n\n\n");
int data;
int position;
int option;
CircularLinkedList list;
initList(&list);
do {
printf("\-----------顺序表演示程序----------\n");
printf("1. 初始化顺序表\n");
printf("2. 尾插法\n");
printf("3. 中间插入法\n");
printf("4. 删除\n");
printf("5. 查询\n");
printf("6. 循环链表的长度\n");
printf("7. 打印循环链表\n");
printf("10. 帮助\n");
printf("0. 退出\n");
printf("请输入您要进行的操作(1~7,0退出):");
scanf("%d", &option);
switch (option) {
case 1:
printf("初始化成功!\n");
break;
case 2:
printf("请输入要添加的数值\n");
scanf("%d", &data);
addBottom(&list, data);
printf("添加成功!\n");
break;
case 3:
printf("请输入要添加的数值和需要插入的位置\n");
scanf("%d %d", &data,&position);
addPos(&list,data,position);
printf("添加成功!\n");
break;
case 4:
printf("请输入要删除的数值\n");
scanf("%d", &data);
deletes(&list, data);
printf("删除成功!\n");
break;
case 5:
{
printf("请输入要查询的数值\n");
scanf("%d", &data);
int position = find(&list, data);
printf("Element %d found at position %d.\n",data, find(&list, data));
}
break;
case 6:
{
int l = length(&list);
printf("循环链表的长度为: %d\n", l);
}
break;
case 7:
printList(&list);
break;
case 10:
printf(" 本程序为链表的演示程序,由王蕊设计开发");
break;
case 0:
printf("退出!\n");
break;
default:
printf("没有这个选项!\n");
break;
}
} while (option != 0);
return 0;
}
七、运行结果
八、小结
C语言循环链表是一种重要的数据结构,它通过形成一个闭环来存储和操作数据。循环链表具有广泛的应用场景,例如在各类搜索算法中作为数据结构后端,以及在文件系统等领域。循环链表的主要优点是其空间利用率高,可以避免存储空链表节点的空间浪费。
九、参考文献
[1] 严蔚敏, 吴伟民. 数据结构(C语言版)[M]. 北京: 清华大学出版社, 2018.
[2] 耿国华. 数据结构与算法(C语言版)[M]. 北京: 高等教育出版社, 2016.