详解循环链表

一、循环链表的定义

循环链表是一种特殊类型的链表,其中最后一个节点指向第一个节点,形成一个循环。

二、循环链表的特点

(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.

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值