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

news2024/11/26 1:46:42

🌇个人主页:平凡的小苏

📚学习格言:别人可以拷贝我的模式,但不能拷贝我不断往前的激情

🛸C语言专栏:https://blog.csdn.net/vhhhbb/category_12174730.html

🚀数据结构专栏:https://blog.csdn.net/vhhhbb/category_12211053.html

        家人们更新不易,你们的👍点赞👍和⭐关注⭐真的对我真重要,各位路过的友友麻烦多多点赞关注,欢迎你们的私信提问,感谢你们的转发!

        关注我,关注我,关注我,你们将会看到更多的优质内容!!

目录

1、顺序表概念

2、函数接口的实现

2.1、顺序表的初始化

2.2、顺序表的插入操作

2.3、顺序表的删除操作 

2.4、顺序表的插入和删除的时间复杂度

2.5、线性表的顺序存储结构的优缺点

2.6、顺序表的查找

2.7、顺序表的销毁

3、顺序表源码

SList.c

SList.h

Test.c


 

1、顺序表概念

线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表的数据元素

  • 线性表的存储结构,说白了,就是在内存中找块地儿,通过占位的形式,把一块内存空间给占了,然后把相同数据类型的数据元素依次存放在这块空地中。既然线性表的每个数据都相同,所以可以用C语言(其他语言也相同)的一维数组来实现顺序存储结构,即把第一个数据元素存到数组下标为0的位置中,接着把线性表相邻的元素存储在数组中相邻的位置。

2、函数接口的实现

  来看线性表顺序存储的结构代码。

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#define InitCapa 4;//初始容量
typedef int SLDateType;
typedef struct SeqList
{
	SLDateType* a; //动态分配数组,存储数据元素
	int size;//数组元素个数
	int capacity;//数组容量的大小
}SeqList;

2.1、顺序表的初始化

void SeqListInit(SeqList* ps)
{
	assert(ps);
	ps->a = (SLDateType*)malloc(sizeof(SLDateType) * 4);
	ps->size = 0;
	ps->capacity = InitCapa;
}

注:顺序表的初始化首先要动态分配容量为4的数组。数组元素的个数初始化为0.

2.2、顺序表的插入操作

         我们现在来考虑,如果要实现线性的插入操作,即在顺序表的第i个位置插入新元素e,应该如何操作?

        举个栗子,本来我们在春运时去买火车票,大家都排队排的好好的。这时来了一个抱着孩子的年轻妈妈,对着队伍中排在第三位的你说,“大哥,求求你帮帮忙,我家里母亲有病,我得急着回去看她,你看我还抱着孩子,这队伍这么长,你可否让我排在你的前面,你心一软,就同意了。这时,你必须得退后一步。骂声四起。但后面得人不清楚这加塞是怎么回事,没什么办法。

        这个例子已经说明了线性表得顺序存储结构,在插入数据时得实现过程(如下图所示)

实现代码如下:

void CheckCapacity(SeqList* ps)
{
	if (ps->size == ps->capacity)
	{
		SLDateType* tmp = (SLDateType*)realloc(ps->a,sizeof(SLDateType) * ps->capacity * 2);
		if (tmp == NULL)
		{
			perror("realloc fail:");
			exit(-1);
		}
		ps->capacity *= 2;
		ps->a = tmp;
	}
}
void SeqListInsert(SeqList* ps, int pos, SLDateType x)
{
	assert(ps);
	CheckCapacity(ps);//检查容量函数,只要是插入元素得操作,都应该检查容量
	int end = ps->size-1;
	while (end >= pos)//每个元素往后移动
	{
		ps->a[end + 1] = ps->a[end];
		end--;
	}
	ps->a[pos] = x;
	ps->size++;
}

 插入算法得思路:

(1)如果顺序表得长度大于等于数组长度,则动态增加容量;

(2)从最后一个元素开始向前遍历到第i个位置,分别将它们都向后移动一个位置;

(3)将要插入得元素填入位置i处

(4)表长加1;

2.3、顺序表的删除操作 

        接着刚才的栗子。此时后面的人群意见都很大,都说怎么可以这样,不管什么原因,插队就是不行,有本事,找火车站开后门去。就在这时,远处跑来一胖子,对着这个美女喊,可找到你了,你这个骗子,还我钱。只见女子二话不说,突然就冲出了队伍,胖子追在其后。哦,原来她是倒卖火车票的黄牛,刚才还在装可怜。于是排队的人群,又像蠕虫一样,都向前移动了一步,骂声渐息,队伍又恢复了平静。

        这就是顺序表的顺序存储结构的删除元素的过程实现(如下图所示)

