C++数据结构:线性顺序表(链表)

news/2024/10/18 2:25:33/

文章目录

  • 前言
  • 一、链表简介
  • 二、单链表实现
  • 二、代码解读
  • 三、链表的优缺点
  • 总结


前言

前一篇文章介绍用数组实现的顺序表时已经提到链表这种结构,在STL中的 list 就是以链表实现的顺序表。这种结构与数组相比最大好处就是可以很方便的在头部和中部插入数据,而数组比较麻烦,需要移动之后的所有数据。


一、链表简介

链表也可以实现顺序表的功能。链表是一种动态数据结构,它可以根据需要自动调整大小,存储不连续的元素。当链表每个节点只记录下一个节点的指针时,它只能实现从前往后的单向访问,称之为单链表。如图所示:
在这里插入图片描述
h 表示链表的开头,它只存储了后面的第一个元素的地址,之后的每个节点存储了本身的值和此节点后的一个地址。就像一根链条将所有元素联系起来,大概这也是其称作链表的原因。

很显然的,有单链表了,自然能想到在最后一个节点中存储头或第一个节点的地址。如此就是单向循环链表,如图
单向循环链表
再进一步我在每个节点都再存储前一个节点的地址呢,就实现了双向链表:
在这里插入图片描述
很显然也是有双向循环链表的:
在这里插入图片描述

看图就明白了,链表的优点是在中间或开头插入或删除元素时,不需要移动后面的元素,效率较高。缺点是不能快速地随机访问任意元素,需要遍历,而且比较占空间。链表在计算机中的存储方式与普通数组不同,它采用指针来存放元素。下面我们就用代码来实现一个简单的顺序表的例子:

二、单链表实现

