首页 > 编程语言 >C++链表

C++链表

时间:2024-07-23 16:41:32浏览次数:8  
标签:node Node 结点 C++ next 链表 指针

引入

链表是一种用于存储数据的数据结构,通过如链条一般的指针来连接元素。它的特点是插入与删除数据十分方便,但寻找与读取数据的表现欠佳。

与数组的区别

链表和数组都可用于存储数据。与链表不同,数组将所有元素按次序依次存储。不同的存储结构令它们有了不同的优势:
链表因其链状的结构,能方便地删除、插入数据,操作次数是 $O(1)$。但也因为这样,寻找、读取数据的效率不如数组高,在随机访问数据中的操作次数是 $O(n)$。
数组可以方便地寻找并读取数据,在随机访问中操作次数是 $O(1)$。但删除、插入的操作次数是 $O(n)$ 次。

构建链表

构建链表时,使用指针的部分比较抽象,光靠文字描述和代码可能难以理解,建议配合作图来理解。

单向链表

单向链表中包含数据域和指针域,其中数据域用于存放数据,指针域用来连接当前结点和下一节点。
实现

struct Node {
    int value;
     Node *next;
};

双向链表

双向链表中同样有数据域和指针域。不同之处在于,指针域有左右(或上一个、下一个)之分,用来连接上一个结点、当前结点、下一个结点。

        struct Node {
          int value;
          Node *left;
          Node *right;
        };

向链表中插入(写入)数据

单向链表

流程大致如下:

  1. 初始化待插入的数据 node
  2. nodenext 指针指向 p 的下一个结点;
  3. pnext 指针指向 node

代码实现如下:

        void insertNode(int i, Node *p) {
          Node *node = new Node;
          node->value = i;
          node->next = p->next;
          p->next = node;
        }

单向循环链表

将链表的头尾连接起来,链表就变成了循环链表。由于链表首尾相连,在插入数据时需要判断原链表是否为空:为空则自身循环,不为空则正常插入数据。

大致流程如下:

  1. 初始化待插入的数据 node
  2. 判断给定链表 p 是否为空;
  3. 若为空,则将 nodenext 指针和 p 都指向自己;
  4. 否则,将 nodenext 指针指向 p 的下一个结点;
  5. pnext 指针指向 node

代码实现如下:

        void insertNode(int i, Node *p) {
          Node *node = new Node;
          node->value = i;
          node->next = NULL;
          if (p == NULL) {
            p = node;
            node->next = node;
          } else {
            node->next = p->next;
            p->next = node;
          }
        }

双向循环链表

在向双向循环链表插入数据时,除了要判断给定链表是否为空外,还要同时修改左、右两个指针。

大致流程如下:

  1. 初始化待插入的数据 node
  2. 判断给定链表 p 是否为空;
  3. 若为空,则将 nodeleftright 指针,以及 p 都指向自己;
  4. 否则,将 nodeleft 指针指向 p;
  5. noderight 指针指向 p 的右结点;
  6. p 右结点的 left 指针指向 node
  7. pright 指针指向 node

代码实现如下:

        void insertNode(int i, Node *p) {
          Node *node = new Node;
          node->value = i;
          if (p == NULL) {
            p = node;
            node->left = node;
            node->right = node;
          } else {
            node->left = p;
            node->right = p->right;
            p->right->left = node;
            p->right = node;
          }
        }

从链表中删除数据

单向(循环)链表

设待删除结点为 p,从链表中删除它时,将 p 的下一个结点 p->next 的值覆盖给 p 即可,与此同时更新 p 的下下个结点。

流程大致如下:

  1. p 下一个结点的值赋给 p,以抹掉 p->value
  2. 新建一个临时结点 t 存放 p->next 的地址;
  3. pnext 指针指向 p 的下下个结点,以抹掉 p->next
  4. 删除 t。此时虽然原结点 p 的地址还在使用,删除的是原结点 p->next 的地址,但 p 的数据被 p->next 覆盖,p 名存实亡。

代码实现如下:

        void deleteNode(Node *p) {
          p->value = p->next->value;
          Node *t = p->next;
          p->next = p->next->next;
          delete t;
        }