实现代码如下:

void SeqListErase(SeqList* ps, int pos)
{
	assert(ps);
	assert(ps->size);//如果容量为0,就抛出异常,不可以再删除
	int begin = pos;
	while (begin < ps->size-1)
	{
		ps->a[begin] = ps->a[begin + 1];
		begin++;
	}
	ps->size--;
}

 删除算法的思路:

(1)从删除元素位置开始遍历到最后一个元素位置,分别将它们都向前移动一个位置;

(2)表长减1;

2.4、顺序表的插入和删除的时间复杂度

  •  先看最好的情况,如果元素要插入到最后一个位置,或者删除最后一个元素时的时间复杂度为O(1),因为不需要移动元素。
  • 最坏的情况呢,如果元素要插入到第一个位置或者删除第一个元素,此时的时间复杂度是多少呢?这就意味着要移动所有的元素向后或者向前,所以这个时间复杂度为O(n).

2.5、线性表的顺序存储结构的优缺点

优点:

  • 无需为表示表中的元素之间的逻辑关系而增加额外的存储空间
  • 可以快速地存取表中任意位置的元素

缺点:

  • 插入和删除的操作需要移动大量的元素

2.6、顺序表的查找

实现代码如下:

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;
}

注:就是遍历查找的过程

2.7、顺序表的销毁

 实现代码如下:

void SeqListDestroy(SeqList* ps)
{
	assert(ps);
	free(ps->a);
	ps->size = ps->capacity = 0;
	ps->a = NULL;
}

3、顺序表源码

SList.c

//SList.c
#include"SList.h"
void SeqListInit(SeqList* ps)
{
	assert(ps);
	ps->a = (SLDateType*)malloc(sizeof(SLDateType) * 4);
	ps->size = 0;
	ps->capacity = InitCapa;
}

void CheckCapacity(SeqList* ps)
{
	if (ps->size == ps->capacity)
	{
		SLDateType* tmp = (SLDateType*)realloc(ps->a,sizeof(SLDateType) * ps->capacity * 2);
		if (tmp == NULL)
		{
			perror("realloc fail:");
			exit(-1);
		}
		ps->capacity *= 2;
		ps->a = tmp;
	}
}
void SeqListPushBack(SeqList* ps, SLDateType x)
{
	assert(ps);
	CheckCapacity(ps);
	ps->a[ps->size] = x;
	ps->size++;
}
void SeqListPopBack(SeqList* ps)
{
	assert(ps->size);
	ps->size--;
}
void SeqListPopFront(SeqList* ps)
{
	//assert(ps);
	//assert(ps->size);
	//int begin = 0;
	//int end = 1;
	//while (end < ps->size)
	//{
	//	ps->a[begin] = ps->a[end];
	//	begin++;
	//	end++;
	//}
	//ps->size--;
	SeqListErase(ps, 0);
}
void SeqListPushFront(SeqList* ps, SLDateType x)
{
	//assert(ps);
	//CheckCapacity(ps);
	//int end = ps->size;
	//int begin = ps->size - 1;
	//while (begin >= 0)
	//{
	//	ps->a[end] = ps->a[begin];
	//	begin--;
	//	end--;
	//}
	//ps->a[0] = x;
	//ps->size++;
	SeqListInsert(ps, 0, x);
}
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;
}
void SeqListInsert(SeqList* ps, int pos, SLDateType x)
{
	assert(ps);
	CheckCapacity(ps);
	int end = ps->size-1;
	while (end >= pos)
	{
		ps->a[end + 1] = ps->a[end];
		end--;
	}
	ps->a[pos] = x;
	ps->size++;
}
void SeqListErase(SeqList* ps, int pos)
{
	assert(ps);
	assert(ps->size);
	int begin = pos;
	while (begin < ps->size-1)
	{
		ps->a[begin] = ps->a[begin + 1];
		begin++;
	}
	ps->size--;
}
void SeqListPrint(SeqList* ps)
{
	for (int i = 0; i < ps->size; i++)
	{
		printf("%d ", ps->a[i]);
	}
	printf("\n");
}

void SeqListDestroy(SeqList* ps)
{
	assert(ps);
	free(ps->a);
	ps->size = ps->capacity = 0;
	ps->a = NULL;
}

SList.h

#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#define InitCapa 4;
typedef int SLDateType;
typedef struct SeqList
{
	SLDateType* a;
	int size;
	int capacity;
}SeqList;

// 对数据的管理:增删查改 
void SeqListInit(SeqList* ps);
void SeqListDestroy(SeqList* ps);

