C++ 数据结构超详细讲解单链表

C++ 数据结构超详细讲解单链表

什么是单链表

单链表是一种常见的线性数据结构,它由若干个节点组成,每个节点包含两部分内容:数据域和指针域。其中数据域存储节点所携带的数据,而指针域存储下一个节点的地址。

单链表的性质在于每个节点只有一个指针域,而第一个节点叫做头节点,通常不存放数据,只用来标注链表的起始位置。最后一个节点的指针域指向 NULL,即表示链表的结束。

如何实现单链表

在 C++ 中,我们可以定义一个结构体来表示单链表中的节点,如下所示:

struct ListNode {
    int val; // 存储节点的值
    ListNode* next; // 指向下一个节点的指针
    ListNode(int x) : val(x), next(nullptr) {} // 构造函数
};

有了这个节点结构体,我们就可以创建一个单链表了。在这里,我将实现一个具有常用操作的单链表类,包括节点的插入、删除、遍历等方法,具体实现如下:

class LinkedList {
public:
    LinkedList() : m_head(nullptr), m_size(0) {}
    ~LinkedList() {
        ListNode* temp = m_head;
        while (temp) {
            ListNode* cur = temp;
            temp = temp->next;
            delete cur;
        }
    }

    // 在单链表的开头插入节点
    void addFirst(int val) {
        ListNode* newNode = new ListNode(val);
        newNode->next = m_head;
        m_head = newNode;
        ++m_size;
    }

    // 在单链表的末尾插入节点
    void addLast(int val) {
        ListNode* newNode = new ListNode(val);
        if (m_head == nullptr) {
            m_head = newNode;
        } else {
            ListNode* temp = m_head;
            while (temp->next) {
                temp = temp->next;
            }
            temp->next = newNode;
        }
        ++m_size;
    }

    // 在单链表的指定位置插入节点
    void add(int index, int val) {
        if (index <= 0) {
            addFirst(val);
        } else if (index >= m_size) {
            addLast(val);
        } else {
            ListNode* newNode = new ListNode(val);
            ListNode* p = m_head;
            for (int i = 0; i < index - 1; ++i) {
                p = p->next;
            }
            newNode->next = p->next;
            p->next = newNode;
            ++m_size;
        }
    }

    // 删除单链表的第一个节点
    void removeFirst() {
        if (m_head) {
            ListNode* temp = m_head;
            m_head = m_head->next;
            delete temp;
            --m_size;
        }
    }

    // 删除单链表的最后一个节点
    void removeLast() {
        if (m_head) {
            if (m_head->next == nullptr) {
                delete m_head;
                m_head = nullptr;
            } else {
                ListNode* temp = m_head;
                while (temp->next->next) {
                    temp = temp->next;
                }
                delete temp->next;
                temp->next = nullptr;
            }
            --m_size;
        }
    }

    // 删除单链表的指定位置的节点
    void remove(int index) {
        if (index <= 0) {
            removeFirst();
        } else if (index >= m_size - 1) {
            removeLast();
        } else {
            ListNode* p = m_head;
            for (int i = 0; i < index - 1; ++i) {
                p = p->next;
            }
            ListNode* temp = p->next;
            p->next = temp->next;
            delete temp;
            --m_size;
        }
    }

    // 获取单链表的第一个节点
    ListNode* getFirst() const {
        return m_head;
    }

    // 获取单链表的最后一个节点
    ListNode* getLast() const {
        ListNode* temp = m_head;
        while (temp && temp->next) {
            temp = temp->next;
        }
        return temp;
    }

    // 获取单链表的指定位置的节点
    ListNode* get(int index) const {
        ListNode* p = m_head;
        for (int i = 0; i < index; ++i) {
            p = p->next;
        }
        return p;
    }

    // 获取单链表的节点个数
    int getSize() const {
        return m_size;
    }

    // 打印单链表的值
    void printList() const {
        ListNode* temp = m_head;
        while (temp) {
            std::cout << temp->val << " ";
            temp = temp->next;
        }
        std::cout << std::endl;
    }

private:
    ListNode* m_head; // 链表的头指针
    int m_size; // 链表的节点个数
};

单链表的使用

有了上面实现的单链表类,我们就可以轻松地在程序中使用单链表了。下面是一些使用示例:

示例一:将数组转为单链表

// 将数组转为单链表
LinkedList list;
int nums[] = {1, 2, 3, 4, 5};
int len = sizeof(nums) / sizeof(nums[0]);
for (int i = 0; i < len; ++i) {
    list.addLast(nums[i]);
}
// 打印单链表
list.printList();
// 输出:1 2 3 4 5

示例二:反转单链表

