顺序表和链表的对比(一)

前言

今天给小伙伴们分享的是在数据结构中顺序表和链表的对比。它们在计算机科学和软件开发中具有广泛的应用,是理解更复杂数据结构(如栈、队列、树、图等)的基础。这次将会给大家从定义初始化,以及功能增删查改上进行详细对比,以便于大家掌握并使用。那让咱们开始吧@

一.基本知识概述

考虑到可能有些小伙伴还没了解到顺序表或链表,就先概述一下关于它们的基本知识。

1.顺序表

顺序表(Sequential List) 是用一段物理地址连续的存储单元依次存储数据元素的线性结构。一般是使用数组方式实现 它的元素在内存中是连续存储的。顺序表是数据结构中最基础的一种线性表,具有高效的随机访问特性,但在插入和删除操作上效率较低

2.链表

链表(Linked List)  一种在物理存储结构上非连续、非顺序的存储结构,又因为在节点结构和操作上不同分有(双链表还细分是否循环与是否带哨兵位头节点):双链表(Doubly Linked List)和单链表(Singly Linked List)。链表与顺序表不同,它是靠指针链接实现的,顺序表的元素在内存中是连续存储的,而链表的元素可以分散在内存的任何位置。因此它在插入和删除上效率比顺序表更高些。

二.定义及初始化

1.顺序表

顺序表通常由以下部分组成:

  1. 数据存储区

    一个数组(需要考虑数据大小,是否需要自主开辟空间和扩容),用于存储元素。
  2. 长度信息

    一个变量,用于记录当前顺序表中元素的数量
静态顺序表

(静态的意思是存储空间有限)首先定义一个结构体,然后在结构体里再定义一个数组以及一个整型变量来显示顺序表长度,不知道数据具体大小的时候,使用起来比较麻烦,容易产生数组越界以及空间浪费问题,这里推荐使用动态的顺序表。

#define MAX_SIZE 100 // 定义一个能容纳所有数据的容量,这个属于静态顺序表了,不易把控使用空间//一般推荐大家使用动态顺序表typedef struct SequentialList
{int data[MAX_SIZE]; // 数据存储区int length;         // 当前顺序表的长度
} SL;

静态顺序表的初始化比较简单,只需初始化长度即可

void InitList(SL* ps) 
{L->length = 0; // 初始化长度为 0
}
动态顺序表

动态顺序表则在空间使用上更加灵活,使用数组指针,通过 malloc 函数开辟所需空间,如果不够再使用realloc 函数进行扩容,但是需考虑内存泄漏问题,以及后续使用完空间的释放问题。

typedef int SLDataType; //定义数组类型,方便存储各种类型不同的数据#define INIT_CAPACITY 4 //定义一个空间容量,方便后续扩容// 动态顺序表 -- 按需申请
typedef struct SequentialList
{SLDataType* a;int size;     // 有效数据个数int capacity; // 空间容量
}SL;

对比于静态顺序表,动态顺序表初始化则较为复杂一点

(扩容函数的使用放在数据插入,不够再扩,节省空间)

void SLInit(SL* ps)
{assert(ps);ps->a = (SLDataType*)malloc(sizeof(SLDataType)* INIT_CAPACITY); 通过malloc 函数开辟空间if (ps->a == NULL)//若开辟失败,返回错误信息{perror("malloc fail"); 	return;}ps->size = 0;ps->capacity = INIT_CAPACITY;
}

2.链表

链表的话则是通过结构体指针来实现,单链表和双链表的定义差不多,主要区别在节点指针的数量及指向方向。双链表较于单链表,支持双向遍历,增删数据更加灵活,但在空间效率上略低于单链表,因为它有两个节点指针,并且在维护时需要调整两个指针,容易出错。

1. 单链表(Singly Linked List)

  • 节点结构

    • 每个节点包含两个部分:

      1. 数据域:存储数据。

      2. 指针域:指向下一个节点的指针。

  • 链表结构

    • 链表由一系列节点组成,每个节点通过指针连接。

    • 链表的最后一个节点的指针域为 NULL,表示链表的结束。

typedef int SLTDataType;  定义数据类型,方便后续适用于存储各种类型数据typedef struct SListNode
{SLTDataType data; struct SListNode* next; 指向下一个节点
}SLTNode;

单链表的初始化通过节点创造函数创建了一个节点并赋初值,然后把节点指针传递回插入函数(下期会详细介绍)

SLTNode* CreatSLTNode(SLTDataType x)
{SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode)); //创建节点if (newnode == NULL){perror("malloc fail"); //若开辟失败,则返回错误信息return NULL;}newnode->data = x;newnode->next = NULL; //避免出现野指针return newnode; //返回节点指针到插入函数
}

