数据结构——顺序表seqlist

news2025/3/14 18:06:04

前言:大家好😍,本文主要介绍了数据结构——顺序表部分的内容

目录

一、线性表的定义

二、线性表的基本操作

三.顺序表

1.定义

2. 存储结构

3. 特点

四 顺序表操作

4.1初始化

4.2 插入

4.2.1头插

4.2.2 尾插

4.2.3 按位置插

4.3 删除

4.3.1 头删

4.3.2 尾删

 4.3.3 按位置删

4.3.4 按值删

4.4 查找 

4.5 删除值val出现的位置

4.6 其余操作

4.7 主函数测试


一、线性表的定义

线性表是具有相同数据类型n个数据元素有限序列,n为表长,当n=0时线性表时一个空表。用l命名线性表,表示为l=(a1,a2,  ,an)。

线性表除第一个元素之外,每个元素都有直接前驱,除最后一个元素之外每个元素都有直接后继

二、线性表的基本操作

Initlist(&L):初始化表,构造一个空的线性表L,构造一个空的线性表,分配内存空间

Destroylist(&L):销毁。销毁线性表并释放线性表L所占用的内存空间

Insertlist(&L,i,e):插入,在表L中第i个位置上插入指定元素e

Deletelist(&L,i,&e):删除,删除表L中第i个位置上的元素,并用e返回删除元素的值

LocateElem(L,e):按值查找,在表L中查找具有给定关键字e值的元素

   GetElem(L,i):按位查找,获取表L中第i个位置的元素的值

Length(L):求表长,返回线性表L的长度,即L中数据元素的个数

Printlist(L):输出,输出线性表所有元素值

Empty(L):判空,若L为空,返回true,否则返回false

对参数的修改结果需要引用&

三.顺序表

1.定义

顺序表是一种线性表的存储实现方式。线性表是具有相同数据类型的元素构成的有限序列,顺序表通过数组的形式将这些元素存储在内存中,并通过下标索引来访问和操作元素。

2. 存储结构

顺序表通常使用数组来实现,数组的每个位置存储一个元素。例如,一个顺序表可以表示为:

数组:[a0, a1, a2, ..., an-1]
其中,a0 是表头元素,an-1 是表尾元素。

3. 特点


优点:
随机访问:可以通过下标索引快速访问任意位置的元素,时间复杂度为 O(1)。
存储密度高:由于没有额外的指针存储空间,顺序表的存储利用率较高。
操作简单:基于数组的实现使得顺序表的操作逻辑相对简单。
缺点:
插入和删除效率低:插入或删除元素时,需要移动大量元素以保持顺序表的连续性,时间复杂度为 O(n)。
存储空间固定:顺序表的存储空间在初始化时需要预先分配,难以动态扩展。如果分配的空间不足,需要重新分配更大的空间并复制数据;如果分配过多,则会浪费空间。
内存碎片问题:频繁的动态扩展和收缩可能导致内存碎片化。

四 顺序表操作

点h文件中定义了一个顺序表(SeqList)的结构体

#define INIT_SIZE 10 //初始化时malloc购买的格子数量
//可库容的顺序表的结构体设计
typedef int ELEM_TYPE;
typedef struct SeqList
{
	ELEM_TYPE* elem;//用来接收malloc返回的数组首地址
	int length;//存放有效值个数
	int listsize;//存放数组的总的格子数
}SeqList, * PSeqList;
  • 作用:定义了一个宏 INIT_SIZE,表示顺序表初始化时分配的内存大小(即初始容量)。

  • INIT_SIZE 被设置为 10,表示初始化时会分配 10 个元素的空间。

  • 结构体名称SeqList,表示顺序表的结构体。

  • 指针类型别名PSeqList,表示指向 SeqList 的指针。

  • ELEM_TYPE* 表示 elem 是一个指针,指向 ELEM_TYPE 类型的数据。ELEM_TYPE 是一个类型别名

4.1初始化

