数据结构——线性数据结构(C语言实现顺序表详解)

news2024/11/29 4:54:19

1.什么线性表

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

在讲顺序表之前,我们先大致了解一下线性表。线性表在逻辑上是一种线性的数据结构。可以把线性表看成一条连续的直线。但是在物理结构上不一定是连续的,线性表在存储时,通常是以数组或者链式结构的形式存储的。

2.什么是顺序表

顺序表的概念:顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。
顺序表的特点:存储数据的数组可以动态调整,数据在内存中是连续存储的。

在这里插入图片描述

3.顺序表的实现

3.1 顺序表的定义

静态顺序表的内容为存放数据的数组和记录数据个数的变量。静态顺表的缺点比较明显,因为数组开辟必须一次性开辟完成,所以对于空间的利用率不佳。动态顺序表的内容为一个指向动态开辟空间的指针、记录数据个数的变量和记录当前顺序表容量的变量。动态顺序表对于空间的利用率较好,但是数据的增删查改效率一般。

静态版本定义

在这里插入图片描述

//静态顺序表
#define N 100
typedef int SeqLTDataType;

typedef struct SeqList
{
	SeqLTDataType data[N];//数据
	int size;//记录当前顺序表元素个数
}SeqList;

动态态版本定义

在这里插入图片描述

//动态顺序表

typedef int SeqLTDataType;
typedef struct SeqList
{
	SeqLTDataType* data;//指向动态开辟的连续空间
	int size;//记录当前顺序表元素个数
	int capacity;//记录当前空间容量
}SeqList;

3.2 动态顺序表初始化

初始化动态顺序表接口,首先我们要开辟一块空间来存放数据,这里我就默认开辟4*sizeof(数据类型)字节空间来存放数据。所以容量初始化成4。由于还没存放数据,所以将size初始化成0。
在这里插入图片描述

#define DEF_CAPACITY 4

void SeqListInit(SeqList* SL)
{
	assert(SL);

	SeqLTDataType*  tmp = (SeqLTDataType*)malloc(sizeof(SeqLTDataType) * DEF_CAPACITY);
	if (NULL == tmp)
	{
		perror("malloc fail");
		return;
	}
	SL->data = tmp;
	SL->size = 0;
	SL->capacity = DEF_CAPACITY;
	
}

3.3 动态顺序表销毁

销毁顺序表需要释放动态申请的空间和将定义的变量清0。
在这里插入图片描述

void SeqListDestroy(SeqList* pSL)
{
	assert(pSL);

	free(pSL->data);
	pSL->data = NULL;
	pSL->capacity = 0;
	pSL->size = 0;

}

3.4动态顺序表打印

顺序表的打印就是遍历一遍顺序表,打印每个数据类型指针偏移量位置相对应的数据。

void SeqListPrint(SeqList* pSL)
{
	assert(pSL);

	for (int i = 0; i < pSL->size; i++)
	{
		printf("%d ",pSL->data[i]);
	}
	printf("\n");
}

3.5 动态顺序表检查当前容量

因为默认开辟的数据存放大小是4*数据类型大小的字节的空间,所以当我们的数据个数等于当前容量标记时,我们需要对申请的数据空间进行扩容。因为每次插入数据前都要进行检查,每次扩容当前容量的2倍大小的新容量,所以我们直接封装一个函数来实现该功能。

void CapacityCheck(SeqList* pSL)
{
	if (pSL->size == pSL->capacity)
	{
		//先创建个临时变量存放扩容后的地址
		SeqLTDataType* tmp = (SeqLTDataType*)realloc(pSL->data, sizeof(SeqLTDataType) * pSL->capacity * 2);
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		pSL->data = tmp;
		pSL->capacity *= 2;

	}
}

我们应该考虑realloc异地扩容的问题,我们不能直接在原数组上直接realloc重新申请空间。每次容量乘2倍,虽然一开始可能realloc扩容后,还是在原空间后申请到连续的空间。但是,当申请的连续空间过大,可能无法满足在申请前空间后接续扩容,realloc函数会找到一块符合要求的新空间,并把数据拷贝到新空间中。
在这里插入图片描述

3.6 动态顺序表头插数据

头插数据的本质是将头插前的数据整体向后移动一个数据字节大小的偏移量,然后在起始地址处插入新数据。实现思路如下,应该从后往前移动数据,即将最后一个数据即,pSL->data[pSL->size]向后移动一位,从后往前遍历整个数据进行后移操作。将新数据插入pSL->data[0]中。在每次插入时要检查当前容量是否充足,若不足就扩容。
在这里插入图片描述

void SeqListPushFront(SeqList* pSL, SeqLTDataType x)
{
	assert(pSL);
	CapacityCheck(pSL);

	for (int i = pSL->size; i > 0; i--)
	{
		pSL->data[i] = pSL->data[i-1];
	}
	
	pSL->data[0] = x;
	pSL->size++;
}

3.7动态顺序表头删数据

头删数据就是从第二个数据后向后遍历数组,依次覆盖前一个位置的数据达到头删的效果。将当前的数据赋给前一个位置,所以循环必须从第二个数据位置开始。

