C语言“仅有尾指针”的单循环链表和“仅有头指针”的单循环链表

文章详细介绍了单循环链表中仅尾指针和仅头指针的实现方式,分析了它们在插入、删除和访问节点时的时间复杂性,强调了两者在效率上的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include <stdio.h>
#include <stdlib.h>

// 单循环链表节点定义
struct Node {
    int data;             // 节点存储的数据
    struct Node* next;    // 指向下一个节点的指针
};

// 创建仅有尾指针的单循环链表
struct Node* createListWithTail(int data) {
    // 创建新节点
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    newNode->data = data;
    newNode->next = newNode;  // 将next指针指向自身,形成循环

    return newNode;  // 返回头节点指针
}

// 在仅有尾指针的单循环链表的末尾添加节点
void appendToListWithTail(struct Node** tail, int data) {
    // 创建新节点
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    newNode->data = data;
    newNode->next = (*tail)->next;  // 将新节点的next指针指向头节点
    (*tail)->next = newNode;  // 将尾节点的next指针指向新节点
    *tail = newNode;  // 更新尾指针为新节点
}

// 遍历并打印仅有尾指针的单循环链表
void printListWithTail(struct Node* tail) {
    struct Node* current = tail->next;  // 从头节点开始遍历
    do {
        printf("%d ", current->data);
        current = current->next;
    } while (current != tail->next);  // 遍历直到回到头节点
}

// 创建仅有头指针的单循环链表
struct Node* createListWithHead(int data) {
    // 创建新节点
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    newNode->data = data;
    newNode->next = newNode;  // 将next指针指向自身,形成循环

    return newNode;  // 返回头节点指针
}

// 在仅有头指针的单循环链表的末尾添加节点
void appendToListWithHead(struct Node* head, int data) {
    // 创建新节点
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    newNode->data = data;
    newNode->next = head;  // 将新节点的next指针指向头节点

    // 遍历链表,找到最后一个节点
    struct Node* current = head;
    while (current->next != head) {
        current = current->next;
    }

    current->next = newNode;  // 将最后一个节点的next指针指向新节点
}

// 遍历并打印仅有头指针的单循环链表
void printListWithHead(struct Node* head) {
    struct Node* current = head;
    do {
        printf("%d ", current->data);
        current = current->next;
    } while (current != head);  // 遍历直到回到头节点
}

int main() {
    // 创建并操作仅有尾指针的单循环链表
    struct Node* tailList = createListWithTail(1);
    appendToListWithTail(&tailList, 2);
    appendToListWithTail(&tailList, 3);
    printListWithTail(tailList);

    printf("\n");

    // 创建并操作仅有头指针的单循环链表
    struct Node* headList = createListWithHead(1);
    appendToListWithHead(headList, 2);
    appendToListWithHead(headList, 3);
    printListWithHead(headList);

    return 0;
}

仅有尾指针的单循环链表和仅有头指针的单循环链表之间的区别:

1. 仅有尾指针的单循环链表:
   - 这种类型的链表只有一个指针,即尾指针,用于指向链表的尾部节点。
   - 在插入和删除节点时,由于只需要修改尾节点的指针,所以操作相对简单,时间复杂度为O(1)。
   - 但在访问链表中的节点时,需要从尾节点开始遍历整个链表,直到回到尾节点,时间复杂度为O(n),其中n是链表的长度。

2. 仅有头指针的单循环链表:
   - 这种类型的链表只有一个指针,即头指针,用于指向链表的头部节点。
   - 在插入和删除节点时,需要先遍历链表找到尾节点,然后再进行操作,时间复杂度为O(n)。
   - 在访问链表中的节点时,只需要从头节点开始遍历整个链表,直到回到头节点,时间复杂度为O(n),其中n是链表的长度。

因此,仅有尾指针的单循环链表在插入和删除节点时更加高效,但在访问节点时较慢;而仅有头指针的单循环链表在插入和删除节点时较慢,但在访问节点时更加高效。

数据结构中,队列是一种先进先出(FIFO, First In First Out)的线性表。使用带节点的单循环链表来表示队列是一种常见的方法,因为它可以简化队列操作的处理。以下是带节点的单循环链表表示队列的实现方法: ### 节点结构 首先,我们需要定义链表的节点结构: ```c typedef struct Node { int data; struct Node* next; } Node; ``` ### 队列结构 接下来,定义队列结构,其中包含指向队列尾的指针: ```c typedef struct Queue { Node* front; // 指向队列节点 Node* rear; // 指向队列尾节点 } Queue; ``` ### 初始化队列 初始化队列时,我们需要创建一个带节点的单循环链表: ```c void initQueue(Queue* q) { q->front = q->rear = (Node*)malloc(sizeof(Node)); q->front->next = q->front; // 初始化时,节点指向自身 } ``` ### 入队操作 入队操作将新节点添加到队列尾部: ```c void enqueue(Queue* q, int value) { Node* newNode = (Node*)malloc(sizeof(Node)); newNode->data = value; newNode->next = q->front; // 新节点指向节点 q->rear->next = newNode; // 原尾节点指向新节点 q->rear = newNode; // 更新尾节点指针 } ``` ### 出队操作 出队操作从队列部移除节点: ```c int dequeue(Queue* q) { if (q->front == q->rear) { printf("Queue is empty\n"); return -1; // 队列为空 } Node* temp = q->front->next; int value = temp->data; q->front->next = temp->next; if (q->rear == temp) { q->rear = q->front; // 如果出队的是最后一个节点,更新尾节点指针 } free(temp); return value; } ``` ### 打印队列 打印队列中的所有元素: ```c void printQueue(Queue* q) { if (q->front == q->rear) { printf("Queue is empty\n"); return; } Node* current = q->front->next; while (current != q->front) { printf("%d ", current->data); current = current->next; } printf("\n"); } ``` ### 总结 通过上述方法,我们可以使用带节点的单循环链表来表示队列。这种方法简化了队列操作,并且避免了队列为空只有一个节点时的特殊情况处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LLZWHS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值