void Init_SeqList(struct SeqList* psl)
{
	//0.安全处理   每一个函数都要写的
	assert(nullptr != psl);
	if (nullptr == psl)
	{
		exit(EXIT_FAILURE);
	}

	//1.对我们的 elem 用来去malloc 在堆区购买一块连续的空间
	psl->elem = (ELEM_TYPE*)malloc(INIT_SIZE * sizeof(ELEM_TYPE));
	if (NULL == psl->elem)
	{
		exit(EXIT_FAILURE);
	}

	//2.对我们的 length 初始化为0
	psl->length = 0;

	//3.对我们的 listsize 初始化为 INITSIZE
	psl->listsize = INIT_SIZE;

}
  • 类型转换malloc 返回的是 void* 类型的指针,需要强制转换为 ELEM_TYPE*

  • 安全检查:如果 malloc 分配失败(返回 NULL),程序会退出。

  • length:表示顺序表中当前存储的元素个数,初始值为 0。

  • listsize:表示顺序表当前分配的总容量,初始值为 INIT_SIZE

  • psl->elem 存储了这块内存的首地址。

  • 通过 psl->elem[i] 可以访问顺序表中的第 i 个元素。

  • 存储元素elem 指向的内存空间被用来存储顺序表中的所有元素。例如,如果 elem 指向的内存空间大小为 INIT_SIZE,则可以存储 INIT_SIZEELEM_TYPE 类型的元素。

4.2 插入

4.2.1头插

bool Insert_Seqlist_head(PSeqList psl, ELEM_TYPE val)
{
	//0.assert
	//0.5 判满
	if (Is_Full(psl))
	{
		Increase(psl);
	}

	//此时,肯定有空闲格子

	//1.集体向后挪(尾巴先动)
	for (int i = psl->length - 1; i >= 0; i--)
	{
		psl->elem[i + 1] = psl->elem[i];
	}

	//2.将val放入0号下标
	psl->elem[0] = val;

	//3.有效值个数+1
	psl->length++;
	return true;
}
  • 逻辑:从顺序表的尾部开始,逐个将元素向后移动一个位置。

    psl->elem[i + 1] = psl->elem[i]:将第 i 个元素移动到第 i + 1 个位置。
  • 循环条件:从 psl->length - 1 开始,直到 i = 0,确保所有元素都向后移动。

  • 更新顺序表的长度,反映新插入的元素。

  • 函数返回 true,表示插入操作成功

psl->length 表示顺序表中当前存储的有效元素的个数。例如:如果 psl->length 的值为 5,说明顺序表中有 5 个有效元素。

psl->length - 1 是对 psl->length 的值减去 1,如果 psl->length 为 5,那么最后一个有效元素的索引为 5 - 1 = 4。常用于从顺序表的最后一个有效元素开始,逐个向前遍历所有元素

4.2.2 尾插

bool Insert_Seqlist_tail(PSeqList psl, ELEM_TYPE val)
{
	//0.assert

	//0.5 判满
	if (Is_Full(psl))
	{
		Increase(psl);
	}

	//此时,肯定有空闲格子
	psl->elem[psl->length] = val;

	psl->length++;

	return true;
}

4.2.3 按位置插

bool Insert_Seqlist_pos(PSeqList psl, ELEM_TYPE val, int pos)
{
	//默认pos==0 则认为是头插

	//0.安全性处理   psl    pos合法性判断
	assert(nullptr != psl);
	assert(pos >= 0 && pos <= psl->length);

	//0.5 判满
	if (Is_Full(psl))
	{
		Increase(psl);
	}

	//此时,肯定有空闲格子
	//1.将插入位置之后的元素,统一向后挪动,把插入位置给空出来
	for (int i = psl->length - 1; i >= pos; i--)
	{
		psl->elem[i + 1] = psl->elem[i];
	}

	//2.插入

	psl->elem[pos] = val;

	//3.length++
	psl->length++;

	return true;
}

通过 psl->elem[i] 可以访问顺序表中的第 i 个元素。

4.3 删除

4.3.1 头删

bool Del_Seqlist_head(SeqList* psl)
{
	//0.assert

	//0.5 判空
	if (Is_Empty(psl))
		return false;

	//1.除了第一个元素之外,统一向前挪动
	for (int i = 1; i <= psl->length - 1; i++)
	{
		psl->elem[i - 1] = psl->elem[i];
	}

	//2.有效值个数-1
	psl->length--;

	return true;
}

//1.除了第一个元素之外,统一向前挪动
    for (int i = 1; i <= psl->length - 1; i++)
    {
        psl->elem[i - 1] = psl->elem[i];
    }

 //1.集体向后挪(尾巴先动)
    for (int i = psl->length - 1; i >= 0; i--)
    {
        psl->elem[i + 1] = psl->elem[i];
    }

4.3.2 尾删

//尾删
bool Del_Seqlist_tail(SeqList* psl)
{
	//0.assert

	//0.5 判空
	if (Is_Empty(psl))
		return false;

	psl->length--;

	return true;
}

 4.3.3 按位置删

