C语言循环链表的原理与使用操作

C语言循环链表是一种基于链表数据结构的可循环访问的存储方式。与线性表相比,链表能够优化数据的插入和删除操作的效率,并且支持动态的内存分配。而循环链表则定义了表头尾相接,最后一个节点指向第一个节点的链表。下面将详细讲解循环链表的原理、使用操作及其实现过程,以及两个示例进行说明。

原理

循环链表是由多个节点组成的链式结构,每个节点包含自身的数据和指向下一个节点的指针。其最后一个节点的指针指向第一个节点,形成了一个环形结构。这种结构具有更好的复用性和高效性,可以被广泛地应用于各个领域的数据结构。

实现步骤

  1. 定义链表节点结构体

    c
    typedef struct node {
    int data;
    struct node* next;
    } Node;

  2. 插入节点

    首先需要定义一个指向链表头的指针,开始时为空。

    c
    Node* head = NULL;

    要插入一个节点,需要先找到要插入的位置,在循环链表中,插入节点的方式与单链表和双链表相同。

    ```c
    void insert(Node head, int data, int pos) {
    Node
    new_node = (Node
    )malloc(sizeof(Node));
    new_node->data = data;
    new_node->next = NULL;

    if (*head == NULL) { // 链表为空,直接插入
        *head = new_node;
        (*head)->next = *head;
        return;
    }
    
    if (pos == 0) { // 插入头部
        new_node->next = (*head)->next;
        (*head)->next = new_node;
        int temp = (*head)->data;
        (*head)->data = new_node->data;
        new_node->data = temp;
        return;
    }
    
    Node* current = (*head);
    for (int i = 1; i < pos; i++) {
        current = current->next;
    }
    
    new_node->next = current->next;
    current->next = new_node;
    

    }
    ```

  3. 删除节点

    与插入节点类似,删除节点也需要找到要删除的位置。因为需要删除的是链表节点,而链表的节点是通过指针实现的,因此需要记录上一个节点的指针。

    ```c
    void delete (Node* head, int pos) {
    if (
    head == NULL) { // 链表为空,什么也不做
    return;
    }

    Node* current = (*head);
    Node* previous = NULL;
    
    if (pos == 0) { // 删除头部节点
        while (current->next != *head) {
            current = current->next;
        }
        Node* node_to_delete = *head;
        current->next = (*head)->next;
        *head = (*head)->next;
        free(node_to_delete);
        return;
    }
    
    for (int i = 1; i <= pos; i++) {
        previous = current;
        current = current->next;
    
        if (current == *head && i != pos) { // 节点不存在
            return;
        }
    }
    
    previous->next = current->next;
    free(current);
    

    }
    ```

  4. 遍历链表

    循环链表的遍历有一个特殊之处,因为循环链表的尾部是指向头部的,因此需要对链表头特殊处理。

    ```c
    void display(Node* head) {
    if (head == NULL) { // 链表为空
    printf("List is empty.\n");
    return;
    }

    Node* current = head;
    do {
        printf("%d ", current->data);
        current = current->next;
    } while (current != head);
    printf("\n");
    

    }
    ```

示例1

下面的示例描述了如何创建一个循环链表,并将数据插入到链表中。

int main() {
    Node* head = NULL;
    int choice, data, position;
    printf("Welcome to the circular linked list implementation.\n");
    while (1) {
        printf("Enter 1 to insert a node\n");
        printf("Enter 2 to delete a node\n");
        printf("Enter 3 to display the list\n");
        printf("Enter 4 to exit\n");
        scanf("%d", &choice);
        switch (choice) {
            case 1:
                printf("Enter the data:");
                scanf("%d", &data);
                printf("Enter the position:");
                scanf("%d", &position);
                insert(&head, data, position);
                break;
            case 2:
                printf("Enter the position:");
                scanf("%d", &position);
                delete (&head, position);
                break;
            case 3:
                display(head);
                break;
            case 4:
                printf("Bye!\n");
                return 0;
            default:
                printf("Invalid choice! Please try again.\n");
        }
        printf("\n");
    }
}

示例2

下面是一个示例,使用循环链表实现一个循环队列。

#define MAX_QUEUE_SIZE 10

typedef struct queue {
    int items[MAX_QUEUE_SIZE];
    int front;
    int rear;
} Queue;

Queue* create_queue();
void enqueue(Queue* queue, int item);
int dequeue(Queue* queue);
void display(Queue* queue);

int main() {
    Queue* queue = create_queue();
    int choice, item;
    printf("Welcome to the circular queue implementation.\n");
    while (1) {
        printf("Enter 1 to enqueue an item\n");
        printf("Enter 2 to dequeue an item\n");
        printf("Enter 3 to display the queue\n");
        printf("Enter 4 to exit\n");
        scanf("%d", &choice);
        switch (choice) {
            case 1:
                printf("Enter the item:");
                scanf("%d", &item);
                enqueue(queue, item);
                break;
            case 2:
                item = dequeue(queue);
                if (item != -1) {
                    printf("Dequeued item is %d\n", item);
                }
                break;
            case 3:
                display(queue);
                break;
            case 4:
                printf("Bye!\n");
                return 0;
            default:
                printf("Invalid choice! Please try again.\n");
        }
        printf("\n");
    }
}

Queue* create_queue() {
    Queue* queue = (Queue*)malloc(sizeof(Queue));
    queue->front = -1;
    queue->rear = -1;
    return queue;
}