在这里插入图片描述

void SeqListPopFront(SeqList* pSL)
{
	assert(pSL);
	assert(pSL->size);

	for(int i = 1; i < pSL->size; i++)
	{
		pSL->data[i - 1] = pSL->data[i];
	}

	pSL->size--;
}

3.8动态顺序表尾插数据

尾插数据就是在size为偏移量的位置处插入数据,然后size++即可。

void SeqListPushBack(SeqList* pSL, SeqLTDataType x)
{
	assert(pSL);

	CapacityCheck(pSL);
	pSL->data[pSL->size++] = x;

}

3.9动态顺序表尾删数据

尾删数据的本质就是让size–,然后下一个数据便可以覆盖未尾删前的数据了。

void SeqListPopBack(SeqList* pSL)
{
	assert(pSL);
	assert(pSL->size);//空表不可删

	pSL->size--;
}

3.10查找某个数据的位置

既然是查找就要遍历数据,这里我们返回的是数组的下标位置。若找不到返回-1。

int SeqListFind(SeqList* pSL, SeqLTDataType x)
{
	assert(pSL);

	for (int i = 0; i < pSL->size; i++)
	{
		if (pSL->data[i] == x)
			return i;
	}
	return -1;
}

3.11修改pos位置数据

前面查找函数的返回值就可以做为我们设计修改函数的参数。修改顺序表数据的本质就是修改对应下标数据的值。

void SeqListModify(SeqList* pSL, int pos, SeqLTDataType x)
{
	assert(pSL);
	assert(pos >= 0 && pos <= pSL->size);//判断下标合法性

	pSL->data[pos] = x;

}

3.12 pos位置插入数据

这就类似于头插数据,需要先将pos位置到size位置的数据整体后移一个偏移量。然后插入新的数据
在这里插入图片描述

void SLInsert(SL* ps, int pos, SeqListtype x)
{
	assert(ps && (pos >= 0 && pos < ps->size));

	for (int i = ps->size; i > pos; i--)
	{
		ps->data[i] = ps->data[i - 1];
	}
	ps->data[pos] = x;
	ps->size++;
}

3.13 pos位置删除数据

在这里插入图片描述

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

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

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

相关文章

qt .pro文件 qmake编译过程

#&#xff1a;注释一行 QT&#xff1a;此项目中使用的Qt modules列表 CONFIG&#xff1a;此项目中使用的配置选项 TARGET&#xff1a;目标输出文件的名字 TEMPLATE&#xff1a;当生成二进制文件时项目的模版&#xff0c;例如app,lib 平台下使用 windows { SOURCES SysInf…

剑指 Offer II 024. 反转链表

题目链接 剑指 Offer II 024. 反转链表 easy 题目描述 给定单链表的头节点 head&#xff0c;请反转链表&#xff0c;并返回反转后的链表的头节点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1] 示例 2&#xff1a; 输入&#xff1a;h…

不用费劲,这5款效率工具为你解决学习工作烦恼

今天我要向大家推荐5款超级好用的效率软件&#xff0c;无论是在学习还是办公中都能够极大地提高效率。这些软件可以帮助你解决许多问题&#xff0c;而且每个都是真正的神器。 1.键盘仿真鼠标——NeatMouse NeatMouse 是一个小型的工具能够使用鼠标光标控制指针。当你的鼠标不…

python编程基础

python编程基础 1、什么是编程语言&#xff1f; 编程语言是用来控制计算机的一系列指令&#xff08;Instruction&#xff09;&#xff0c;它有固定的格式和词汇&#xff08;不同编程语言的格式和词汇不一样&#xff09;&#xff0c;必须遵守&#xff0c;否则就会出错&#xf…

opencv加水印

本文介绍opencv给图片加水印的方法。 目录1、添加水印1.1、铺满1.2、在指定区域添加1.3、一比一铺满1、添加水印 添加水印的原理是调低两张图片的透明度&#xff0c;然后叠加起来。公式如下&#xff1a; dst src1 * opacity src2 * (1 - opacity) gamma; opacity是透明度&a…

UE官方教程笔记02-实时渲染基础下

对官方教程视频[官方培训]02-实时渲染基础下 | 陈拓 Epic的笔记没听懂的地方就瞎写反射实时渲染中反射是一个非常有挑战的特性UE中有多种不同的方案&#xff0c;各有各的优势和缺点反射捕获屏幕空间反射平面反射LumenRT Reflection反射捕获在指定位置捕获一张Cube Map需要预计算…

低代码:助力乡村振兴事业开启“智慧模式”

伴随着脱贫攻坚目标任务的全面完成&#xff0c;我国“三农”工作重心历史性地转向全面推进乡村振兴&#xff0c;这也标志着我国农业农村工作迈上了一个新台阶。 什么是乡村振兴&#xff1f; 乡村振兴是新时代“三农”工作的总抓手&#xff0c;坚持农业农村优先发展&#xff0c;…

windows 下docker 安装clickhouse