bool Del_Seqlist_pos(SeqList* psl, int pos)
{
	//0.assert psl pos
	assert(psl != NULL);
	assert(pos >= 0 && pos < psl->length);

	//0.5 判空isempty
	if (Is_Empty(psl))
		return false;

	//1.将pos位置之后的有效值,统一向前覆盖(头先动)
	for (int i = pos + 1; i <= psl->length - 1; i++)
	{
		psl->elem[i - 1] = psl->elem[i];
	}


	//2.有效值个数-1
	psl->length--;

	return true;
}

4.3.4 按值删


//按值删(只删除这个val值出现的第一次的位置)
bool Del_Seqlist_val(SeqList* psl, ELEM_TYPE val)
{
	//0.assert
	//0.5 isempty

	//1.通过调用查找函数,查找val值在顺序表中的位置
	int index = Search_SeqList(psl, val);

	//2.若返回的位置下标为-1 返回假  若不等于-1,则此时怎么删
	if (index == -1)
		return false;

	return Del_Seqlist_pos(psl, index);
}

4.4 查找 


//4.查找数据是否已经存在(若存在,则只需要返回下标即可  找不到返回-1)
int Search_SeqList(PSeqList psl, ELEM_TYPE val)
{
	//0.assert

	for (int i = 0; i < psl->length; i++)
	{
		if (psl->elem[i] == val)
			return i;
	}

	return -1;
}

4.5 删除值val出现的位置

//删除当前val值出现的所有位置(1)
bool Del_SeqList_All_Val1(struct SeqList* psl, ELEM_TYPE val)
{
	int count = 0;
	for (int i = 0; i < psl->length; i++)
	{
		if (psl->elem[i] == val)
		{
			count++;
		}
	}

	for (int i = 0; i < count; i++)
	{
		int index = Search_SeqList(psl, val);
		Del_Seqlist_pos(psl, index);
	}

	return true;

}

 

//删除当前val值出现的所有位置(2)
bool Del_SeqList_All_Val2(struct SeqList* psl, ELEM_TYPE val)
{
	int qianfangkongxiangezishu = 0;
	for (int i = 0; i < psl->length; i++)
	{
		if (psl->elem[i] == val)
			qianfangkongxiangezishu++;
		else
			psl->elem[i - qianfangkongxiangezishu] = psl->elem[i];
	}
	psl->length = psl->length - qianfangkongxiangezishu;
	return true;
}

4.6 其余操作

//5.判空
bool Is_Empty(PSeqList psl)
{
	return psl->length == 0;
}

//6.判满
bool Is_Full(PSeqList psl)
{
	return psl->length == psl->listsize;
}

//7.扩容函数(1.5 2)   默认用2倍扩容
void Increase(PSeqList psl)
{
	ELEM_TYPE* tmp = (ELEM_TYPE*)realloc(psl->elem, psl->listsize * sizeof(ELEM_TYPE) * 2);
	if (tmp != nullptr)
	{
		psl->elem = tmp;
	}

}

//8.清空  (不释放已购买的内存)
void Clear(PSeqList psl)
{
	//malloc申请空间先不释放,而是认为所有格子里都是无效值
	psl->length = 0;
}

//9.销毁  (需要释放malloc购买的内存的)
void Destroy(PSeqList psl)
{
	free(psl->elem);
	psl->length = psl->listsize = 0;
}


//打印
void Show(PSeqList psl)
{
	//assert

	for (int i = 0; i < psl->length; i++)
	{
		printf("%d ", psl->elem[i]);
	}

	printf("\n");

}

4.7 主函数测试

int main()
{
	struct SeqList sq;

	Init_SeqList(&sq);

	Insert_Seqlist_head(&sq, 100);
	Insert_Seqlist_head(&sq, 101);
	Insert_Seqlist_head(&sq, 102);
	Insert_Seqlist_tail(&sq, 200);
	Insert_Seqlist_tail(&sq, 201);
	Insert_Seqlist_tail(&sq, 202);
	Insert_Seqlist_tail(&sq, 2000);
	Insert_Seqlist_tail(&sq, 2010);
	Insert_Seqlist_tail(&sq, 2020);
	Insert_Seqlist_pos(&sq, 10000, 3);
	Show(&sq);

	Insert_Seqlist_head(&sq, 111);
	Insert_Seqlist_tail(&sq, 222);
	Show(&sq);

	//删除
	Del_Seqlist_head(&sq);
	Del_Seqlist_tail(&sq);
	Show(&sq);

	Del_Seqlist_pos(&sq, 4);
	Show(&sq);
	Del_Seqlist_pos(&sq, 8);
	Show(&sq);
	Del_Seqlist_pos(&sq, 0);
	Show(&sq);

	Del_Seqlist_val(&sq, 201);
	Show(&sq);

	//Clear(&sq);
	//Show(&sq);

	//Destroy(&sq);
	//Show(&sq);

	//------------------------------------------------
	Insert_Seqlist_pos(&sq, 3, 2);
	Insert_Seqlist_pos(&sq, 3, 4);
	Insert_Seqlist_pos(&sq, 3, 6);
	Show(&sq);

	Del_SeqList_All_Val2(&sq, 3);
	Show(&sq);

	return 0;
}

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

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