void enqueue(Queue* queue, int item) {
    if ((queue->rear + 1) % MAX_QUEUE_SIZE == queue->front) { // 队列满
        printf("Queue is full.\n");
        return;
    }
    if (queue->front == -1) { // 队列为空
        queue->front = 0;
        queue->rear = 0;
    } else {
        queue->rear = (queue->rear + 1) % MAX_QUEUE_SIZE;
    }
    queue->items[queue->rear] = item;
}

int dequeue(Queue* queue) {
    if (queue->front == -1) { // 队列为空
        printf("Queue is empty.\n");
        return -1;
    }
    int item = queue->items[queue->front];
    if (queue->front == queue->rear) { // 队列中只有一个元素
        queue->front = -1;
        queue->rear = -1;
    } else {
        queue->front = (queue->front + 1) % MAX_QUEUE_SIZE;
    }
    return item;
}

void display(Queue* queue) {
    if (queue->front == -1) { // 队列为空
        printf("Queue is empty.\n");
        return;
    }
    int i;
    for (i = queue->front; i != queue->rear; i = (i + 1) % MAX_QUEUE_SIZE) {
        printf("%d ", queue->items[i]);
    }
    printf("%d ", queue->items[i]);
    printf("\n");
}

以上两个示例详细说明了循环链表的原理、使用操作和实现过程,希望能对读者有所帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言循环链表的原理与使用操作 - Python技术站

(0)
上一篇 2023年5月24日
下一篇 2023年5月24日

相关文章

  • C语言快速幂取模算法小结

    C语言快速幂取模算法小结 快速幂算法是用来加速计算 a^n 的算法,它可以使计算复杂度从O(n)降为O(logn),因此在需要对 a^n 进行大量计算时非常有用。而在取模运算中,快速幂算法同样适用,因为我们可以在计算时对中间结果进行模运算的操作,这样可以避免数值溢出。 算法说明 快速幂取模算法的实现中主要有以下几个步骤: 如果n等于0,直接返回1。 如果n为…

    C 2023年5月23日
    00
  • C语言实现贪吃蛇小游戏

    下面是关于“C语言实现贪吃蛇小游戏”的完整攻略,包含以下几个方面的内容: 1.准备工作 在开始实现贪吃蛇游戏之前,需要准备好所需的开发环境和工具,包括 C 语言编译器、代码编辑器等。 2.实现游戏的基本框架 在实现贪吃蛇游戏的基本框架时,需要考虑游戏整体的结构和功能。通常包括游戏的界面、游戏的逻辑、游戏的音效等。 其中,实现游戏的逻辑是比较复杂的部分。通常需…

    C 2023年5月23日
    00
  • Windows系统出现致命错误C0000034正在更新操作174的解决方法

    Windows系统出现致命错误C0000034正在更新操作174的解决方法 问题描述 在Windows系统更新期间,用户可能会遇到以下错误提示: Windows系统出现致命错误C0000034正在更新操作174 出现这种错误提示时,系统更新进程会在一段时间后终止,并回滚所有进行的更改,导致系统无法更新。 解决方法 以下是解决此问题的步骤: 步骤 1:进入WI…

    C 2023年5月30日
    00
  • Linux中使用VS Code编译调试C++项目详解

    下面我将详细讲解如何在Linux中使用VS Code编译调试C++项目。 准备工作 安装VS Code 首先,我们需要安装一个文本编辑器,这里我们选择VS Code。可以到官网下载 Visual Studio Code。 下载完成后,解压安装文件并将其保存在可执行路径中(例如/usr/local/bin),使其能够在终端中运行。 安装C++编译器 接下来,我…

    C 2023年5月23日
    00
  • Android中RecyclerView拖拽、侧删功能的实现代码

    下面是关于“Android中RecyclerView拖拽、侧删功能的实现代码”的完整攻略。 RecyclerView基础 在介绍实现RecyclerView拖拽、侧删功能之前,先简单介绍一下RecyclerView的基础知识。 RecyclerView是Android提供的新的可复用列表控件,使用了一个LayoutManager来管理Item的样式,数据由A…

    C 2023年5月22日
    00
  • C语言实现小型电子词典

    C语言实现小型电子词典攻略 项目概述 这是一个使用C语言实现的小型电子词典,它可以通过命令行窗口输入单词并查询其对应的中文翻译。本词典基于哈希表实现。哈希表是一种数据结构,可以快速地进行查询和插入操作,因此非常适合用于实现词典这样的查询应用。 实现步骤 1. 读取词典文件 首先需要从词典文件中读取单词和对应的中文翻译,这里推荐使用标准数据格式JSON来存储词…

    C 2023年5月23日
    00
  • gin 获取post请求的json body操作

    获取post请求的json body操作指的是在网站的后端处理中,从请求中获取客户端使用POST方式提交的JSON数据。在Gin框架中,可以使用以下步骤来实现该操作。 1. 引入相关库 在Go中,可以使用标准库encoding/json来处理JSON数据。为了在Gin框架中方便处理JSON数据,需要引入github.com/gin-gonic/gin库。 i…

    C 2023年5月23日
    00
  • C语言自定义类型详解(结构体、枚举、联合体和位段)

    C语言自定义类型详解 C语言中自定义类型是构建代码结构的关键组成部分。一个程序中定义的自定义类型,可以用来描述程序中的状态和数据,使程序更加清晰和易于维护。C语言中的自定义类型有结构体、枚举、联合体和位段等。本文将为大家详细讲解C语言中这四种自定义类型的使用和应用场景。 结构体 定义结构体 结构体是用于存储多个不同数据类型的变量的自定义类型。例如,一个保存学…

    C 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部