数据结构入门(3)顺序表和链表

news2024/12/23 1:09:30

1.线性表

线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使 用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串...

线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的, 线性表在物理上存储时,通常以数组和链式结构的形式存储。

2.顺序表

1.概念及结构

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存 储。在数组上完成数据的增删查改。

顺序表一般可以分为:

1. 静态顺序表:使用定长数组存储元素。

2. 动态顺序表:使用动态开辟的数组存储。

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>

typedef int SLDataType;
typedef struct SeqList
{
	SLDataType* a;//指向动态数组的指针
	int size;//数组个数大小
	int capacity;//数组的最大容量
}SeqList;

 2.基本功能接口实现

静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定大了,空 间开多了浪费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间 大小,所以下面我们实现动态顺序表。

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>

typedef int SLDataType;
typedef struct SeqList
{
	SLDataType* a;
	int size;
	int capacity;
}SeqList;

//常用接口
//顺序表初始化
void SeqListInit(SeqList* psl);
// 检查空间,如果满了,进行增容
void CheckCapacity(SeqList* psl);
// 顺序表尾插
void SeqListPushBack(SeqList* psl, SLDataType x);
// 顺序表尾删
void SeqListPopBack(SeqList* psl);
// 顺序表头插
void SeqListPushFront(SeqList* psl, SLDataType x);
// 顺序表头删
void SeqListPopFront(SeqList* psl);
// 顺序表查找
int SeqListFind(SeqList* psl, SLDataType x);
// 顺序表在pos位置插入x
void SeqListInsert(SeqList* psl, size_t pos, SLDataType x);
// 顺序表删除pos位置的值
void SeqListErase(SeqList* psl, size_t pos);
// 顺序表销毁
void SeqListDestory(SeqList* psl);
// 顺序表打印
void SeqListPrint(SeqList* psl);

具体实现过程看文章《顺序表接口实现 》

3.需要思考的问题

. 1. 中间/头部的插入删除,时间复杂度为O(N)

2. 增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗。

3. 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到 200,我们再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间。

下面要讲到的链表可以解决上面产生的问题

3.链表

1.概念及结构

概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表 中的指针链接次序实现的 。

可以看到,各个数据元素通过指针次序进行链接,就像一条环环相扣的链子一样,故称之为链表。

链表在逻辑上是连续的,但物理结构中不一定连续,因为每增加一个结点,都会去到堆上动态申请内存空间,这是随机的。

2.链表的分类

1. 单向或者双向

2. 带头或者不带头(也就是平常说的哨兵位)

3. 循环或者非循环

虽然有这么多的链表的结构,但是我们实际中最常用还是两种结构:

3.链表的实现

参考文章《链表接口实现》

4.双向链表的实现

双向链表和单向链表的区别在于它多了一个前驱指针可以指向前面结点而不是像单链表那样还要从头结点开始遍历找到。

这里不再提供双向链表的接口实现,各位同学可以根据单链表的实现自行实现一下,这样可以更加深刻的理解指针的含义。

双向链表的基本功能

// 2、带头+双向+循环链表增删查改实现
typedef int LTDataType;
typedef struct ListNode
{
 LTDataType _data;
 struct ListNode* next;
 struct ListNode* prev;
}ListNode;

// 创建返回链表的头结点.
ListNode* ListCreate();
// 双向链表销毁
void ListDestory(ListNode* plist);
// 双向链表打印
void ListPrint(ListNode* plist);
// 双向链表尾插
void ListPushBack(ListNode* plist, LTDataType x);
// 双向链表尾删
void ListPopBack(ListNode* plist);
// 双向链表头插
void ListPushFront(ListNode* plist, LTDataType x);
// 双向链表头删
void ListPopFront(ListNode* plist);
// 双向链表查找
ListNode* ListFind(ListNode* plist, LTDataType x);
// 双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x);
// 双向链表删除pos位置的结点
void ListErase(ListNode* pos);

4.顺序表和链表的区别和联系

链表和顺序表是两种常见的数据结构,它们在存储空间、随机访问、增删查改、应用场景和缓存利用率等方面有一些区别。下面我将从这些角度逐一说明它们的区别:

1. 存储空间: 顺序表使用一段连续的物理内存空间存储数据,而链表则通过节点之间的指针连接来实现数据的存储。顺序表在插入或删除元素时可能会涉及到移动其他元素的操作,而链表的插入和删除操作仅需要调整节点之间的指针,因此链表可以更灵活地利用内存空间。

