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日

相关文章

  • Javascript数据结构与算法之列表详解

    Javascript数据结构与算法之列表详解 简介 本文旨在讲解Javascript中数据结构和算法的列表。 列表定义和实现 列表是一组有序的数据,每个列表中的数据项称为元素。在Javascript中,列表可以用数组来实现。数组的好处是它能够存储任意类型的数据,而且可以根据需要动态地调整数组的大小。下面是一个创建列表的基本模板: function List(…

    数据结构 2023年5月17日
    00
  • 数位dp

    数位dp 思想 一般来说,题目是要求在区间\([l,r]\)中符合某一种条件的数的个数 我们用前缀和的思想考虑,分别求出\([1,r]\)和\([1,l-1]\)中数的个数相减即为所求 这里采用记忆化搜索的方式实现 模板 #include<iostream> #include<cstring> #include<vector&g…

    算法与数据结构 2023年4月17日
    00
  • C语言数据结构 链表与归并排序实例详解

    C语言数据结构 链表与归并排序实例详解 链表介绍 链表是一种数据结构,它对于存储数据是动态而灵活的。它可以根据我们的需要动态的分配内存空间。链表是由先后相连的数据单元(结点)组成,每个结点都包含了下一结点的地址信息,最后一个结点的地址信息为NULL。链表按照操作方式可以分为单向链表、双向链表与循环链表等几种类型。 归并排序原理 归并排序是一种分治思想的算法,…

    数据结构 2023年5月16日
    00
  • ecnuoj 5042 龟速飞行棋

    5042. 龟速飞行棋 题目链接:5042. 龟速飞行棋 赛中没过,赛后补题时由于题解有些抽象,自己写个题解。 可以发现每次转移的结果只跟后面两个点的胜负状态有关。 不妨设 \(f_{u,a,b}\) 表示,\(u+1\) 号点的胜负态为 \(a\),\(u+2\) 号点的胜负态为 \(b\),此时从 \(1\) 号点出发的胜负态是什么。那么可以发现,利用 …

    算法与数据结构 2023年4月17日
    00
  • 数据结构 红黑树的详解

    数据结构:红黑树的详解攻略 一、红黑树的定义 红黑树是一种二叉搜索树,它在每个节点上增加了一个存储位来表示节点的颜色,可以是红色或黑色。红黑树的特征是对于任何有效的红黑树,从根到叶子结点或空子结点的每条路径都包含相同数目的黑色结点。 二、插入操作 对于新插入的节点,将其涂红并插入红黑树中,然后按照二叉搜索树的规则将其插入到红黑树中。 如果父节点是黑色,则不需…

    数据结构 2023年5月17日
    00
  • Java实现链表数据结构的方法

    Java实现链表数据结构的方法可以分为以下步骤: 定义链表节点类Node 首先,在Java中实现链表数据结构,需要定义一个链表节点类,称为Node。Node类中包含两个重要属性: 数据域data,用于存储每个节点的数据信息。 指针域next,用于存储下一个节点的引用。 代码示例: public class Node { public int data; //…

    数据结构 2023年5月17日
    00
  • 「分治」黑白棋子的移动

    本题为3月23日23上半学期集训每日一题中A题的题解 题面 题目描述 有2n个棋子(n≥4)排成一行,开始位置为白子全部在左边,黑子全部在右边,如下图为n=5的情形: ○○○○○●●●●● 移动棋子的规则是:每次必须同时移动相邻的两个棋子,颜色不限,可以左移也可以右移到空位上去,但不能调换两个棋子的左右位置。每次移动必须跳过若干个棋子(不能平移),要求最后能…

    算法与数据结构 2023年4月18日
    00
  • C语言数据结构树的双亲表示法实例详解

    C语言数据结构树的双亲表示法实例详解 什么是双亲表示法 在树上,每个节点都有且仅有一个父节点(根节点除外)。对于一个树结构,我们可以使用许多方法来表示这个树,其中最常见的一种方法是双亲表示法。该表示法使用一个一维数组来存储树的节点,数组的下标即为该节点的编号,数组的值则表示该节点的父节点编号。 当一个节点没有父节点时,该节点即为根节点。 双亲表示法的优缺点 …

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