2. 双链表(Doubly Linked List)

  • 节点结构

    • 每个节点包含三个部分:

      1. 数据域:存储数据。

      2. 前驱指针:指向前一个节点的指针。

      3. 后继指针:指向下一个节点的指针。

  • 链表结构

    • 链表由一系列节点组成,每个节点通过前驱指针和后继指针连接。

    • 链表的第一个节点的前驱指针为 NULL,最后一个节点的后继指针为 NULL

双链表的定义则比单链表多一个指针,于是便有了访问上一个节点的功能

typedef int LTDataType; 定义数据类型,方便后续适用于存储各种类型数据typedef struct ListNode
{struct ListNode* next; 指向下一个节点指针struct ListNode* prev; 指向上一个节点指针LTDataType data;
}SL;

双链表的初始化跟单链表差不多,多了一个回访指针的初始化。


SL* CreatSListNode(LTDataType x)
{SL* node = (LTNode*)malloc(sizeof(LTNode));if (node == NULL){perror("malloc fail");//return NULL;exit(-1);//调用 exit 函数以非零状态终止程序。}node->next = NULL;node->prev = NULL;//回访指针,指向上一个节点node->data = x;return node;
}

在这里呢,再提一下带哨兵位(sentinel node)头节点的双链表。先解释一下什么是哨兵位节点(sentinel node)吧。

哨兵节点(sentinel node)是一种特殊的结点,它可以简化链表中的操作,减少边界条件的判断和特殊处理,假如用它作头节点,在进行链表增删操作时就不用单独考虑链表是否为空的情况了。

具体实现也很简单,大家可以理解成跟不带哨兵位节点时一样,只不过之前是在头节点中开始放数据,现在是在第二个节点中开始放数据,相当于头节点里面数据是空的,头节点是空指针。

// 创建新节点的函数SL*CreatSListNode(LTDataType x)
{SL* node = (LTNode*)malloc(sizeof(LTNode));if (node == NULL){perror("malloc fail");//return NULL;exit(-1);//调用 exit 函数以非零状态终止程序。}node->next = NULL;node->prev = NULL;//回访指针,指向上一个节点node->data = x;return node;
}// 初始化双链表的函数void InitList(SL* L) 
{// 创建哨兵节点L->sentinel = (Node*)malloc(sizeof(Node));L->sentinel->prev = L->sentinel; // 哨兵节点的 prev 指向自己L->sentinel->next = L->sentinel; // 哨兵节点的 next 指向自己
}void InsertAtHead(SL* L, int x )
{SL* newNode = CreatSListNode(x);// 将新节点插入到哨兵节点之后newNode->next = L->sentinel->next;newNode->prev = L->sentinel;L->sentinel->next->prev = newNode;L->sentinel->next = newNode;
}

以上就是这期的内容,希望能给有需求的小伙伴们提供一些帮助,如果有疏漏的地方,小伙伴们可以直接指出,以便纠正,祝大家天天开心@

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/73445.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

星越L_外后视镜使用讲解

目录 1.外后视镜调节 2后视镜折叠 3.后视镜加热 1.外后视镜调节 L控制左边后视镜调节,上下拨动调整视野,一般此镜左右21分,上下55开。 R控制左边后视镜调节,上下拨动调整视野,一般此镜左右13分,上下55开。 2后视镜折叠 车辆解锁自动展开 车辆关闭自动折叠 严寒天气…

DevOps实践:持续集成与持续部署完全指南

文章目录 引言:从人工到自动化的进化革命一、CI/CD核心认知升级1.1 持续集成 vs 持续部署 vs 持续交付1.2 中小团队为什么要实施CI/CD? 二、CI/CD工具链选型指南2.1 中小团队推荐技术栈2.2 工具对比决策矩阵 三、实战五步构建企业级流水线3.1 基础环境搭…

【数据结构】数据结构,算法 概念

0.本篇问题: 数据、数据元素、数据对象、数据项之间的基本关系?ADT是什么?数据结构的三要素?数据的逻辑结构有哪些?数据的存储结构有哪些?算法的五个特征?O(1) O(logn) O(n^n) O(n) O(n^2…

同步Oracle及mysql至KADB的KFS配置文件参考

Oracle源端flysync.ini文件 注意:oracle用户名大写 mysql源端flysync.ini文件 附:目标端KADB的flysync.ini文件 [m_kes_3113] 源端为KES kufl-port3113 datasource-typekingbase rolemaster replication-host10.4.43.53 replication-port54321 …

PECL(Positive Emitter-Coupled Logic)电平详解

一、PECL电平的定义与核心特性 PECL(正射极耦合逻辑)是一种基于 射极耦合逻辑(ECL)技术 的高速差分信号标准,采用 正电源供电(如5V或3.3V)。其核心特性包括 高速传输、低噪声、强抗干扰能力&am…

以 ArcGIS Pro 为笔,绘就水墨地图画卷

一、引言 水墨画,作为中国传统绘画艺术的瑰宝,以其独特的韵味和表现力,在艺术领域占据着重要地位。它通过水与墨的交融,展现出山水之间的灵动与韵味。 而将这种艺术形式与现代地理信息系统(GIS)技术相结合…

软考网络安全专业

随着信息技术的迅猛发展,网络安全问题日益凸显,成为社会各界普遍关注的焦点。在这样的背景下,软考网络安全专业应运而生,为培养高素质的网络安全人才提供了有力支撑。本文将对软考网络安全专业进行深入剖析,探讨其在信…

在线 SQL 转 SQLAlchemy:一键生成 Python 数据模型

一款高效的在线 SQL 转 SQLAlchemy 工具,支持自动解析 SQL 语句并生成 Python SQLAlchemy 模型代码,适用于数据库管理、后端开发和 ORM 结构映射。无需手写 SQLAlchemy 模型,一键转换 SQL 结构,提升开发效率,简化数据库…

自定义tiptap插件

本文为开发开源项目的真实开发经历,感兴趣的可以来给我的项目点个star,谢谢啦~ 具体博文介绍: 开源|Documind协同文档(接入deepseek-r1、支持实时聊天)Documind 🚀 一个支持实时聊天和接入 - 掘…

网络安全需要学多久才能入门?

网络安全是一个复杂且不断发展的领域,想要入行该领域,我们需要付出足够多的时间和精力好好学习相关知识,才可以获得一份不错的工作,那么网络安全需要学多久才能入门?我们通过这篇文章来了解一下。 学习网络安全的入门时间因个人的…

EG82088串口边缘计算网关

EG82088串口边缘计算网关 EG8208是一款专业级8路独立隔离型RS485通讯控制器,通过Modbus及JSON支持、灵活的TCP/IP和UDP切换、内置监控自诊断等特性,广泛应用于工业自动化、楼宇管理等领域,为用户提供卓越的数据采集和设备管理解决方案。 接口类型:8RS485/8DO/1LAN协…

Linux下GCC和C++实现带多组标签的Snowflake SQL查询批量数据导出程序

设计一个基于多个带标签Snowflake SQL语句作为json配置文件的Linux下GCC的C代码程序,实现根据不同的输入参数自动批量地将Snowflake数据库的数据导出为CSV文件到本地目录上,标签加扩展名.csv为导出数据文件名,文件已经存在则覆盖原始文件。需…

Trae AI 辅助修复uniapp 微信小程序的Bug

一、transparent的兼容问题 设计稿: 实际在iphone 6 plu上: 直接让Trae AI修复: 修改后验证通过。 二、v-if分支中子元素根据输入框中内容长度动态添加class样式失效 遇到了个“怪问题”,在其他手机或者开发者工具都正常。也…

conda install 和 pip install 的区别

conda install 和 pip install 是两个常用的包安装命令,但它们在很多方面存在差异。 1. 所属管理系统不同 1.1 conda install conda install 是Anaconda和Miniconda发行版自带的包管理工具 conda 的安装命令。conda 是一个跨平台的开源包管理系统和环境管理系统&…

uni-app App 端分段导出 JSON 数据为文件

在开发过程中,我们经常需要将大量数据导出为 JSON 文件,尤其是在处理长列表或大数据集时。然而,直接将所有数据写入一个文件可能会导致性能问题,尤其是在移动设备上。为了优化性能并提高用户体验,我们可以将数据分段导…

视频推拉流EasyDSS案例分析:互联网直播/点播技术与平台创新应用

随着互联网技术的快速发展,直播/点播平台已成为信息传播和娱乐的重要载体。特别是在电视购物领域,互联网直播/点播平台与技术的应用,不仅为用户带来了全新的购物体验,也为商家提供了更广阔的营销渠道。传统媒体再一次切实感受到了…

MySQL再次基础 向初级工程师迈进

作者:在计算机行业找不到工作的大四失业者 Run run run ! ! ! 1、MySQL概述 1.1数据库相关概念 1.2MySQL数据库 2、SQL 2.1SQL通用语法 SQL语句可以单行或多行书写,以分号结尾。SQL语句可以使用空格/缩进来增强语句的可读性。MySQL数据库的SQL语句不区…

手写一个简易版的tomcat

Tomcat 是一个广泛使用的开源 Servlet 容器,用于运行 Java Web 应用程序。深入理解 Tomcat 的工作原理对于 Java 开发者来说是非常有价值的。本文将带领大家手动实现一个简易版的 Tomcat,通过这个过程,我们可以更清晰地了解 Tomcat 是如何处理…

VSTO(C#)Excel开发8:打包发布安装卸载

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的,可以在任何平台上使用。 源码指引:github源…

如何逐步迭代衍生出一个网络安全产品

逐步迭代衍生出一个网络安全产品需要结合市场需求、技术趋势和用户反馈,通过系统化的开发和优化过程来实现。以下是逐步迭代的详细步骤: 1. 确定市场需求和产品定位 市场调研:分析当前网络安全市场的痛点和趋势,如云安全、零信任、…