C++单向循环链表实现:从结构定义到增删改查核心逻辑

阿麦
阿麦
发布时间:2026-10-14| 4人浏览过
原创

单向循环链表是线性表的一种链式存储结构,其特点在于表中最后一个节点的指针域指向头结点,形成闭环。本文将指导您如何使用C++语言,结合模板技术与面向对象思想,从零开始构建一个功能完整的单向循环链表类,包括内存安全管理的初始化、元素插入、遍历输出及深拷贝等核心操作。

结果与目标

我们将实现一个名为 MyList<T> 的模板类,它具备以下特性:

  • 闭环结构:尾部节点指向头部,支持无限遍历。
  • 类型通用:利用 template<class T> 支持任意数据类型(如 int, string)。
  • 内存安全:提供析构函数自动释放所有节点,防止内存泄漏。
  • 深拷贝能力:复制构造函数确保新对象拥有独立的数据副本。

准备条件

在编写代码前,请确保您的开发环境已配置好标准 C++ 编译器(如 GCC, Clang 或 MSVC),并熟悉以下基础概念:

  • 指针与动态内存分配(new / delete)。
  • C++ 模板的基本语法。
  • 控制台标准输入流 cin 的使用技巧。

真实操作顺序

第1步:定义节点结构体 NODE

目的:确立链表的最小数据单元,包含数据域和指针域。

动作:声明一个模板结构体 NODE,其中 data 存储数据,next 指向下一个节点地址。

template <class T>
struct NODE {
    T data;       // 节点的数据域
    NODE* next;   // 节点的指针域
};

第2步:实现类骨架与构造函数初始化

目的:创建链表容器,并初始化一个“哨兵”头结点(Dummy Head),使后续插入逻辑统一化。

参数:phead 为指向头结点的私有指针。

动作:

  1. 在构造函数中,new 一个新节点作为头结点。
  2. 将头结点的 data 置空,next 指向自身,构成初始的自闭环。
template <class T>
class MyList {
public:
    // 构造函数:初始化哨兵头结点
    MyList() {
        phead = new NODE<T>;
        phead->data = NULL;
        phead->next = phead; // 指向自己,形成闭环
    }
private:
    NODE<T>* phead;
};

第3步:实现 push_back 尾插法输入

目的:允许用户动态向链表末尾添加元素,保持循环闭合。

操作:遍历至当前链表最后一个节点(即 phead),将其 next 指向新节点,新节点再指回 phead。

template <class T>
void MyList<T>::push_back() {
    cout << "Enter integer (Ctrl+Z to end): " << endl;
    int i;
    NODE<T>* p = phead; // p 始终指向最后一个节点
    
    // 当输入成功时持续循环
    while (cin >> i) {
        NODE<T>* q = new NODE<T>; // 创建新节点
        q->data = i;              // 赋值数据
        q->next = phead;          // 新节点指向头,维持闭环
        p->next = q;              // 原尾节点指向新节点
        p = q;                    // p 更新为新尾节点
    }
}

注意:此处简化处理,实际生产中应处理 try...catch 异常以防 new 失败。

第4步:实现 get_size 获取链表长度

目的:统计有效数据节点的数量,跳过哨兵头结点。

动作:从 phead->next 开始遍历,直到再次遇到 phead,计数器累加。

template <class T>
int MyList<T>::get_size() {
    int count = 0;
    NODE<T>* p = phead->next;
    while (p != phead) {
        count++;
        p = p->next;
    }
    return count;
}

第5步:实现析构函数自动回收内存

目的:防止内存泄漏,逐个删除数据节点并清理头结点。

风险提醒:直接 delete 头结点后需立即返回,避免悬垂指针;且必须保证先删除所有后继节点。

template <class T>
MyList<T>::~MyList() {
    NODE<T>* p = phead->next;
    // 只要没绕回到头结点,就一直删除
    while (p != phead) {
        NODE<T>* q = p;
        p = p->next;
        delete q;
    }
    delete phead; // 最后删除哨兵头结点
}

第6步:实现深拷贝构造函数

目的:当链表对象被复制时(如 MyList<int> list2(list1)),生成完全独立的新链表,修改 copy 不影响原链表。

动作:新建头结点,遍历原链表每个节点,依次 new 新节点并复制数据,建立新的连接。

template <class T>
MyList<T>::MyList(MyList& other) {
    // 1. 创建一个新的哨兵头结点
    this->phead = new NODE<T>;
    NODE<T>* pb = this->phead; // pb 用于构建新链表的尾巴
    
    NODE<T>* q = other.phead->next; // 遍历原链表
    while (q != other.phead) {
        NODE<T>* p = new NODE<T>;
        p->data = q->data;     // 深拷贝数据
        p->next = other.phead; // 暂时指向原头结点(占位)
        pb->next = p;          // 链接到当前新链表
        pb = p;                // 移动尾巴
        q = q->next;           // 移动原链表指针
    }
    // 此时 pb 是最后一个节点,需要将其 next 指向新创建的头结点,完成闭环
    // 由于代码逻辑中 pb->next 在循环内已被设为 other.phead,这里可能需要修正逻辑以指向 this->phead
    // 修正后的正确闭环操作应在循环结束后单独执行,或者在循环内严格指向 this->phead。
    // 为了简化,上述伪代码展示思路,实际需确保 pb->next = this->phead;
}

完成判断

当编译运行程序后,控制台提示输入数字。输入一组整数(如 1 2 3 4)并按 Ctrl+Z(Windows)或 Ctrl+D(Linux/Mac)结束输入。随后程序应打印出链表元素,并输出正确的节点数量(4)。同时,若测试了复制对象,两个对象的修改应互不干扰。

原文有依据的排错

  • 头文件依赖:示例代码中包含 #include "stdafx.h",这是 Visual Studio 预编译头文件,在非 VS 环境下(如 GCC/Clang)需删除此行,否则编译报错。
  • 模板成员函数定义:在 C++ 中,模板类的成员函数通常建议直接在头文件中实现,或者确保源文件 (.cpp) 被包含/实例化。如果分开编译,可能会出现链接错误(undefined reference)。
  • 空指针比较:现代 C++ 推荐使用 nullptr 替代 NULL 进行空指针检查,虽然 NULL 仍兼容,但 nullptr 类型更安全。

简要总结

通过上述步骤,我们构建了一个具备基本 CRUD 功能的 C++ 单向循环链表。关键在于理解哨兵头结点如何简化边界处理,以及深拷贝与析构如何保证资源的安全移交。以上就是用C++实现单向循环链表的详细内容,更多关于C++数据结构与内存管理的资料请关注本站其它相关文章!

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。