c语言实例 -- 循环链表

要求:

创建一个循环链表

下面是一个简单的循环链表(循环单链表)的C语言实现。循环链表是指链表的最后一个节点的指针指向第一个节点,形成一个环形结构。这种结构的优点是在一些特定的场景可以简化操作逻辑。

循环链表的基本操作

  1. 初始化循环链表
  2. 插入节点
  3. 删除节点
  4. 打印链表
  5. 销毁链表
#include <stdio.h>
#include <stdlib.h>

// 定义节点结构
typedef struct Node {
    int data;
    struct Node* next;
} Node;

// 初始化循环链表
Node* initialize() {
    Node* head = NULL;
    return head;
}

// 插入节点
void insert(Node** head, int data) {
    Node* newNode = (Node*)malloc(sizeof(Node));
    newNode->data = data;
    if (*head == NULL) {
        // 如果链表为空,新节点即为头节点
        *head = newNode;
        newNode->next = newNode;
    } else {
        Node* temp = *head;
        // 找到链表的最后一个节点
        while (temp->next != *head) {
            temp = temp->next;
        }
        temp->next = newNode; // 最后节点指向新节点
        newNode->next = *head; // 新节点指向头节点
    }
}

// 删除节点
void delete(Node** head, int key) {
    if (*head == NULL) return; // 如果链表为空,不做处理

    Node *temp = *head, *prev;

    // 如果头节点就是需要删除的节点
    if (temp->data == key) {
        // 找到最后一个节点,重新设置其next指针
        Node* last = *head;
        while (last->next != *head) {
            last = last->next;
        }
        if (*head == last) {
            free(*head);
            *head = NULL;
        } else {
            last->next = temp->next;
            *head = temp->next;
            free(temp);
        }
        return;
    }

    // 查找要删除的节点
    while (temp->next != *head && temp->data != key) {
        prev = temp;
        temp = temp->next;
    }

    // 如果找到了,删除节点
    if (temp->data == key) {
        prev->next = temp->next;
        free(temp);
    }
}

// 打印链表
void printList(Node* head) {
    if (head == NULL) return;
    Node* temp = head;
    do {
        printf("%d ", temp->data);
        temp = temp->next;
    } while (temp != head);
    printf("\n");
}

// 销毁链表
void destroyList(Node** head) {
    if (*head == NULL) return;

    Node* temp = *head;
    Node* next;

    // 先处理第二个节点开始的部分
    while (temp->next != *head) {
        next = temp->next;
        free(temp);
        temp = next;
    }
    // 最后处理头节点
    free(temp);
    *head = NULL;
}

// 主函数
int main() {
    Node* head = initialize();

    insert(&head, 10);
    insert(&head, 20);
    insert(&head, 30);

    printf("Circular Linked List: ");
    printList(head);

    delete(&head, 20);
    printf("After deletion of 20: ");
    printList(head);

    destroyList(&head);
    return 0;
}

讲解

  • 初始化循环链表:创建一个头节点的指针并将其初始化为NULL
  • 插入节点:向链表中插入新节点时,首先创建新节点并将数据填充。如果链表为空,则新节点的next指针指向自己;否则,找到最后一个节点并调整指针以连接新节点,使其形成环。
  • 删除节点:找到要删除的节点,如果是头节点,特别处理从temp->next开始的链表,调整最后一个节点的next,或者直接删除节点并重置头节点。如果不是头节点,则找到节点前的节点以调整其next指针。
  • 打印链表:从头节点开始,遍历链表直到回到头节点。
  • 销毁链表:释放所有节点的内存,循环释放直到再次回到头节点。

通过上面的代码,可以实现一个简单的循环链表,进行增删节点、遍历以及内存释放等基本操作。

情景设定:任务调度器

在很多嵌入式系统和实时操作系统中,经常需要多任务调度。例如,我们可以设想一个简单的定时任务调度器,在有限的硬件资源下循环顺序执行一组任务。我们可以使用循环链表来实现这种任务调度器,每个节点都表示一个待执行的任务。

每个任务执行后,将立即转移到下一个任务,形成一套循环的任务执行机制。这种设计能够保证所有任务被公平、持续地执行。

实现代码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> // 用于sleep函数

// 定义节点结构表示一个任务
typedef struct TaskNode {
    char* taskName;
    void (*execute)(void); // 指向任务执行函数的指针
    struct TaskNode* next;
} TaskNode;

// 初始化任务调度器
TaskNode* initializeScheduler() {
    return NULL;
}

// 添加任务
void addTask(TaskNode** head, char* taskName, void (*execute)(void)) {
    TaskNode* newTask = (TaskNode*)malloc(sizeof(TaskNode));
    newTask->taskName = taskName;
    newTask->execute = execute;

    if (*head == NULL) {
        *head = newTask;
        newTask->next = newTask;
    } else {
        TaskNode* temp = *head;
        while (temp->next != *head) {
            temp = temp->next;
        }
        temp->next = newTask;
        newTask->next = *head;
    }
}

// 删除任务
void deleteTask(TaskNode** head, char* taskName) {
    if (*head == NULL) return;

    TaskNode *current = *head, *prev = NULL;

    do {
        if (strcmp(current->taskName, taskName) == 0) {
            if (prev == NULL) {
                TaskNode* last = *head;
                while (last->next != *head) {
                    last = last->next;
                }
                if (current == last) {
                    free(current);
                    *head = NULL;
                } else {
                    last->next = current->next;
                    *head = current->next;
                    free(current);
                }
            } else {
                prev->next = current->next;
                free(current);
            }
            return;
        }
        prev = current;
        current = current->next;
    } while (current != *head);
}

// 任务调度循环
void runScheduler(TaskNode* head) {
    TaskNode* current = head;
    if (current == NULL) return;

    do {
        printf("Executing task: %s\n", current->taskName);
        current->execute();
        current = current->next;
        sleep(1); // 模拟任务切换间隔
    } while (current != head);
}

// 示例任务函数
void taskA() {
    printf("Task A is running.\n");
}

void taskB() {
    printf("Task B is running.\n");
}

void taskC() {
    printf("Task C is running.\n");
}

// 主函数
int main() {
    TaskNode* scheduler = initializeScheduler();

    addTask(&scheduler, "Task A", taskA);
    addTask(&scheduler, "Task B", taskB);
    addTask(&scheduler, "Task C", taskC);

    printf("Task Scheduler started\n");
    runScheduler(scheduler);

    deleteTask(&scheduler, "Task B");
    printf("\nTask B removed\n");

    runScheduler(scheduler);

    return 0;
}

讲解

  • 任务节点:每个节点存放一个任务的名称和其对应的执行函数。

  • 任务调度器的初始化:通过初始化函数创建一个空的任务链表,准备好后续任务的添加。

  • 添加任务:通过函数指针将具体任务的行为存储到节点中,并链接形成循环链表。

  • 删除任务:从链表中找到要删除的任务节点并释放内存,把链表重新链接。

  • 任务调度:通过runScheduler函数循环调用每个任务对应的函数,模拟任务被连续调度执行的过程。

此示例实现了一个简单的任务调度器,通过循环链表结构,可以公平地调度任务,并支持任务的增删。这在嵌入式系统中可以用于管理有限的周期性任务执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值