详解循环链表

定义

循环链表是一种链表,其中最后一个节点的指针指向第一个节点,形成一个环形结构。

特点

  1. 最后一个节点的指针指向第一个节点,形成一个环形结构。
  2. 可以通过任意一个节点遍历整个链表。
  3. 插入和删除节点时,需要特别注意头节点和尾节点的处理等。

循环链表操作

  1. 头节点
  2. 尾节点
  3. 指定位置插入
  4. 删除元素
  5. 查找元素
  6. 遍历输出链表

循环链表的实现

 初始化链表

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;
}

小结

  1. 循环链表是一种特殊的链表,它的最后一个节点指向头节点,形成一个循环的环状结构。
  2. 循环链表可以通过头指针来访问链表的任意位置,而不仅仅是从头节点开始。
  3. 插入节点的操作和普通链表类似,可以在链表的头部、尾部或指定位置插入节点。
  4. 删除节点的操作也与普通链表类似,可以根据节点的值来删除节点。
  5. 查找节点的操作也与普通链表类似,可以根据节点的值来查找节点是否存在。
  6. 遍历循环链表时,需要注意循环的终止条件,即当遍历到头节点时结束循环。

参考资料

主要参考各种搜索引擎及AI

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值