数据结构 | 单循环链表

一、认识单循环链表

单循环链表是带头结点的单链表 + 闭环设计,尾节点不再指向 NULL,而是回头指向头结点,形成一个首尾相连的环。

这种结构最大的优势:可以从任意节点遍历全表,不再需要判断 NULL,逻辑更统一。

1. 节点结构体设计思路

循环链表节点结构与单链表完全一致,只改变指针指向规则,不改变节点本身。

cpp 复制代码
struct CNode {
    int data;               // 数据域:存储有效信息
    CNode* next;            // 指针域:指向下一个节点
};

2. 单循环链表 vs 普通单链表

  • 尾节点指向:单链表→NULL;循环链表→头结点
  • 判空条件:单链表 head->next==NULL;循环链表 head->next==head
  • 遍历结束:单链表 p==NULL;循环链表 p==head

【单链表 结构示意图】

【单循环链表 结构示意图】

二、基础工具函数

基础函数是插入、删除的前提,包含:初始化、判空、查找、获取长度、打印。

1. 初始化

思路:空表时,头结点指向自己,形成最小闭环。

cpp 复制代码
// 初始化带头结点的单循环链表
void Init_CircleList(CNode* plist) {
    if (plist == nullptr) return;
    plist->next = plist;       // 空表:头结点指向自身
}

2. 判空

cpp 复制代码
bool Is_Empty(CNode* plist) {
    return plist->next == plist;
}

3. 查找

cpp 复制代码
CNode* Search(CNode* plist, int val) {
    if (plist == nullptr) return nullptr;
    CNode* p = plist->next;
    // 遍历一圈:回到头结点结束
    while (p != plist) {
        if (p->data == val) return p;
        p = p->next;
    }
    return nullptr;
}

4. 获取有效长度

cpp 复制代码
int Get_Length(CNode* plist) {
    int cnt = 0;
    CNode* p = plist->next;
    while (p != plist) {
        cnt++;
        p = p->next;
    }
    return cnt;
}

5. 打印链表

cpp 复制代码
void Show(CNode* plist) {
    if (Is_Empty(plist)) {
        cout << "链表为空!" << endl;
        return;
    }
    CNode* p = plist->next;
    while (p != plist) {
        cout << p->data << " ";
        p = p->next;
    }
    cout << endl;
}

三、插入操作

按位置插入: 头插、尾插都是它的特殊情况

  • 头插 → pos = 0
  • 尾插 → pos = 链表长度
  • 中间插 → 0 < pos < 长度

插入思路

  1. 判断位置合法性

  2. 找到前驱节点

  3. 新建节点

  4. 先连后面,再连前面(防止指针断裂)

【头插示意图】

【尾插示意图】

cpp 复制代码
// 按位置插入(统一头插、尾插、中间插)
bool Insert_Pos(CNode* plist, int val, int pos) {
    int len = Get_Length(plist);
    if (pos < 0 || pos > len) return false;
    // 新建节点
    CNode* newNode = new CNode;
    newNode->data = val;
    // 找前驱
    CNode* p = plist;
    for (int i = 0; i < pos; i++) {
        p = p->next;
    }
    // 插入(核心步骤)
    newNode->next = p->next;
    p->next = newNode;
    return true;
}

四、删除操作

删除操作统一为两个核心函数,所有删除场景都能覆盖:

1. 按位置删除

  • 头删 → pos = 0
  • 尾删 → pos = len - 1
  • 中间删 → 通用

【头删示意图】

【尾删示意图】

cpp 复制代码
// 按位置删除
bool Del_Pos(CNode* plist, int pos) {
    if (Is_Empty(plist)) return false;
    int len = Get_Length(plist);
    if (pos < 0 || pos >= len) return false;
    // 找前驱
    CNode* p = plist;
    for (int i = 0; i < pos; i++) {
        p = p->next;
    }
    // 待删除节点
    CNode* q = p->next;
    // 跨越指向
    p->next = q->next;
    // 释放内存
    delete q;
    return true;
}

2. 按值删除

cpp 复制代码
// 按值删除
bool Del_Val(CNode* plist, int val) {
    if (Is_Empty(plist)) return false;
    // 第一步:找目标节点
    CNode* p = plist->next;
    while (p != plist) {
        if (p->data == val) break;
        p = p->next;
    }
    if (p == plist) return false; // 没找到
    // 第二步:找前驱
    CNode* q = plist;
    while (q->next != p) {
        q = q->next;
    }
    // 第三步:删除
    q->next = p->next;
    delete p;
    return true;
}

五、清空与销毁

核心区别

清空 :删除所有数据节点,保留头结点,链表还能继续用

销毁 :删除所有节点(含头结点),链表彻底销毁

销毁函数

cpp 复制代码
// 销毁整个循环链表
void Destroy(CNode*& plist) {
    CNode* p = plist->next;
    CNode* q = nullptr;
    // 释放所有数据节点
    while (p != plist) {
        q = p->next;
        delete p;
        p = q;
    }
    // 最后释放头结点
    delete plist;
    plist = nullptr;
}

六、总结

  1. 闭环:尾节点指向头结点,无 NULL 指针。

  2. 判空 :head->next == head;遍历结束:p == head。

  3. 插入/删除统一:只需要按位置操作,头插尾插、头删尾删都是特例。

  4. 指针修改原则:先连后面,再连前面,避免环断裂。

  5. 内存安全:new 必须配套 delete,销毁时必须释放所有节点。

  6. 应用场景:环形队列、循环播放列表、轮询调度等需要循环遍历的场景。

相关推荐
wuweijianlove6 小时前
算法性能的渐近与非渐近行为对比的技术4
算法
_dindong6 小时前
cf1091div2 C.Grid Covering(数论)
c++·算法
AI成长日志6 小时前
【Agentic RL】1.1 什么是Agentic RL:从传统RL到智能体学习
人工智能·学习·算法
黎阳之光6 小时前
黎阳之光:视频孪生领跑者,铸就中国数字科技全球竞争力
大数据·人工智能·算法·安全·数字孪生
skywalker_116 小时前
力扣hot100-3(最长连续序列),4(移动零)
数据结构·算法·leetcode
6Hzlia6 小时前
【Hot 100 刷题计划】 LeetCode 17. 电话号码的字母组合 | C++ 回溯算法经典模板
c++·算法·leetcode
wfbcg7 小时前
每日算法练习:LeetCode 209. 长度最小的子数组 ✅
算法·leetcode·职场和发展
_日拱一卒7 小时前
LeetCode:除了自身以外数组的乘积
数据结构·算法·leetcode
计算机安禾7 小时前
【数据结构与算法】第36篇:排序大总结:稳定性、时间复杂度与适用场景
c语言·数据结构·c++·算法·链表·线性回归·visual studio