目录
循环链表的概念
循环链表是一种特殊的链表结构。它与普通链表不同的地方在于,最后一个节点指向第一个节点,形成了一个环。这也就意味着,在循环链表中,每个节点都有前驱节点和后继节点。循环链表既可以向前遍历,也可以向后遍历。
循环链表与单链表的区别
循环单链表和单链表的区别就是,需要查找尾结点,然后将尾结点的next域指向头结点并形成一个循环,单链表直接指向NULL即可。
循环链表的常用操作
-
头节点:循环链表第一个节点之前的节点,通常没有存储数据,主要作用是方便对循环链表的操作。
-
尾节点:循环链表最后一个节点,其next指针指向头节点。
-
插入元素:在指定位置插入新元素,需要修改前一个节点的next指针和新节点的next指针。
-
删除元素:删除指定位置的元素,需要修改前一个节点的next指针。
-
查找元素:从头节点开始遍历循环链表,直到找到目标元素或遍历完整个链表。
循环列表的实现
-
建立新的结点
typedef struct Node { int data; struct Node* next; } Node;.
-
循环链表的定义
typedef struct CircularLinkedList { Node* head; Node* tail; int length; } CircularLinkedList;
-
初始化循环链表
void init_circular_linked_list(CircularLinkedList* list) { list->head = NULL; list->tail = NULL; list->length = 0; }
-
循环链表的插入
// 在头部插入节点 void insert_at_start(CircularLinkedList* list, int data) { Node* new_node = (Node*)malloc(sizeof(Node)); new_node->data = data; new_node->next = list->head; list->head = new_node; list->length++; } // 在任意i位置处插入元素x void insert_at_position(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++; } // 在尾部插入节点 void insert_at_end(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++; } }
-
循环链表的删除
//删除指定值得节点 void delete_node(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_position(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 print_circular_linked_list(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 <string.h>
typedef struct Node {
int data;
struct Node* next;
} Node;
typedef struct CircularLinkedList {
Node* head;
Node* tail;
int length;
} CircularLinkedList;
void init_circular_linked_list(CircularLinkedList* list) {
list->head = NULL;
list->tail = NULL;
list->length = 0;
}
// 判断循环链表是否为空
int is_empty(CircularLinkedList* list) {
return list->length == 0;
}
// 在头部插入节点
void insert_at_start(CircularLinkedList* list, int data) {
Node* new_node = (Node*)malloc(sizeof(Node));
new_node->data = data;
new_node->next = list->head;
list->head = new_node;
list->length++;
}
// 在任意i位置处插入元素x
void insert_at_position(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++;
}
// 在尾部插入节点
void insert_at_end(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++;
}
}
// 返回循环链表长度
int get_length(CircularLinkedList* list) {
return list->length;
}
//删除指定值得节点
void delete_node(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_position(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 print_circular_linked_list(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[] = "\n\
★╭------╮☆☆☆☆☆☆╭------╮\n\
★╰╮八方来财╭╯◢ █ ◣◢ █ ◣╰╮期末高分╭╯\n\
★╭╯╰---╯╰╮██自 由██╭╯╰---╯╰╮\n\
★║◢ █ ◣◢ █ ◣║◥ █快乐█ ◤║◢ █ ◣◢ █ ◣║\n\
★║██████████║ ◥ ██ ◤ ║██████████║ \n\
★║◥ █真心█ ◤║ ║◥ █祝福█ ◤║\n\
★║ ◥ ██ ◤ ║☆ ☆ ☆ ☆ ☆║ ◥ ██ ◤ ║\n\
★║ ◥ ◤ ║☆ 事事如意☆ ║ ◥ ◤ ║\n\
\\ ☆ 祝我 . 也祝你!☆\n\n";
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;
init_circular_linked_list(&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("8. 打印循环链表\n");
printf("9. 帮助\n");
printf("0. 退出\n");
printf("请输入您要进行的操作(1~9,0退出):");
scanf("%d", &option);
switch (option) {
case 1:
printf("初始化成功!\n");
break;
case 2:
printf("请输入要添加的数值\n");
scanf("%d", &data);
insert_at_start(&list, data);
printf("添加成功!\n");
break;
case 3:
printf("请输入需要插入的位置和要添加的数值\n");
scanf("%d %d",&data,&position);
insert_at_position(&list,data,position);
printf("添加成功!\n");
break;
case 4: // 添加节点到循环链表
printf("请输入要添加的数值\n");
scanf("%d", &data);
insert_at_end(&list, data);
printf("添加成功!\n");
break;
case 5: // 查找节点
printf("请输入要查询的数值\n");
scanf("%d", &data);
int position = find_position(&list, data);
printf("元素: %d 发现在位置: %d.\n",data, find_position(&list, data));
break;
case 6: // 删除节点
printf("请输入要删除的位置\n");
scanf("%d", &position);
delete_node(&list,position);
printf("删除成功!\n");
break;
case 7: // 获取循环链表的长度
printf("循环链表的长度为: %d\n", get_length(&list));
break;
case 8:
print_circular_linked_list(&list);// 打印循环链表
break;
case 9:
printf(" 本程序为循环链表的演示程序,由王路平编写!\n");
break;
case 0: // 退出程序
printf("Exiting program...\n");
break;
default: // 处理无效选项
printf("Invalid option entered. Please enter a valid option.\n");
break;
}
} while (option != 0); // 当用户选择退出程序时,结束循环
return 0;
}
效果图 ![](https://img-blog.csdnimg.cn/d2549b7f0eea4f1fa0f69077701396a0.jpeg)
小结
循环列表的概念:循环链表是一种特殊的链表结构。它与普通链表不同的地方在于,最后一个节点指向第一个节点,形成了一个环。这也就意味着,在循环链表中,每个节点都有前驱节点和后继节点。循环链表既可以向前遍历,也可以向后遍历。循环列表的优点就是从链尾到链头比较方便。比如需要处理的数据具有环形结构特点时,用循环列表就非常合适。虽然单链表也可以实现,但是循环链表的代码要简洁的多。
参考文献
第二章——单链表和循环单链表_循环链表和单链表的区别-CSDN博客
C语言数据结构——循环链表_c 实现循环链表_管不住嘴的小吃货的博客-CSDN博客
百度,书本等