相关文章

使用位运算如何找到数组中只出现一次的数?

题目链接&#xff1a;137. 只出现一次的数字 II - 力扣&#xff08;LeetCode&#xff09; 算法解析 位运算是用于二进制的运算符号。而对于多次出现的数字&#xff0c;其二进制都是一模一样的&#xff0c;这里是3次重复的出现是数字。由此我们可以想到&#xff0c;如果我们由低…

Linux笔记之通配符和正则表达式的区别

Linux笔记之通配符和正则表达式的区别 code review! 参考笔记 1.Linux笔记之通配符和正则表达式的区别 2.C++笔记之C语言中的换行符和转义符 文章目录 Linux笔记之通配符和正则表达式的区别1.通配符概念2.通配符和正则表达式的区别3.C++或C语言中有没有通配符?4.Linux Bash脚…

防汛应急包,快速响应,守护安全

根据中国水利部统计&#xff0c;自1949年以来&#xff0c;我国几乎每年都面临洪水威胁&#xff0c;其中20世纪90年代后洪涝灾害频率显著增加&#xff0c;仅1990-2009年间就发生超4000起较大灾害&#xff0c;直接经济损失近3万亿元&#xff0c;受灾人口达20亿人次。在2020年长江…

小记一下Zookeeper配置中心的部分原理

记录一下&#xff0c;这里其实很类似nacos的Value&#xff0c;注解&#xff0c;可以结合去理解。 Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {Class<?> beanClass bean.getClass();Field[] fields …

蓝桥杯备赛-基础训练(四)字符串 day17

好久不见&#xff0c;今天开始继续更新&#xff0c;或许拿不了奖&#xff0c;但是希望记录自己学习的过程&#xff0c;如果感觉有收获的同学在下面多多评论说说我代码的缺陷&#xff0c;感谢大家&#xff01; 1、反转字符串 编写一个函数&#xff0c;其作用是将输入的字符串反…

软件工程概述、软件过程模型、逆向工程(高软45)

系列文章目录 软件工程概述、软件过程模型、逆向工程。 文章目录 系列文章目录前言一、软件工程概述二、能力成熟度模型1.能力成熟度模型CMM2.能力成熟度模型集成CMMI 三、软件过程模型1.瀑布模型SDLC2.原型化模型3.螺旋模型4.增量模型5.喷泉模型6.敏捷模型7.统一过程模型RUP 四…

数据结构--邻接表

回顾上节&#xff1a; 邻接矩阵--数组实现的顺序存储&#xff0c;空间复杂度高&#xff0c;不合适存储稀疏图。On^2 一、邻接表法&#xff08;顺序链式存储&#xff09; 无向图&#xff1a; 用一维数组存储顶点信息&#xff0c;使用指针存储顶点的第一条边/弧。对于边/弧&…

ChromeOS 134 版本更新

ChromeOS 134 版本更新 一、ChromeOS 134 更新内容 1. ChromeOS 自助终端&#xff08;Kiosk&#xff09;模式支持隔离 Web 应用&#xff08;Isolated Web Apps&#xff09; 从 ChromeOS 134 开始&#xff0c;自助终端&#xff08;Kiosk&#xff09;模式支持 隔离 Web 应用&a…

node.js-WebScoket心跳机制(服务器定时发送数据,检测连接状态,重连)

1.WebScoket心跳机制是&#xff1f; 基于上一篇文章&#xff0c;WebScoket在浏览器和服务器间完成一次握手&#xff0c;两者间创建持久性连接&#xff0c;并进行双向数据连接。node.js-node.js作为服务器&#xff0c;前端使用WebSocket&#xff08;单个TCP连接上进行全双工通讯…

【蓝桥杯—单片机】第十五届省赛真题代码题解析 | 思路整理

