定义
循环链表是一种链表,其中最后一个节点的指针指向第一个节点,形成一个环形结构。
特点
- 最后一个节点的指针指向第一个节点,形成一个环形结构。
- 可以通过任意一个节点遍历整个链表。
- 插入和删除节点时,需要特别注意头节点和尾节点的处理等。
循环链表操作
- 头节点
- 尾节点
- 指定位置插入
- 删除元素
- 查找元素
- 遍历输出链表
循环链表的实现
初始化链表
typedef struct Node {
int data;
struct Node* next;
} Node;
// 初始化链表
void initialize(Node** head) {
*head = NULL;
}
头插法插入节点
// 头插法插入节点
void insertAtHead(Node** head, int value) {
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = value;
if (*head == NULL) {
*head = newNode;
newNode->next = *head;
}
else {
Node* current = *head;
while (current->next != *head) {
current = current->next;
}
newNode->next = *head;
current->next = newNode;
*head = newNode;
}
}
尾插法插入节点
// 尾插法插入节点
void insertAtTail(Node** head, int value) {
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = value;
if (*head == NULL) {
*head = newNode;
newNode->next = *head;
}
else {
Node* current = *head;
while (current->next != *head) {
current = current->next;
}
current->next = newNode;
newNode->next = *head;
}
}
在位置i插入元素
// 在位置i插入元素
void insertAtPosition(Node** head, int value, int position) {
int length = getLength(*head);
if (position < 0 || position > length) {
printf("无效的位置\n");
return;
}
if (position == 0) {
insertAtHead(head, value);
}
else if (position == length) {
insertAtTail(head, value);
}
else {
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = value;
Node* current = *head;
int i = 0;
while (i < position - 1) {
current = current->next;
i++;
}
newNode->next = current->next;
current->next = newNode;
}
}
运行结果
删除元素
// 删除元素
void delete(Node** head, int value) {
if (*head == NULL) {
printf("链表为空\n");
return;
}
Node* temp = *head;
Node* prev = NULL;
do {
if (temp->data == value) {
if (temp == *head) {
*head = temp->next;
}
prev->next = temp->next;
free(temp);
return;
}
prev = temp;
temp = temp->next;
} while (temp != *head);
printf("链表中没有该元素\n");
}
运行结果
查找元素
// 查找元素
int search(Node* head, int value) {
if (head == NULL) {
printf("链表为空\n");
return 0;
}
Node* current = head;
do {
if (current->data == value) {
return 1;
}
current = current->next;
} while (current != head);
return 0;
}
遍历输出链表
// 遍历链表
void traverse(Node* head) {
if (head == NULL) {
printf("链表为空\n");
return;
}
Node* current = head;
do {
printf("%d ", current->data);
current = current->next;
} while (current != head);
printf("\n");
}
完整的Demo
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node* next;
} Node;
// 初始化链表
void initialize(Node** head) {
*head = NULL;
}
// 获取链表长度
int getLength(Node* head) {
int length = 0;
Node* current = head;
if (head == NULL) {
return length;
}
do {
length++;
current = current->next;
} while (current != head);
return length;
}
// 头插法插入节点
void insertAtHead(Node** head, int value) {
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = value;
if (*head == NULL) {
*head = newNode;
newNode->next = *head;
} else {
Node* current = *head;
while (current->next != *head) {
current = current->next;
}
newNode->next = *head;
current->next = newNode;
*head = newNode;
}
}
// 尾插法插入节点
void insertAtTail(Node** head, int value) {
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = value;
if (*head == NULL) {
*head = newNode;
newNode->next = *head;
} else {
Node* current = *head;
while (current->next != *head) {
current = current->next;
}
current->next = newNode;
newNode->next = *head;
}
}
// 在位置i插入元素
void insertAtPosition(Node** head, int value, int position) {
int length = getLength(*head);
if (position < 0 || position > length) {
printf("无效的位置\n");
return;
}
if (position == 0) {
insertAtHead(head, value);
} else if (position == length) {
insertAtTail(head, value);
} else {
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = value;
Node* current = *head;
int i = 0;
while (i < position - 1) {
current = current->next;
i++;
}
newNode->next = current->next;
current->next = newNode;
}
}
// 删除元素
void delete(Node** head, int value) {
if (*head == NULL) {
printf("链表为空\n");
return;
}
Node* temp = *head;
Node* prev = NULL;
do {
if (temp->data == value) {
if (temp == *head) {
*head = temp->next;
}
prev->next = temp->next;
free(temp);
return;
}
prev = temp;
temp = temp->next;
} while (temp != *head);
printf("链表中没有该元素\n");
}
// 查找元素
int search(Node* head, int value) {
if (head == NULL) {
printf("链表为空\n");
return 0;
}
Node* current = head;
do {
if (current->data == value) {
return 1;
}
current = current->next;
} while (current != head);
return 0;
}
// 遍历链表
void traverse(Node* head) {
if (head == NULL) {
printf("链表为空\n");
return;
}
Node* current = head;
do {
printf("%d ", current->data);
current = current->next;
} while (current != head);
printf("\n");
}
int main() {
Node* head;
int choice, value, position;
initialize(&head);
while(1) {
printf("1. 头插法插入节点\n");
printf("2. 尾插法插入节点\n");
printf("3. 在位置i插入元素\n");
printf("4. 删除元素\n");
printf("5. 查找元素\n");
printf("6. 输出链表\n");
printf("0. 退出程序\n");
printf("请输入你的选择:");
scanf("%d", &choice);
switch(choice) {
case 1:
printf("请输入要插入的节点值:");
scanf("%d", &value);
insertAtHead(&head, value);
break;
case 2:
printf("请输入要插入的节点值:");
scanf("%d", &value);
insertAtTail(&head, value);
break;
case 3:
printf("请输入要插入的节点值:");
scanf("%d", &value);
printf("请输入要插入的位置:");
scanf("%d", &position);
insertAtPosition(&head, value, position);
break;
case 4:
printf("请输入要删除的节点值:");
scanf("%d", &value);
delete(&head, value);
break;
case 5:
printf("请输入要查找的节点值:");
scanf("%d", &value);
if (search(head, value)) {
printf("链表中存在该元素\n");
} else {
printf("链表中不存在该元素\n");
}
break;
case 6:
traverse(head);
break;
case 0:
exit(0);
default:
printf("无效的选择\n");
}
}
return 0;
}
小结
- 循环链表是一种特殊的链表,它的最后一个节点指向头节点,形成一个循环的环状结构。
- 循环链表可以通过头指针来访问链表的任意位置,而不仅仅是从头节点开始。
- 插入节点的操作和普通链表类似,可以在链表的头部、尾部或指定位置插入节点。
- 删除节点的操作也与普通链表类似,可以根据节点的值来删除节点。
- 查找节点的操作也与普通链表类似,可以根据节点的值来查找节点是否存在。
- 遍历循环链表时,需要注意循环的终止条件,即当遍历到头节点时结束循环。
参考资料
主要参考各种搜索引擎及AI