// 反转单链表
ListNode* newHead = nullptr;
ListNode* temp;
while (list.getFirst()) {
    temp = list.getFirst()->next;
    list.getFirst()->next = newHead;
    newHead = list.getFirst();
    list.removeFirst();
}
// 将反转后的结果转为单链表
list.getFirst() = newHead;
// 打印单链表
list.printList();
// 输出:5 4 3 2 1

总结

在 C++ 中实现单链表并不难,只需要用一个节点结构体表示链表中的节点,再用一个类来表示整个单链表,然后实现一些常用操作即可。单链表的操作就是对节点的操作,一定要注意节点为空的情况。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++ 数据结构超详细讲解单链表 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • 一文带你走进js数据类型与数据结构的世界

    一文带你走进JS数据类型与数据结构的世界 一、JS数据类型 1. 原始类型 JS中原始类型包括:Undefined、Null、Boolean、Number、String、Symbol(ES6新增)。 其中Undefined和Null分别代表未定义和空值,Boolean表示布尔值,Number表示数字,String表示字符串,Symbol是ES6新增的一种基础…

    数据结构 2023年5月17日
    00
  • 实际问题中用到的算法——递归算法确定插帧顺序

    问题: 现在需要给一个视频序列插帧,插帧算法要求每次只能由两帧输入插值得到其中间帧。如果现在需要给一个视频做 4 倍(或者更高的 8,16 倍等类似)的插帧,则一个插帧的思路是当前视频每相邻帧之间插入 3 帧,即:假设插帧前视频帧序号是 0,4,8,12…,则插帧时补充相邻帧跨过的 3 个序号,得到插帧后的视频帧序号为 0,1,2,3,4,5,6,.. 即可…

    算法与数据结构 2023年4月18日
    00
  • Redis五种数据结构在JAVA中如何封装使用

    Redis 是一款高性能的键值存储数据库,支持五种不同的数据结构:字符串(String)、哈希(Hash)、列表(List)、集合(Set)和有序集合(Sorted Set)。在Java中使用Redis需要封装对应的数据结构,本文将详细介绍如何封装Redis的五种数据结构。 封装Redis字符串数据结构 Redis字符串数据结构对应Java中的String类…

    数据结构 2023年5月17日
    00
  • 一些常见的字符串匹配算法

    作者:京东零售 李文涛 一、简介 1.1 Background 字符串匹配在文本处理的广泛领域中是一个非常重要的主题。字符串匹配包括在文本中找到一个,或者更一般地说,所有字符串(通常来讲称其为模式)的出现。该模式表示为p=p[0..m-1];它的长度等于m。文本表示为t=t[0..n-1],它的长度等于n。两个字符串都建立在一个有限的字符集上。 一个比较常见…

    算法与数据结构 2023年4月25日
    00
  • 【ACM算法竞赛日常训练】DAY4题解与分析【树】【子序列】| 组合数学 | 动态规划

    DAY4共2题: 树(组合数学) 子序列(dp,数学) ? 作者:Eriktse? 简介:19岁,211计算机在读,现役ACM银牌选手?力争以通俗易懂的方式讲解算法!❤️欢迎关注我,一起交流C++/Python算法。(优质好文持续更新中……)?? 原文链接(阅读原文获得更好阅读体验):https://www.eriktse.com/algorithm/109…

    算法与数据结构 2023年4月18日
    00
  • EMI/EMS/EMC有什么关系?

    EMI(Electromagnetic Interference)直译是“电磁干扰”,是指电子设备(即干扰源)通过电磁波对其他电子设备产生干扰的现象。 从“攻击”方式上看,EMI主要有两种类型:传导干扰和辐射干扰。 电磁传导干扰是指干扰源通过导电介质(例如电线)把自身电网络上的信号耦合到另一个电网络。 电磁辐射干扰往往被我们简称为电磁辐射,它是指干扰源通过空…

    算法与数据结构 2023年4月17日
    00
  • Java数据结构与算法之单链表深入理解

    Java数据结构与算法之单链表深入理解攻略 什么是单链表? 单链表(Singly Linked List)是指一个节点只指向下一个节点的链表。 单链表由多个节点组成,每个节点有两个属性:数据域和指针域。数据域保存节点的数据,指针域保存下一个节点的指针,因此每个节点包含两个域:data和next。 单链表的基本操作 单链表常用的基本操作包括: 在链表头部添加元…

    数据结构 2023年5月17日
    00
  • Java数据结构最清晰图解二叉树前 中 后序遍历

    Java数据结构最清晰图解二叉树前 中 后序遍历 前言 二叉树是数据结构中至关重要的一种数据结构,对于计算机科学的学习和工作都是至关重要的。而遍历二叉树是二叉树的重要操作之一。 为了帮助读者更好地理解二叉树前、中、后序遍历的过程,本文介绍 Java 数据结构中最清晰的图解二叉树前、中、后序遍历攻略。 什么是二叉树? 二叉树是一种非常重要的数据结构,它由根节点…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部