void SeqListPrint(SeqList* ps);
void SeqListPushBack(SeqList* ps, SLDateType x);
void SeqListPushFront(SeqList* ps, SLDateType x);
void SeqListPopFront(SeqList* ps);
void SeqListPopBack(SeqList* ps);

// 顺序表查找
int SeqListFind(SeqList* ps, SLDateType x);
// 顺序表在pos位置插入x
void SeqListInsert(SeqList* ps, int pos, SLDateType x);
// 顺序表删除pos位置的值
void SeqListErase(SeqList* ps, int pos);

注:这里的尾插、头插、尾删、头删都是插入删除函数的复用 

Test.c

 

#include"SList.h"
void TestSList()
{
	SeqList SL;
	SeqListInit(&SL);
	SeqListPushBack(&SL, 1);
	SeqListPushBack(&SL, 2);
	SeqListPushBack(&SL, 3);
	SeqListPushBack(&SL, 4);

	SeqListPrint(&SL);
	SeqListInsert(&SL, 1, 5);
	SeqListInsert(&SL, 1, 6);

	SeqListPrint(&SL);

	SeqListDestroy(&SL);
}
int main()
{
	TestSList();
	return 0;
}

好了!!!小编的分享到这里就结束了,想要继续了解数据结构的知识的,敬请期待博主的更新,有什么不足的地方请各位大佬多多指教!!!

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

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

相关文章

Dart的安装及环境变量配置

本文介绍dart的安装步骤及环境变量配置&#xff0c;以及如何在vscode中进行开发环境配置。一、dart的安装访问dart官网https://dart.cn/&#xff0c;点击网站右上角的获取DART SDK进行下载页面。如下图&#xff0c;选择下载SDK的zip压缩文件。根据自己的操作系统情况选择合适版…

DOM 文档对象模型

目录 一、简介 二、节点Node 三、document 1、简介 2、document对象的原型链 3、部分属性 四、元素节点 1、如何获取元素节点对象 通过document对象来获取已存在的元素节点 通过document对象来创建元素节点 2、原型链 3、通过元素节点对象获取其他节点的方法 五、…

如何备份网站到本地电脑(适用虚拟主机)

一、mysql数据库备份 登陆主机控制面板&#xff0c;点击左侧的数据库。 在数据库管理页面最下方有备份数据库的操作项目。点击【通过SQL文件导入导出】&#xff0c;进入到导出和导入的页面。 选择【导出/备份】这个选项导出。会在在wwwroot目录生成以时间命名的sql文件。 导出…

ADC模数转换器(基于STM32F407)

简介 Analog-to-digital converters&#xff08;模拟数字转换器&#xff09;&#xff0c;我的STM32F407中内置3个ADC&#xff0c;每个 ADC 有 12 位、10 位、8 位和 6 位可选&#xff0c;ADC 具有独立模式、双重模式和三重模式&#xff0c;对于不同 AD 转换要求几乎都有合适的…

list链表,结点

目录 1.链表 2.list构造函数 3.list的赋值和交换&#xff0c;&#xff0c;assign,swap 4.list大小的操作,size,empty,resize 5.list插入和删除&#xff0c;push_back,pop_back,push_front,pop_front,insert,clear,erase,remove 6.list容器数据存取,front,back 7.list反转…

数字孪生加持,水利水电工程或将实现全生命周期管理

水利水电工程在数字孪生技术的加持&#xff0c;使得建设和运营更加高效和智能化&#xff0c;将工程中各种元素、过程和系统数字化&#xff0c;并建立数字孪生模型&#xff0c;以实现工程建设和运营的智能化管理。数字孪生对水利水电实现对工程建设的全生命周期管理&#xff0c;…

Bean的生命周期和作用域

Bean的生命周期Bean的执行流程&#xff1a;Bean 执行流程&#xff1a;启动Spring 容器 -> 实例化 Bean&#xff08;分配内存空间&#xff0c;从无到有&#xff09;-> Bean 注册到 Spring 中&#xff08;存操作&#xff09; -> 将 Bean 装配到需要的类中&#xff08;取…

《计算机网络:自顶向下方法》实验2:常用网络命令的使用

使用Ping实用程序来测试计算机的网络连通性 登录到Windows中。单击开始,然后将鼠标指针移到程序上,再移到Windows系统,然后单击命令提示符。在命令提示窗口键入ping 127.0.0.1。问题1:发送了多少数据包?接受了多少数据包?丢失了多少数据包? 发送了4个数据包;接受了4个数…

JavaScript Web API实战:7个小众技巧让你的网站瞬间提升用户体验