双向循环链表

流程大致如下:

  1. p 左结点的右指针指向 p 的右节点;
  2. p 右结点的左指针指向 p 的左节点;
  3. 新建一个临时结点 t 存放 p 的地址;
  4. p 的右节点地址赋给 p,以避免 p 变成悬垂指针;
  5. 删除 t

代码实现如下:

        void deleteNode(Node *&p) {
          p->left->right = p->right;
          p->right->left = p->left;
          Node *t = p;
          p = p->right;
          delete t;
        }

技巧

异或链表

异或链表(XOR Linked List)本质上还是 双向链表,但它利用按位异或的值,仅使用一个指针的内存大小便可以实现双向链表的功能。

我们在结构 Node 中定义 lr = left ^ right,即前后两个元素地址的 按位异或值。正向遍历时用前一个元素的地址异
或当前节点的 lr 可得到后一个元素的地址,反向遍历时用后一个元素的地址异或当前节点的 lr 又可得到前一个的元素地址。
这样一来,便可以用一半的内存实现双向链表同样的功能。

标签:node,Node,结点,C++,next,链表,指针
From: https://www.cnblogs.com/mcr130102/p/18318838

相关文章

  • c/c++ jsoncpp的基本使用
    一、概述jsoncpp官网作用:在c++中可以方便的组装及解析json格式的数据。二、代码示例voidMyJsonCpp::toJsonStr(){Json::ValuejsonValue;jsonValue["username"]="luoluoyang";jsonValue["password"]="123456";jsonValue["ag......
  • 三种语言实现计算逆序对的数量(C++/Python/Java)
    题目给定一个长度为......
  • 力扣第二题——两数相加(链表的讲解与运用,含解决链表问题模板)(含思路详解、完整代码与知
    内容介绍给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。请你将两个数相加,并以相同形式返回一个表示和的链表。你可以假设除了数字0之外,这两个数都不会以0 开头。示例1:输入:l1=[2,4,3],......
  • 三种语言实现归并排序(C++/Python/Java)
    题目给定你一个长度为......
  • 力扣209. 长度最小的子数组C++、窗口写法
    给定一个含有 n 个正整数的数组和一个正整数 target 。找出该数组中满足其总和大于等于 target 的长度最小的 子数组 [numsl,numsl+1,...,numsr-1,numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。示例1:输入:target=7,nums=[2,3,1,2,4,3]......
  • 三种语言实现快速选择(C++/Python/Java)
    题目给定一个长度为......
  • C++11 智能指针之shared_ptr
    1.背景基于Alexa的全链路智能语音SDK基于C++实现了跨平台特性,跑通了Android、Mac、Linux等设备,在兼容iOS时发现iOS未提供音频采集和播放的C++接口,所以需要改造SDK,允许SDK初始化时注入外部的采集器和播放器实现类,同时SDK中的Android播放器是基于ffmpeg解码+opensl实现,但......
  • C++11 智能指针之shared_from_this
    shared_ptr作用:C++中采用new和delete来申请和释放内存,如果管理不当,很容易出现内存泄露;std::shared_ptr,std::unique_ptr,std::weak_ptr,三种智能指针类,可以自动管理内存使用示例:智能指针对象和一般的指针用法几乎完全相同#include<iostream>#include<memory>//需......
  • C++多线程并发基础入门教程
    C++多线程并发基础入门教程《C++ConcurrencyinAction,SecondEdition》这本书深入浅出的讲解了C++多线程知识;如果英文水平足够好,可以查阅英文原版,它也有中文译本,虽然翻译过来的质量不如原版,但英文原版阅读太费精力;我推荐新手或者有一定经验的人看这本书。1什么是C++多......
  • Qt与C++标准的兼容之旅
    第一章:Qt与C++:相互成就的技术演进Qt,作为一个跨平台的应用程序和用户界面框架,自其诞生之初便与C++紧密相连。C++,一种广泛使用的高级编程语言,以其高效的性能和面向对象的特性在软件开发中占据重要地位。在探讨Qt与C++之间的关系时,我们不仅是在分析技术层面的互动,更是在审视一......