首页 > 编程语言 >【数据结构】自己动手写一个C++链表功能

【数据结构】自己动手写一个C++链表功能

时间:2024-10-16 15:17:49浏览次数:9  
标签:Node index head temp C++ next 链表 数据结构

链表数据结构在操作数据时具有更高的性能,但同时因为其结构的原因会造成时间复杂度为O(N),因此理解链表结构的底层实现能够让我们在开发中对程序的性能进行进一步优化。

如果你不知道什么是链表或者时间复杂度,可以参考我另外两篇文章:

代码

为了保证你能够更好的理解,我已经在代码中加入了很多注释方便理解,因此文章内不再阐述每个代码的作用。

#include <iostream>
using namespace std;

template <typename T>

// 节点结构
struct Node
{
    // 节点存储的数据
    T data;
    Node* next;

    explicit Node(T value): data(value), next(nullptr)
    {
    }
};

// 定义链表类
template <typename T>
class LinkedList
{
private:
    Node<T>* head; // 链表头指针私有
    int size; // 链表大小


public:
    LinkedList(): head(nullptr), size(0)
    {
    } // 构造函数
    // 插入节点到链表头部
    void add(T value)
    {
        // 链表中个数数量增加
        size++;
        // 创建一个新的Node
        auto* newNode = new Node(value);
        // 如果链接中当前头是空的
        if (head == nullptr)
        {
            // 则把头元素设置为当前的新元素
            head = newNode;
            return;
        }
        Node<T>* temp = head;
        while (temp->next != nullptr)
        {
            temp = temp->next; // 找到链表的末尾
        }
        // 将末尾Node的next指向新Node
        temp->next = newNode;
    }

    // 添加元素到指定位置
    void addAt(int index, T value)
    {
        // 检查要添加的索引是否不正确
        if (index > size || index < 0)
        {
            cout << "index out of bounds" << endl;
            return;
        }
        // 元素个数增加
        size++;
        if (index == 0)
        {
            head = new Node<T>(value);
            return;
        }
        // 当前索引位置
        int i = 0;
        // 临时变量
        Node<T>* temp = head;
        // 从链表头开始逐步取下一个链接并且要求下一个链表的位置<index
        while (temp->next != nullptr && i++ < index - 1)
        {
            temp = temp->next;
        }
        // 此时i == index,取出当前Node的正常next
        Node<T>* next = temp->next;
        // 将当前Node的next指向新Node
        temp->next = new Node<T>(value);
        // 将新创建的node的next指向原来的next
        temp->next->next = next;
    }

    void removeAt(int index)
    {
        if (index > size || index < 0)
        {
            cout << "index out of bounds" << endl;
            return;
        }
        int i = 0;
        Node<T>* temp = head;
        // 找到要删除的节点的前一个节点(i++ < index - 1)
        while (temp->next != nullptr && i++ < index - 1)
        {
            temp = temp->next;
        }
        // 要删除的Node节点
        Node<T>* deleteNode = temp->next;
        // 把当前Node节点的next指向deleteNode的next
        temp->next = deleteNode->next;
        size--;
        delete deleteNode;
    }

    T get(int index)
    {
        if (index > size || index < 0)
        {
            cout << "index out of bounds" << endl;
            return nullptr;
        }
        int i = 0;
        // 临时变量
        Node<T>* temp = head;
        // 从链表头开始逐步取下一个链接并且要求下一个链表的位置<index
        while (temp->next != nullptr && i++ < index)
        {
            temp = temp->next;
        }
        return temp->data;
    }

    // 清空链表元素
    void clear()
    {
        while (head != nullptr)
        {
            Node<T>* temp = head;
            head = head->next;
            delete temp;
        }
        size = 0;
    }

    // 输出链表中的元素
    void print() const
    {
        Node<T>* temp = head;
        while (temp != nullptr)
        {
            cout << temp->data << " ";
            temp = temp->next;
        }
        cout << endl;
    }

    // 析构函数,清理内存空间
    ~LinkedList()
    {
        clear();
    }
};

int main(int argc, char* argv[])
{
    LinkedList<int> list;
    list.add(1);
    list.add(2);
    list.add(3);
    list.print(); // 输出:1 2 3

    // 在索引1处插入4
    list.addAt(1, 4);
    list.print(); // 输出:1 4 2 3

    // 删除索引1的元素
    list.removeAt(1);
    list.print(); // 输出:1 2 3

    // 清空
    list.clear();
    list.print(); // 输出空
}

