【数据结构】顺序表的深度刨剖析

news/2024/11/17 6:36:36/

前言:

在上一篇文章中,我们已经对数据结构有了一定了解,我们可以通过优化空间复杂度或者时间复杂度从而提高我们程序运行或存储速率。至此我们就知道了数据结构的重要性,所以今天我们将要了解和学习一种实用的数据结构——线性表

一、线性表概述:

线性表(linear list)是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列,是最基本、最简单也最常用的一种数据结构。

线性表中的数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其他数据元素都是首尾相连的(注意,这句话只适用大部分线性表,而不是全部。比如,循环链表逻辑层次上也是线性表,但存储层次上属于链式存储,是把最后一个数据元素的尾指针指向了首位节点)

线性表在逻辑上是线性结构,但是在物理结构并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。 常见的线性表:顺序表、链表、栈、队列、字符串等等

二、顺序表:

了解完线性表后,就要进入我们今天的主题,我们今天最主要学的的是线性表中的顺序表。

  1. 概念和结构:

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储,并在数组上完成数据的增删查改。其本质就是数组,但与数组不同的是:顺序表在其数组本质的基础上,还要求数据连续存储,不能跳跃或间隔存储。

顺序表一般可分为两类:

静态顺序表:使用一定长度的数组存储元素。但是静态顺序表存在很明显的缺陷,即大小固定,数据少了就会造成空间浪费,数据多了空间不够导致不能存储。

#define N 10
typedef int SLDataType;
typedef struct SeqList
{SLDataType arr[N];int size;
}SeqList;

动态顺序表:使用动态开辟的数组存储元素。动态顺序表很好弥补了静态顺序表的弊端,使空间申请变得灵活,我们可根据情况进行扩容操作从而申请到合适大小的空间。

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

2、顺序表的实现:

现在开始,我们开始实现顺序:

①初始化顺序表:

void SeqListInit(SeqList* ps)
{assert(ps);//防止传入空指针;ps->a = malloc(sizeof(SLDateType) * INIT_CAPACITY);if (ps->a == NULL){perror("malloc fail");}ps->size = 0;ps->capacity = INIT_CAPACITY;}

②销毁顺序表:

void SeqListDestroy(SeqList* ps)
{assert(ps);//防止传入空指针;free(ps->a);ps->a = NULL;ps->capacity = ps->size=0;
}

③顺序表尾插:

尾插即在最后一个元素下一个位置上插入元素,也就是size的位置上,插入之后,总数据+1也就是size++。

void SeqListPushBack(SeqList* ps, SLDateType x)
{assert(ps);//检查是否需要扩容if (ps->size == ps->capacity){SLDateType* tmp = (SLDateType)realloc(ps->a, sizeof(SLDateType) * ps->capacity + 5);if (tmp == NULL){perror("realloc fail");return;}ps->a = tmp;ps->capacity += 5;}ps->a[ps->size++] = x;
}

④顺序表尾删:

尾删就是把最后一个元素删除,所以size不能为0,删除之后总数据减一,size--。

void SeqListPopBack(SeqList* ps)
{assert(ps);assert(ps->size > 0);ps->size--;}

⑤顺序表头插:

头插也就是在第一个元素前面插入第一个元素,因为我们使用数组实现的顺序表所以头插需要挪动元素。

插入之后,总数据+1也就是size++。

void SeqListPushFront(SeqList* ps, SLDateType x)
{assert(ps);if (ps->size == ps->capacity){SLDateType* tmp = (SLDateType)realloc(ps->a, sizeof(SLDateType) * ps->capacity + 5);if (tmp == NULL){perror("realloc fail");return;}ps->a = tmp;ps->capacity += 5;}for (int i = ps->size; i > 0; i--){ps->a[i] = ps->a[i - 1];}ps->a[0] = x;ps->size++;}

⑥顺序表的头删除:

与头插类似,同样需要挪动元素,只不过挪动方向变了,头插是往后挪,头删是往前挪,删除之后总数据减一,size--。

void SeqListPopFront(SeqList* ps)
{assert(ps);int count = 1;for (count = 1; count <= ps->size; count++){ps->a[count - 1] = ps->a[count];}ps->size--;
}

⑦打印顺序表:

void SeqListPrint(SeqList* ps)
{if (ps->size == 0){printf("顺序表为空");return;}for (int i = 0; i < ps->size; i++){printf("%d ", ps->a[i]);}printf("\n");
}

⑧顺序表中查找:

int SeqListFind(SeqList* ps, SLDateType x)
{assert(ps);for (int i = 0; i < ps->size; i++){if (ps->a[i] == x){return i;}return -1;}
}

⑨在指定下标插入:

插入之后,总数据+1也就是size++。

void SeqListInsert(SeqList* ps, int pos, SLDateType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);if (ps->size == ps->capacity){SLDateType* tmp = (SLDateType)realloc(ps->a, sizeof(SLDateType) * ps->capacity + 5);if (tmp == NULL){perror("realloc fail");return;}ps->a = tmp;ps->capacity += 5;}for (int i = ps->size; i > pos;i--){ps->a[i] = ps->a[i - 1];}ps->a[pos] = x;ps->size++;
}