#include <iostream>
using namespace std;template <typename T> class Node {
public:T data;Node<T>* next;
};template <typename T> class LinkedList {
private:Node<T>* head;int len;
public:LinkList() {head = new Node<T>;head->next = NULL; //(*head).next = NULL;len = 0;}~LinkList() {Node<T>* p = head;while (p != NULL) {Node<T>* q = p->next;delete p;p = q;}}bool insert(int i, T data) {if (i < 0 || i > len) {return false;}Node<T>* p = head;for (int j = 0; j < i; j++) {p = p->next;}Node<T>* q = new Node<T>;q->data = data;q->next = p->next;p->next = q;len++;return true;}bool remove(int i) {if (i < 0 || i >= len) {return false;}Node<T>* p = head;for (int j = 0; j < i; j++) {p = p->next;}Node<T>* q = p->next;p->next = q->next;delete q;len--;return true;}int length() const {return len;}bool get(int i, T& data) const {if (i < 0 || i >= len) {return false;}Node<T>* p = head->next;for (int j = 0; j < i; j++) {p = p->next;}data = p->data;return true;}
};

在上面代码中,我们定义了一个 Node 类和一个 LinkList 类。其中 Node 类表示链表中的一个节点,包含数据和指向下一个节点的指针;LinkedList 类表示一个链表,包含头节点和链表长度。这个例子中实现了插入、删除、获取长度和获取元素等方法。

head->next 是链表中的一个指针,指向链表的第一个节点。head->next 表示链表的首节点,head 本身并没有值,它只是一个指向首节点的指针。head 的下一个节点才是第一个节点。

二、代码解读

相对于数组实现的顺序表,链表要稍复杂一些。第一个类定义了节点的数据结构,当然用struck也是可以的。next 是一个指针,用于指向下一个地址。

构造函数中 head->next = NULL; //(*head).next = NULL; 使用了指针的写法,这种写法略微方便点,如注释的写法也是可以的。因为 head 是一个指针,用->指针可以直接得到 head 的成员,如果写成类.成员就要先对指针解引,所以要有括号表示运算的优化级。

析构函数直接通过最后的元素的下一个指针是 NULL 这个特征,沿着链表一直删除。

insert方法需要先判断插入的位置是否合法,如果i在范围内,则找到当前的这个第 i 项的前一个元素。所以 for 循环中的条件是 < i ,然后将 i-1 项的 next 指针指向插入元素,将新元素的next 改成原 i-1 项的 next。如此即完成插入方法。下一个方法 remove 其实就是 insert 方法的逆序。

get 方法是用于读取元素值的,T& data 这个形参表示:这里使用了一个引用去取值。会将第 i 项的值存入传入的实参中,这是一个简单的引用写法。


三、链表的优缺点

  • 链表的主要缺点就是查找不方便,每一次取值都将遍历从头到 i ,时间复杂度相较数组在查找知道是第几项的情况下会慢很多,因为数组可以直接以下标取值。
  • 链表在往中间插入数据时会方便很多,数组需要每次移动插入位置后的所有元素。
  • 链表不需要连续大片的内存块,对内存的利用更充分。但是链表因为要存储下一个元素的指针,双向链表更是要存上一个元素的指针。所以同样的数据相对于数组所占用的内存会多得多,在64位系统中每个指针就占了8个字节,而一个 int 整数才占4字节。
  • 链表的另一种结构双向链表可以实现队列的功能。STL中的 list 就有 pop_front、push_back 这两个成员函数,很容易实现 FIFO 先进先出的功能。
  • 单向链表用NULL来判断是否到了尾部,环形链表可以用是否遇到头节点指针判断。
  • 双向链表因为存储了上一个节点的指针,可以实现双向迭代。弥补了相对数组的一个大缺点。

总结

以上使用了单链表实现一个自已的链表数据结构,并稍微加以分析这种数据结构的优缺点,用以更深入地理解此种结构的使用。以便在实际工作学习使用中根据需求灵活选择合适的数据结构。希望本文也能给读者带来一定启发!


http://www.ppmy.cn/news/86594.html

相关文章

常见的前端框架有哪些?

常用的前端框架有Bootstrap框架、React框架、Vue框架、Angular框架、Foundation框架等等 常用框架介绍&#xff1a; Bootstrap框架 Bootstrap是当今可用的前端框架中最受欢迎的&#xff0c;它具有直观&#xff0c;时尚的界面而且功能强大可以更快更轻松的实现web开发而且不需…

nginx判断访问的是不是index.html如果是且index.html存在直接返回

可以通过以下配置实现此功能&#xff1a; 复制server {listen 80;server_name example.com;root /var/www/example.com;index index.html;location / {try_files $uri $uri/ index;}location index {if (-f $document_root/index.html) {return 200;}rewrite ^ /index.html la…

今天用AI创作助手写的文章--Docker提问系列介绍 Docker 的基本概念和优势

目录 介绍 Docker 的基本概念和优势&#xff0c;以及在应用程序开发中的实际应用。基本概念&#xff1a;优势&#xff1a; 哪些应用可以部署到docker里面Docker在服务器里面的安装步骤Docker里面的报错如何很仔细的排查解决&#xff1f;总结一下docker 未来发展趋势 介绍 Docke…

Spring Boot 3.x 系列【35】服务监控 | 健康信息

有道无术,术尚可求,有术无道,止于术。 本系列Spring Boot版本3.0.5 源码地址:https://gitee.com/pearl-organization/study-spring-boot3 文章目录 1. 配置2. 基本原理3. 自动配置4. 自定义健康指标5. 分组6. 数据源1. 配置 Health是健康的意思,该端点用来检查正在运行…

[Daimayuan] 重建(C++,Floyd)

B B B 地区在地震过后&#xff0c;所有村庄都造成了一定的损毁&#xff0c;而这场地震却没对公路造成什么影响。但是在村庄重建好之前&#xff0c;所有与未重建完成的村庄的公路均无法通车。换句话说&#xff0c;只有连接着两个重建完成的村庄的公路才能通车&#xff0c;只能到…

C++11 -- 可变参数模板

文章目录 可变参数模板的概念可变模板参数的定义获取可变模板参数包的值递归函数方式展开参数包获取逗号表达式展开参数包获取 STL容器中的emplace相关接口参数emplace_back与STL容器中的push_back的主要区别emplace_back与push_back的差异原理emplate_back与push_back的区别验…

delphi11.3的WebBrower支持Edge

看到此消息后&#xff0c;立即下载了DelphiCE&#xff08;社区版&#xff09; 安装&#xff0c;创建项目&#xff0c;放TWebBrowers&#xff0c;TButton 配置参数为EdgeOnly F9运行&#xff0c;没反应 配置参数为EdgeIfAvailable F9运行&#xff0c;提示浏览器版本过低 全网搜索…

net::err_aborted 错误码 404

net::err_aborted 错误码 404 一般来说&#xff0c;在jsp中引入js、css时就可能会出现net::ERR_ABORTED 404&#xff08;即Not Found&#xff09;错误&#xff0c;即前端报错&#xff0c;解决方式也有两种比较常见的方式。具体介绍如下&#xff1a; 解决方法一 在js&#xf…