2. 随机访问:顺序表支持通过索引直接访问元素(时间复杂度O(1)),即可以通过下标快速定位需要的元素。而链表需要从头节点开始遍历,直到找到目标节点(时间复杂度O(N))。因此,顺序表的随机访问速度更快,而链表的访问效率较低。

3. 增删查改: 顺序表的增删操作可能涉及元素的迁移,而链表的增删操作只需要调整节点之间的指针,因此链表在插入和删除操作上更高效。而查找和修改操作方面,顺序表可以直接通过索引定位元素,相对更快速,而链表需要遍历节点进行查找。

4. 应用场景: 顺序表适用于静态数据,即数据量固定且对随机访问和顺序访问的需求较高的场景。链表适用于动态数据,即需要频繁的插入和删除操作的场景,比如实现队列、栈和链表本身。

5. 缓存利用率:顺序表的数据存储在连续的内存空间中,有利于缓存的预加载和利用,提高访问速度。而链表的节点分散在内存中的不同位置,对于缓存的利用不够友好,可能导致缓存不命中,访问速度较慢。

总的来说,顺序表和链表在存储空间、随机访问、增删查改、应用场景和缓存利用率等方面有一些不同。选择使用哪种数据结构应根据具体的需求和场景来进行权衡和权衡。

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

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

相关文章

汤唯短发造型:保留经典和适合自己的风格,也许才是最重要的

汤唯短发造型&#xff1a;保留经典和适合自己的风格&#xff0c;也许才是最重要的 汤唯短发造型登上Vogue四月刊封面&#xff0c;引发网友热议。#李秘书讲写作#说说是怎么回事&#xff1f; 这次Vogue四月刊的封面大片&#xff0c;汤唯以一头短发亮相&#xff0c;身穿五颜六色的…

Python笔记:函数

Python函数定义规则&#xff1a; 函数代码块以def关键词开头&#xff0c;后接函数标识符名称和圆括号()。任何传入参数和自变量必须放在圆括号中间&#xff0c;圆括号之间可以用于定义参数。return [表达式] 结束函数&#xff0c;选择性地返回一个值给调用方&#xff0c;不带表…

力扣(LeetCode)142.环形链表 II

本博客讲解一道以前大厂面试常考的链表oj题 ——————————————————————— 题目介绍&#xff1a; 给定一个链表的头节点 head &#xff0c;返回链表开始入环的第一个节点。 如果链表无环&#xff0c;则返回 null。 如果链表中有某个节点&#xff0c;可以通…

【C语言】操作符相关知识点

移位操作符 << 左移操作符 >>右移操作符 左移操作符 移位规则&#xff1a; 左边抛弃、右边补0 右移操作符 移位规则&#xff1a; 首先右移运算分两种&#xff1a; 1.逻辑移位 左边用0填充&#xff0c;右边丢弃 2.算术移位 左边用原该值的符号位填充&#xff0c;…

桥接模式以及在JDBC源码剖析

介绍&#xff1a; 1、桥接模式是指&#xff1a;将实现和抽象放在两个不同类层次中&#xff0c;使两个层次可以独立改变 2、是一种结构型设计模式 3、Bridge模式基于类的最小设计原则&#xff0c;通过使用封装、聚合以及继承等行为让不同的类承担不同的职责。 4、特点&#xff1…

【智能算法】樽海鞘群算法(SSA)原理及实现

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.代码实现4.参考文献 1.背景 2017年&#xff0c;Mirjalili受到樽海鞘集群行为启发&#xff0c;提出了樽海鞘群算法(Salp Swarm Algorithm, SSA)。 2.算法原理 2.1算法思想 樽海鞘集群是领导者-追随者类型算法&#xff0c;整体…

基于SpringBoot的“医院信管系统”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“医院信管系统”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 功能结构图 系统首页界面图 用户注册界面图 医生…

CANopen转Profinet网关连接西门子PLC与变流器通讯

CANopen转Profinet网关&#xff08;XD-COPNm20&#xff09;在智能领域&#xff0c;变流器的应用非常广泛&#xff0c;变流器一般会采用CANopen协议。现场采用台达的变流器&#xff08;支持CANopen协议&#xff09;作为CANopen从站&#xff0c;S7-1500系列PLC做主站&#xff0c;…

软件设计不是CRUD(14):低耦合模块设计理论——行为抽象与设计模式(上)

是不是看到“设计模式”四个字,各位读者就觉得后续内容要开始讲一些假大空的内容了?各位读者是不是有这样的感受,就是单纯讲设计模式的内容,网络上能找到很多资料,但是看过这些资料后读者很难将设计模式运用到实际的工作中。甚至出现了一种声音:设计模式是没有用的,应用…

