手搓 C++ 中LinkedList(链表)类模板:

C++ 标准模板库(STL)中的 LinkedList(链表)是 C++ 开发者一个非常重要的工具,它是一个可以自由改变长度的“数组”,通过成员函数实现增、删、改、查。

和数组不同的是,链表中每个元素的地址不是连续的,而是通过Node节点连接的。每个Node节点中包含一个Data成员(用于存储数据)和一个next指针(用于指向下一个节点的地址),从而实现逻辑上的连续(如图)。
在这里插入图片描述

⚠️ 注意

  • 为了在创建下一个节点时依然可以访问到前一个节点,我们要用一个前驱节点(PrvNode)来保存上一个节点的地址,每创建一个新节点就要更新一次前驱节点。
  • 为了实现遍历链表,我们还要用一个头节点来记录第一个节点的地址,通过它作为入口可以遍历整个链表。
  • 在删除某个位置的节点时,只需要把它的next指向下下个节点的地址即可,然后再用delete关键字清除被删除节点的内存空间。

LinkedList类模板代码

本小白结合栈的原理和 C++ 模板的基础知识,模拟了一个 STL 中 LinkedList 类模板(单向链表),并包含了部分的基础功能:push_back(),push_front(),pop(),find(),empty(),size()。

虽然目前代码运行没啥问题,但maybe会有一些潜在的漏洞或风险,希望各位大佬多多指教,也希望能帮助到和我一样正在学习 C++ 的朋友们,了解链表工作的底层原理!!!

#include <iostream>

using namespace std;

template<class T>
class LinkedList
{
private:
    struct Node
    {
        T m_Data;
        Node* next;
    };
    Node* PrvNode;
    Node* HeadNode;
    size_t m_ListSize;
public:
    LinkedList()
    {
        this->PrvNode = nullptr;
        this->HeadNode = nullptr;
        this->m_ListSize = 0;
    }
    bool empty()
    {
        return this->m_ListSize == 0 ? true : false;
    }
    void push_back(T data)
    {
        Node* newNode = new Node;
        newNode->m_Data = data;
        newNode->next = nullptr;
        if (this->empty())
        {
            this->HeadNode = newNode;
        }
        else
        {
            this->PrvNode->next = newNode;
        }
        this->PrvNode = newNode;
        this->m_ListSize++;
    }
    void push_front(T data)
    {
        Node* newNode = new Node;
        newNode->m_Data = data;
        newNode->next = this->HeadNode;
        this->HeadNode = newNode;
        this->m_ListSize++;
    }
    void pop(size_t pos)
    {
        if (pos > this->m_ListSize)
        {
            throw invalid_argument("Index out of boundry.");
        }
        if (this->m_ListSize == 1)
        {
            if (this->HeadNode != nullptr)
            {
                delete this->HeadNode;
                this->HeadNode = nullptr;
            }
            this->PrvNode = nullptr;
        }
        else
        {
            Node* delNode = nullptr;
            if (pos == 0)
            {
                delNode = this->HeadNode;
                this->HeadNode = this->HeadNode->next;
                delete delNode;
                delNode = nullptr;
            }
            else
            {
                Node* posNode = this->HeadNode;
                for (size_t i = 0; i < pos - 1; i++)
                {
                    posNode = posNode->next;
                }
                delNode = posNode->next;
                if (pos == this->m_ListSize - 1)
                {
                    this->PrvNode = posNode;
                    posNode->next = nullptr;
                }
                else
                {
                    posNode->next = posNode->next->next;
                }
                delete delNode;
                delNode = nullptr;
            }
        }
        this->m_ListSize--;
    }
    T find(size_t pos)
    {
        if (pos > this->m_ListSize - 1)
        {
            throw invalid_argument("Index out of boundry.");
        }
        Node* tempNode = this->HeadNode;
        for (size_t i = 0; i < pos; i++)
        {
            tempNode = tempNode->next;
        }
        return tempNode->m_Data;
    }
    size_t size()
    {
        return this->m_ListSize;
    }
    ~LinkedList()
    {
        if (!this->empty())
        {
            Node* tempNode = this->HeadNode;
            Node* freeNode = nullptr;
            while (tempNode != nullptr)
            {
                freeNode = tempNode;
                tempNode = tempNode->next;
                delete freeNode;
                freeNode = nullptr;
            }
        }
    }
};

int main()
{
    LinkedList<int> list;
    list.push_back(10);
    list.push_front(20);
    list.push_back(30);
    list.push_front(40);
    list.push_back(50);
    cout << list.size() << endl;
    cout << list.find(0) << endl;
    cout << list.find(1) << endl;
    cout << list.find(2) << endl;
    cout << list.find(3) << endl;
    cout << list.find(4) << endl;
    list.pop(4);
    cout << list.find(3) << endl;
    list.pop(0);
    return 0;
}

我的问题

STL模板库中的链表是有迭代器(Iterator)功能的,我不太理解这个应该如何编写,有没有大佬能教教!万分感谢!🙏

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