版权所有:XuanRan
未经书面授权,禁止转载

标签:Node,index,head,temp,C++,next,链表,数据结构
From: https://blog.csdn.net/qq_37945670/article/details/142959082

相关文章

  • C语言手撕实战代码_线索二叉树_先序中序线索二叉树_树的先根遍历_后根遍历_树的度_孩
    文章目录1.设计算法构造一棵先序线索二叉树2.先序线索二叉树的先序遍历算法3.设计算法构造一棵中序线索二叉树4.遍历中序线索二叉树5.树的先根遍历和后根遍历6.树T的叶子结点个数7.计算一棵以孩子兄弟表示的树T的度,该算法的时间复杂度为O(n)8.计算树孩子兄弟链表表示的T......
  • c++面向对象的两种格式
            面向对象编程(OOP)是C++的一个重要特性,它允许你将代码组织成类(class)和对象(object),从而提高代码的可读性、可维护性和复用性。所以,在项目开发中使用面向对象编程是非常重要的,即便函数也可以提高封装性,但是,类的使用通俗来说,直接将函数封装,同时可以通过继承父类来大......
  • 专题:链表(已完结)
    1.移除链表元素就是续签prenodecurnode需要注意本地使用虚拟头节点逻辑更加简单/***Definitionforsingly-linkedlist.*structListNode{*intval;*ListNode*next;*ListNode():val(0),next(nullptr){}*ListNode(intx):val......
  • 南沙C++信奥赛陈老师解一本通题 1943:【08NOIP普及组】排座椅
    ​ 【题目描述】上课的时候总有一些同学和前后左右的人交头接耳,这是令小学班主任十分头疼的一件事情。不过,班主任小雪发现了一些有趣的现象,当同学们的座次确定下来之后,只有有限的DD对同学上课时会交头接耳。同学们在教室中坐成了MM行NN列,坐在第ii行第jj列的同学的位置是(i,ji,j......
  • 每日OJ题_牛客_礼物的最大价值_路径dp_C++_Java
    目录牛客_礼物的最大价值_路径dp题目解析C++代码Java代码牛客_礼物的最大价值_路径dp礼物的最大价值_牛客题霸_牛客网(nowcoder.com)描述:        在一个m×n的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于0)。你可以从棋盘的左上角开始拿格子......
  • 数据结构--顺序表
    简介:这是顺序表的数据结构以C/C++语言实现,编译器为VS2022,如有不对的地方欢迎大家在评论区里讨论在其中我们要用到如下头文件:#include"stdio.h"#include"stdlib.h"简单宏定义一些类型,宏定义的内容可以根据自身需求进行更换:#defineMaxsize50 //静态顺序表的最大长度#def......
  • 【C++】C++ STL 树形结构容器全解析:map、set、multimap、multiset 的使用与区别
    C++语法相关知识点可以通过点击以下链接进行学习一起加油!命名空间缺省参数与函数重载C++相关特性类和对象-上篇类和对象-中篇类和对象-下篇日期类C/C++内存管理模板初阶String使用String模拟实现Vector使用及其模拟实现List使用及其模拟实现容器适配器Stack与QueuePriority......
  • G-数据结构-G
    \[\huge近日多做数据结构题,或恐后再读不能醒悟,或记其思路,或骂出题人,或不想刷题,虽有此篇。\]\[\]\[\]\[\]\[\]T1距离首先这题部分分很多,直接$O(n^2)$枚举点对,在树上差分即可获得70分。那么正解几乎和部分分就没什么关系了。首先看到\[ans_u=\sum_{x∈subtree_......
  • GESP2024年9月认证C++四级( 第一部分选择题(1-5))
    题三代码:#include<iostream>usingnamespacestd;//全局变量var,初始化为100intvar=100;//函数定义voidfunction(){//局部变量var,只在这个函数内部可见,初始化为200intvar=200;//输出局部变量var的值,即200......
  • C++ STL迭代器、resize和reserve区别、map和unordered_map区别,vector和List区别、map
    1.STL迭代器删除元素迭代器失效是指在对容器进行修改时,原有的迭代器可能变得不可用。正确删除元素的方法是使用erase,并返回新的有效迭代器。示例代码#include<iostream>#include<vector>intmain(){  std::vector<int>vec={1,2,3,4,5};  //输出......