⑩删除指定下标位置元素:

删除之后总数据减一,size--。

void SeqListErase(SeqList* ps, int pos)
{assert(ps);assert(pos >= 0 && pos <= ps->size);for (int i = pos; i < ps->size-1; i++){ps->a[i] = ps->a[i + 1];}ps->size--;}

总结:

顺序表相对来说比较简单,很重要一点就是在执行操作时,要思考是否要进行断言操作,避免使用空指针。文章到此就结束啦。


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

相关文章

中科亿海微FPGA应用(一、点灯)

1.软件&#xff1a; https://download.csdn.net/download/weixin_41784968/87564071 需要申请license才能使用&#xff1a;软件试用申请_软件试用申请_中科亿海微电子科技&#xff08;苏州&#xff09;有限公司 2.开发板&#xff1a; 芯片EQ6HL45&#xff0c;42.5k LUT。 3…

Autosar诊断-DCM模块内的子模块

文章目录 前言一、DCM模块内的子模块1.1、DSL(Diagnostic Session Layer)1.2、DSD(Diagnostic Service Dispatcher)1.3、DSP(Diagnostic Service Processing)二、DCM和其他模块的交互2.1 DCM和PduR的交互2.2 DCM和ComM的交互总结前言 诊断通信管理(Diagnostic Communica…

摄影入门 | 相机的基本原理

一、获取图像——小孔成像实验 小孔成像实验中&#xff0c;点燃蜡烛&#xff0c;会在小孔另一面的白纸上看到一个倒立的烛焰。 此现象可以用来解释物理学原理&#xff1a;光在同种均匀介质中&#xff0c;在不受引力作用干扰的情况下沿直线传播。 这样&#xff0c;我们就用一种…

【CE进阶】lua脚本使用

▒ 目录 ▒&#x1f6eb; 导读需求开发环境1️⃣ 脚本窗口Lua ScriptLua EngineAuto assemble2️⃣ 全局变量3️⃣ 进程当前打开的进程ID系统的进程列表系统的顶部窗口列表4️⃣ 线程5️⃣ 输入设备6️⃣ 屏幕7️⃣ 剪贴板&#x1f6ec; 文章小结&#x1f4d6; 参考资料&#x…

AUTOSAR-各个模块作用初识(下)

文章目录 一、Autoasr整体框架图(Vector)二、各个模块简介13.AVB-Audio video Bridge13.1.vAVTP13.2.vSrp13.3.vRtp14.MCAL14.1.CAN driver14.2.ETH driver14.3.EthSwt14.4.FR14.5.LIN14.6.RamTst14.7.ADC-AD采集驱动程序14.8.DIO-通用的输入输出端口的控制驱动程序14.9.Eep-…

不做孔乙己也不做骆驼祥子

对教书育人的探讨前言一、为什么要“育人”1.育人为先2.育人是快乐的二、怎么“育人”前言 借着本次师德师风建设的主题&#xff0c;跟各位老师谈一谈对于“育人”的一些观点&#xff0c;和教育的一些看法。本文仅代表自己的观点&#xff0c;有不到位的地方&#xff0c;大家可以…

git为什么要先commit,然后pull,最后再push?而不是commit完直接push?

情况是这样的&#xff0c;现在远程有一个仓库&#xff0c;分支就一个&#xff0c;是master。然后我本地的仓库是从远程的master上clone下来的。大家都是clone下来&#xff0c;再在自己本地改好&#xff0c;再commit然后pull然后push&#xff0c;大家都是这么做的。那么现在问题…

java:序列化与反序列化

目录 序列化和反序列化的定义&#xff1a; 如何使用序列化&#xff1f; 总结 序列化和反序列化的定义&#xff1a; (1)Java序列化就是指把Java对象转换为字节序列的过程 比如可以将一个类转化为json类型 Java反序列化就是指把字节序列恢复为Java对象的过程。 (2)序列化最重要…