Python安装第三方库

前言&#xff1a;大部分时候我们都是使用pip install去安装一些第三方库&#xff0c;但是偶尔也会有部分库无法安装&#xff08;最典型的就是dlib这个库&#xff09;&#xff0c;需要采取别的方法解决&#xff0c;这里做笔记记录一下。 使用国内镜像源安装 因为pypi的服务器在…

Java后端八股文之Redis

文章目录 1. Redis是什么&#xff1f;2. Redis为什么这么快&#xff1f;3. 为什么要使用缓存&#xff1f;4. Redis几种使用场景&#xff1a;5. Redis的Zset底层为什么要使用跳表而不是平衡树、红黑树或者B树&#xff1f;6.Redis持久化6.1 什么是RDB持久化6.1.1RDB创建快照会阻塞…

大数据开发-FLUME安装部署与实战案例

文章目录 前言安装部署配置修改案例:采集文件内容上传至HDFS案例:采集网站日志上传HDFS前言 Flume是Cloudera提供的一个高可用的,高可靠的,分布式的海量日志采集、聚合和传输的系统,Flume支持在日志系统中定制各类数据发送方,用于收集数据;同时,Flume提供对数据进行简…

es 查询案例分析

场景描述&#xff1a; 有这样一种场景&#xff0c;比如我们想搜索 title&#xff1a;Brown fox body&#xff1a;Brown fox 文章索引中有两条数据&#xff0c;兔子和狐狸两条数据 PUT /blogs/_bulk {"index": {"_id": 1}} {"title": "…

Oracle Primavera P6 数据库升级

前言 为了模拟各种P6测试&#xff0c;我常常会安装各种不同版本的p6系统&#xff0c;无论是P6服务&#xff0c;亦或是P6客户端工具Professional&#xff0c;在今天操作p6使用时&#xff0c;无意识到安装在本地的P6 数据库&#xff08;21.12&#xff09;出现了与Professional软…

对于stm32中printf函数的移植方法

一、准备工作 使用printf之前需要先打开工程选项&#xff0c;把use microLIB选项打开。microlib是keil为嵌入式平台优化的一个精简库&#xff0c;本文使用到的printf将会用到这个microlib。 二、对printf进行重定向 将printf打印的东西输出到串口&#xff0c;由于printf默认输…

关于分布式分片,你该知道的事儿

关于分布式分片&#xff0c;你该知道的事儿 前言一、关于分片方式的那些事儿1.1 按照Hash划分1.2 按照区间范围划分1.3 按照数据量划分1.4 来些例子1.4.1 Redis的分片划分1.4.2 Mongo的分片划分 二、关于分区再平衡的那些事儿2.1 基于固定分片数量2.2 基于动态分片数量2.3 基于…

让生活更加精致的APP?

晚上好&#xff0c;今天博主来介绍几款帮助你条理生活的APP&#xff0c;让你的生活更加精致&#xff0c;充满仪式感。 一&#xff0e;格志日记 一款以“格子”的方式记录日记的APP&#xff0c;非常简单明了&#xff0c;用户可以依据自己的喜好&#xff0c;来自由定义或者删除格…

初阶数据结构之---堆的应用(堆排序和topk问题)

引言 上篇博客讲到了堆是什么&#xff0c;以及堆的基本创建和实现&#xff0c;这次我们再来对堆这个数据结构更进一步的深入&#xff0c;将讲到的内容包括&#xff1a;向下调整建堆&#xff0c;建堆的复杂度计算&#xff0c;堆排序和topk问题。话不多说&#xff0c;开启我们今…

Python面向对象——程序架构

需求 创建图形管理器 -记录多种图形(圆形、矩形.) --提供计算总面积的方法&#xff0c; 要求:增加新图形&#xff0c;不影响图形管理器 测试: 创建图形管理器&#xff0c;存储多个图形对象。 通过图形管理器&#xff0c;调用计算总面积方法 思路 ​​​​​​​ 代码 # ------…

C# SM2加解密 ——国密SM2算法

SM2 是国家密码管理局组织制定并提出的椭圆曲线密码算法标准。 本文使用第三方密码库 BouncyCastle 实现 SM2 加解密&#xff0c;使用 NuGet 安装即可&#xff0c;包名&#xff1a;Portable.BouncyCastle&#xff0c;目前最新版本为&#xff1a;1.9.0。 using Org.BouncyCastl…