docker 下载https://www.docker.com/products/docker-desktop/将下载下来的Docker Desktop Installer.exe文件双击进行安装即可&#xff0c;安装完成后&#xff0c;任务栏会出现一个蓝色的小鲸鱼图标&#xff08;注意安装完成后可能会重启系统&#xff09;Docker Desktop如果出…

禁用XXE处理漫谈

前言 近期准备面试题时&#xff0c;XXE漏洞防范措施&#xff08;或者说修复方式&#xff09;在一些文章中比较简略&#xff0c; 故本文根据研究进行总结&#xff0c;作为技术漫谈罢了。 简述 XXE漏洞 XXE&#xff08;XML外部实体注入&#xff09;&#xff0c;程序解析XML数…

国产8K摄像机拍摄回顾与画面数据反馈

本文分析两款国产8K摄像机&#xff0c;一款是全画幅&#xff0c;一款是M43画幅。一、全新国产全画幅8K B1机器参数数据汇总&#xff1a;全画幅8K 60fps&#xff0c;受益于8K全画幅的优势与大幅升级的图像处理系统&#xff0c;BOSMA 8K摄像机系统提升到新的高度。拍摄支持&#…

Ubuntu 安装 CUDA and Cudnn

文章目录0 查看 nvidia驱动版本1 下载Cuda2 下载cudnn参考&#xff1a;0 查看 nvidia驱动版本 nvidia-smi1 下载Cuda 安装之前先安装 gcc g gdb 官方&#xff1a;https://developer.nvidia.com/cuda-toolkit-archive&#xff0c;与驱动版本进行对应&#xff0c;我这里是12.0…

C++语法规则1(C++面向对象 )

C面向对象 面向对象的三大特征是继承&#xff0c;多态和封装&#xff0c;C重面向对象重要的就是这些&#xff0c;我们下面通过一些简单的实例加以理解&#xff0c;从这小节开始&#xff0c;我们将开启新的编程旅途。与 C 语言编程的思想完全不同了&#xff0c;这就是 C!理解概…

[Linux基础]history相关的环境变量设置

目录 背景 简介 命令操作 1. 语法&#xff1a; 2. 功能 3. 参数 环境变量设置 背景 工作中时常收到客户的反馈&#xff0c;我的系统什么也没干&#xff0c;就出现文件丢失&#xff0c;程序错误等等问题&#xff1b;我们在问题排查的时候查看history信息也是重要环节…

大数据导论、Apache ZooKeeper

目录标题1、数据与数据分析2、数据分析基本步骤3、大数据时代4、分布式技术5、 Apache ZooKeeper5.1 ZooKeeper 概述5.2 ZooKeeper 特性5.3 ZooKeeper 集群角色5.4 ZooKeeper 集群搭建5.5 ZooKeeper 数据模型1、数据与数据分析 数据分析是指用适当的统计分析方法对收集来的数据…

零基础小白如何自学网络安全成为顶尖黑客?

在成为黑客之前&#xff0c;你需要做两点准备&#xff1a; 1、学一门编程语言。学哪一门不重要&#xff0c;但你要参考一下下面的条例&#xff1a; C语言是Unix系统的基础。它&#xff08;连同汇编语言&#xff09;能让你学习对黑客非常重要的知识&#xff1a;内存的工作原理…

Go爬虫学习笔记(二)

3 进阶路线&#xff1a;如何深入学习Go语言&#xff1f; 时间与复利思维 一万小时定律 - MBA智库百科 (mbalib.com)&#xff1a;大量训练。 思维模型 类比&#xff1a;类比旧知识知识组块&#xff1a;将知识拆分知识体系&#xff1a;知识之间的联系&#xff1a;wiki、笔记双链…

漏洞分析丨cve-2012-0003

作者:黑蛋一、漏洞简介这次漏洞属于堆溢出漏洞&#xff0c;他是MIDI文件中存在的堆溢出漏洞。在IE6&#xff0c;IE7&#xff0c;IE8中都存在这个漏洞。而这个漏洞是Winmm.dll中产生的。二、漏洞环境虚拟机调试工具目标软件辅助工具XP-SP3、KaliOD、IDAIE6Windbg组件gflags.exe三…

Java 不同路径

不同路径中等一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。问总共有多少条不同的路径&#xff1f…

直播间与2位优秀创作者分享经历

我是卢松松&#xff0c;点点上面的头像&#xff0c;欢迎关注我哦&#xff01; 昨天&#xff0c;卢松松的直播间好像又被推荐给了2.9万人观看&#xff0c;讲了一个小时后直播间的人数一直攀升&#xff0c;最终冲破了2万人大关。晚些时候&#xff0c;白杨SEO也来到了我的直播间&…

【数据结构】——树与二叉树

文章目录树二叉树二叉树的性质完全二叉树二叉树的存储遍历二叉树和线索二叉树6.4 树和森林哈夫曼树应用树 树的定义&#xff1a;树是以分支关系定义的层次结构。 D; 树(Tree)是n(n≥0)个结点的有限集。 R 数据关系 有且仅有一个特定的称为根(Root) 的结点 当n>1时&…