第十五届省赛真题代码题解析 前言赛题代码思路笔记竞赛板配置建立模板明确基本要求显示功能部分频率界面正常显示高位熄灭 参数界面基础写法&#xff1a;两个界面分开来写优化写法&#xff1a;两个界面合一起写 时间界面回显界面校准校准过程校准错误显示 DAC输出部分按键功能部…

VLAN和Trunk实验

VLAN和Trunk实验 实验拓扑 实验需求 1.按照图示给所有路由器&#xff08;此处充当pc机&#xff09;配置IP地址 2.SW1和SW2上分别创建vlan10和vlan20&#xff0c;要求R1和R3属于vlan10&#xff0c;R2和R4属于vlan20 3.SW1和SW2相连的接口配置类型为trunk类型&#xff0c;允许…

鸿蒙开发-一多开发之媒体查询功能

在HarmonyOS中&#xff0c;使用ArkTS语法实现响应式布局的媒体查询是一个强大的功能&#xff0c;它允许开发者根据不同的设备特征&#xff08;如屏幕尺寸、屏幕方向等&#xff09;动态地调整UI布局和样式。以下是一个使用媒体查询实现响应式布局的实例&#xff1a; 1. 导入必要…

【Go学习】04-1-Gin框架-路由请求响应参数

【Go学习】04-1-Gin框架 初识框架go流行的web框架GinirisBeegofiber Gin介绍Gin快速入门 路由RESTful API规范请求方法URI静态url路径参数模糊匹配 处理函数分组路由 请求参数GET请求参数普通参数数组参数map参数 POST请求参数表单参数JSON参数 路径参数文件参数 响应字符串方式…

数据类设计_图片类设计之5_不规则类图形混合算法(前端架构)

前言 学的东西多了,要想办法用出来.C和C是偏向底层的语言,直接与数据打交道.尝试做一些和数据方面相关的内容 引入 接续上一篇,讨论图片类型设计出来后在场景中如何表达,以及不规则图片的混合算法. 图片示意图 图片是怎样表示的,这里把前面的补上 这里的数字1是不规则数据类对…

【模拟CMOS集成电路设计】带隙基准(Bandgap)设计与仿真(基于运放的电流模BGR)

【模拟CMOS集成电路设计】带隙基准&#xff08;Bandgap&#xff09;设计与仿真 前言工程文件&部分参数计算过程&#xff0c;私聊~ 一、 设计指标指标分析&#xff1a; 二、 电路分析三、 仿真3.1仿真电路图3.2仿真结果(1)运放增益(2)基准温度系数仿真(3)瞬态启动仿真(4)静态…

版本控制器Git(4)

文章目录 前言一、分布式版本控制系统的概念二、克隆远程仓库三、多用户协作与公钥管理四、配置Git忽略特殊文件五、给命令配置别名总结 前言 加油加油&#xff0c;路在脚下&#xff01;&#xff01;&#xff01; 一、分布式版本控制系统的概念 本地操作&#xff1a;所有操作&a…

Rabbitmq--延迟消息

13.延迟消息 延迟消息&#xff1a;生产者发送消息时指定一个时间&#xff0c;消费者不会立刻收到消息&#xff0c;而是在指定时间之后才会收到消息 延迟任务&#xff1a;一定时间之后才会执行的任务 1.死信交换机 当一个队列中的某条消息满足下列情况之一时&#xff0c;就会…

springboot436-基于SpringBoot的汽车票网上预订系统(源码+数据库+纯前后端分离+部署讲解等)

&#x1f495;&#x1f495;作者&#xff1a; 爱笑学姐 &#x1f495;&#x1f495;个人简介&#xff1a;十年Java&#xff0c;Python美女程序员一枚&#xff0c;精通计算机专业前后端各类框架。 &#x1f495;&#x1f495;各类成品Java毕设 。javaweb&#xff0c;ssm&#xf…

宇树ROS1开源模型在ROS2中Gazebo中仿真

以GO1为例 1. CMakelists.txt更新语法 cmake_minimum_required(VERSION 3.8) project(go1_description) if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")add_compile_options(-Wall -Wextra -Wpedantic) endif() # find dependencies find…

Web网页制作之爱家居的设计(静态网页)

一、使用的是PyCharm来敲写的代码&#xff08;布局&#xff09; 二、主要的html代码的介绍 这段代码展示了如何使用HTML和CSS创建一个结构化的网页&#xff0c;包含导航栏、新闻内容、图片展示和页脚信息。通过引入外部CSS文件&#xff0c;可以进一步美化和布局这些元素。 HTM…