随着技术的日新月异&#xff0c;为开发人员提供了令人难以置信的新工具和API。但据了解&#xff0c;在100 多个 API中&#xff0c;只有5%被开发人员积极使用。 让我们来看看一些有用的Web API&#xff0c;它们可以帮助您将网站推向月球&#xff01; 1、 截屏接口 Screen Capt…

Blockchain gold经测试完美兼容EVM虚拟机

尽管对于行业人士来说&#xff0c;有关寻找更快更便宜的基础层区块链的对话并不是什么新鲜事。 但随着 Defi Summer 持续一年有余的繁荣增长&#xff0c;更实际的需求——以太坊上高昂的 gas 费用使得开发者时间尤为昂贵。 可以看到的是&#xff0c;作为有着以太坊 CPU 之称的 …

Halcon 拟合直线

本文用 Halcon 的矩阵操作实现最小二乘拟合直线 *首先随机生成一组数据 Mx : [100:10:500] tuple_length(Mx, len) tuple_gen_const(len, 5, r) Ma : 2 Mb : 40 tuple_rand(len, noise) My : Ma * Mx Mb * noise gen_circle(ContCircle, My, Mx, r)接下来用矩阵进行最小二乘求…

一次Linux系统密码修改失败事件

一、事件描述 某业务系统采用移动云主机&#xff0c;某次因误操作导致移动云内嵌密码管理相关Pga进程导致页面无法修改密码&#xff0c;东移动云主机web终端登录也无法修改&#xff0c;密码错误次数最大已无法登录&#xff0c;无奈只能重启主机&#xff0c;修改密码&#xff1b…

如何保证线程的原子性

线程的原子性是指&#xff1a;一个或者一系列指令&#xff0c;它的操作是不可中断的&#xff0c;一旦开始是不允许被其他CPU或线程来中断。 我们来看下述代码&#xff1a;ThreadAtomicityDemo类中有个初始值为0的Integer类型的静态变量count&#xff0c;还有一个每次sleep一毫…

Vue3快速上手

Vue3快速上手 1.Vue3简介 2020年9月18日&#xff0c;Vue.js发布3.0版本&#xff0c;代号&#xff1a;One Piece&#xff08;海贼王&#xff09;耗时2年多、2600次提交、30个RFC、600次PR、99位贡献者github上的tags地址&#xff1a;https://github.com/vuejs/vue-next/release…

微信上制作投票链接在线制作投票链接如果制作投票链接

现在来说&#xff0c;公司、企业、学校更多的想借助短视频推广自己。通过微信投票小程序&#xff0c;网友们就可以通过手机拍视频上传视频参加活动&#xff0c;而短视频微信投票评选活动既可以给用户发挥的空间激发参与的热情&#xff0c;又可以让商家和企业实现推广的目的&…

华为OD机试 - 知识图谱新词挖掘 1(Python)【2023-Q1 新题】

华为OD机试300题大纲 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。 华为 OD 清单查看地址:blog.csdn.net/hihell/category_12199275.html 华为OD详细说明:https://dream.blog.csdn.net/article/details/128980730 知识图谱新词挖掘…

利用global mapper导出等高线 在sketch up制作三维模型

为了做一个地形模型&#xff0c;绞尽脑汁实验了所有能查到的教程&#xff0c;在免费的基础上总体尝试失败&#xff0c;一是需要花钱的插件例如bitmap to mesh&#xff0c;即便能下载到&#xff0c;也是无法安装使用。如果你能下到且安装上&#xff0c;别忘了分享给我。 二是有的…

如何终止一个线程

如何终止一个线程 是使用 thread.stop() 吗&#xff1f; public class ThreadDemo extends Thread{Overridepublic void run() {try {Thread.sleep(10000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("this is demo thread :"Thre…

学了两个月的Java,最后自己什么也不会,该怎么办?

学着学着你会发现每天的知识都在更新&#xff0c;也都在遗忘&#xff0c;可能就放弃了。但是只要自己肯练&#xff0c;肯敲代码&#xff0c;学过的知识是很容易就被捡起来的。等你学透了用不了一年也可以学好 Java的运行原理&#xff1a;Java是一门编译解释型语言&#xff0c;…

片内RAM读写测试实验

片内RAM读写测试实验 概念 RAM是FPGA中常用的基础模块&#xff0c;可广泛用于缓存数据的情况&#xff0c;同样它也是 ROM&#xff0c;FIFO 的基础。 官方已经提供了RAM的IP核进行例化即可。 读写时序&#xff08;具体还是要看官方资料&#xff09;&#xff1a; 过程 创…