【数据结构】——顺序表详解

news2024/12/26 21:55:06

大家好!当我们学习了动态内存管理后,就可以写一个管理数据的顺序表了!!!

顺序表的理解:

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

顺序表是在计算机内存中以数组的形式保存的线性表,线性表的顺序存储是指用一组地址连续的存储单元依次存储线性表中的各个元素、使得线性表中在逻辑结构上相邻的数据元素存储在相邻的物理存储单元中,即通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系,采用顺序存储结构的线性表通常称为顺序表。顺序表是将表中的结点依次存放在计算机内存中一组地址连续的存储单元中。

在这里插入图片描述

静态顺序表就是像数组一样的大小固定的,动态的可以在容量不够时进行扩容而达到能够存储大量数据的效果!!!

一、先创建一个结构体来表示顺序表

typedef int DATE;//重命名顺序表的数据类型
typedef struct ArrayList {
	DATE* date;
	size_t size;//顺序表长度
	size_t capacity;//顺序表容量
}AL;

二、顺序表的所有接口展示

void Init(AL* al);
void checkCapacity(AL* al);
void pushBack(AL* al, DATE info);
void pushFront(AL* al, DATE info);
void insertDate(AL* al,size_t pos, DATE info);
void printDate(AL* al);
void Erase(AL* al, size_t pos);
void PopBack(AL* al);
void PopFront(AL* al);
size_t FindDate(AL* al, DATE info);
void ExchangeDate(AL* al, size_t pos, DATE info);
void Deatory(AL* al);

三、每个接口功能介绍及实现原理

1、初始化函数的实现

void Init(AL* al)
{
	assert(al);
	al->size = 0;
	al->capacity = 4;//初始化容量为4
	DATE* tmp = (DATE*)malloc(sizeof(DATE) * al->capacity);
	if (tmp == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}
	al->date = tmp;
}

初始化顺序表的长度为0、容量为4!

2、检查容量函数的实现

void checkCapacity(AL* al)
{
	if (al->size == al->capacity)
	{
		DATE* tmp = (DATE*)realloc(al->date, sizeof(DATE) * al->capacity*2);
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(-1);
		}
		al->capacity *= 2;
		al->date = tmp;
		printf("扩容成功!\n");
	}
}

如果长度等于容量时就说明需要扩容了,就将容量扩到2倍大小

3、尾插函数的实现

void pushBack(AL* al, DATE info)
{
	assert(al);
	checkCapacity(al);
	al->date[al->size] = info;
	al->size++;
}

每次插入之前一定要检查容量
尾插就是在size尾位置写入需要插入的值,然后要对长度进行加一
在这里插入图片描述

4、头插函数的实现

void pushFront(AL* al, DATE info)
{
	assert(al);
	checkCapacity(al);
	if (al->size == 0)
	{
		al->date[0] = info;
		al->size++;
	}
	else
	{
		size_t end = al->size;
		while (end)
		{
			al->date[end] = al->date[end-1];
			end--;
		}
		al->date[0] = info;
		al->size++;
	}
}

头插一个数据,必须将后面的数据向后面移动,移动的过程中可能超过容量大小,所以在插入时都需要进行扩容判断

在这里插入图片描述

挪动方法如上

在这里插入图片描述

5、尾删函数

void PopBack(AL* al)
{
    assert(ps);
	assert(al->size > 0);
	al->size--;
}

将长度减一即可删除最后一个数据

6、头删函数

void PopFront(AL* al)
{
    assert(al->size > 0);
	int begin = 1;
	while (begin<al->size)
	{
		al->date[begin - 1] = al->date[begin];
		begin++;
     }
	al->size--;
}

挪动顺序方法如下:
在这里插入图片描述
定义一个变量begin=1,首先是要将数据2移动到数据1的位置,对应的操作是
al->date[begin - 1] = al->date[begin];然后begin++,依次将数据3挪到数据2的位置,数据4挪到数据3的位置。循环最后一次是将数据5挪到数据4的位置,也就是begin=4,al->size=5.则循环判断条件为beginsize,循环结束后将
al->size–;

在这里插入图片描述

7、任意位置删除数据函数的实现

void Erase(AL* al, size_t pos)
{
	assert(al);
	assert(pos >= 0 && pos <= al->size);
	if (al->size == 0)
	{
		printf("暂无数据!!\n");
		return;
	}
	size_t end = pos;
	while (end<al->size-1)
	{![在这里插入图片描述](https://img-blog.csdnimg.cn/a1a63c6776c142eeb77e15536b8f9a53.png#pic_center)

		al->date[end] = al->date[end + 1];
		end++;
	}
	al->size--;
}

删除一个数据,就要将这个位置之后的元素全部向前挪动一个位置
由于下标易班都有size_t表示,所以一个要把握好头删时出现无符号-1和0循环条件比较大小的情况

如果我们要删除数3,然后数据3后面的数据向前挪动,第一步就是将数据4移动到数据3的位置,定义一个变量end=pos=2;对应的操作为al->date[end] = al->date[end+1];,然后end++;将数据5移动到最开始数据4的地方。最后一次循环是将数据5移动到数据4的地方,也就是end最后等于3,al->size=5,则循环判断条件是end< al->size-1,循环结束将al->size–;

在这里插入图片描述

8、任意位置插入数据函数的实现

void insertDate(AL* al, size_t pos, DATE info)
{
	assert(al);
	assert(pos >= 0 && pos <= al->size);
	checkCapacity(al);
	int end = al->size;
	while (end > pos)
	{
		al->date[end] = al->date[end - 1];
		end--;
	}
	al->date[pos] = info;
	al->size++;
}

由于下标易班都有size_t表示,所以一个要把握好头插时出现无符号-1和0循环条件比较大小的情况

在这里插入图片描述

任意位置插入需要将插入位置及其以后的数据一次向后挪动一个位置!

9、头插头删和头删尾删函数的改进

我们写完任意插和任意删后,就可以对头插头删和头删尾删函数的改进,直接在他们的函数体里面调用任意插入和任意删除函数

void pushFront(AL* al, DATE info)
{
	assert(al);
	checkCapacity(al);
	if (al->size == 0)
	{
		al->date[0] = info;
		al->size++;
	}
	else
	{
		insertDate(al, 0, info);
	}
}
void pushBack(AL* al, DATE info)
{
	assert(al);
	checkCapacity(al);
	insertDate(al, al->size, info);
}
void PopBack(AL* al)
{
	assert(al);
	if (al->size == 0)
	{
		printf("暂无数据!!\n");
		return;
	}
	Erase(al, al->size);

}
void PopFront(AL* al)
{
	assert(al);
	if (al->size == 0)
	{
		printf("暂无数据!!\n");
		return;
	}
	Erase(al, 0);
}

头插就是调用insert函数在0位置插入
尾插就是调用insert函数在size位置插入
头删就是调用Erase函数删除0位置
尾删就是调用Erase函数删除size位置

10、查找数据函数实现

size_t FindDate(AL* al, DATE info)
{
	assert(al);
	for (size_t i = 0; i < al->size; i++)
	{
		if (al->date[i] == info)
			return i;
	}
	return -1;
}

依次便利顺序表,如果找到需要查找的数据,咋返回其下标,否则返回-1

11、修改数据

void ExchangeDate(AL* al, size_t pos, DATE info)
{
	assert(al);
	assert(pos >= 0 && pos <= al->size);
	al->date[pos] = info;
}

先查找要修改的数据是否存在,然后进行修改
他一般会和查找函数配合使用

在这里插入图片描述

12、销毁顺序表

由于顺序表开辟了堆区内存,所以我们在使用完顺序表后一定要对开辟的内存进行释放!

void Deatory(AL* al)
{
	assert(al);
	free(al->date);
	al->date=NULL;
	al->capacity = al->size = 0;
}

销毁一个顺序表,将顺序表的容量置为0,顺序表的有效数据个数置为0,将date指针所指向的动态开辟的内存空间释放了,由于释放了动态开辟的内存空间,所有p指向的空间未初始化,date成为野指针,为了防止野指针,将date置为空指针。

数据结构篇之——顺序表的分享到这里就结束了,感谢大家的浏览访问!!!

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

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

相关文章

self-attention、transformer、bert理解

参考李宏毅老师的视频 https://www.bilibili.com/video/BV1LP411b7zS?p2&spm_id_frompageDriver&vd_sourcec67a2725ac3ca01c38eb3916d221e708 一个输入&#xff0c;一个输出&#xff0c;未考虑输入之间的关系&#xff01;&#xff01;&#xff01; self-attention…

CSS详细基础(三)复合选择器

前两章介绍了CSS中的基础属性&#xff0c;以及一些基础的选择器&#xff0c;本贴开始介绍复合选择器的内容~ ​ 在 CSS 中&#xff0c;可以根据选择器的类型把选择器分为基础选择器和复合选择器&#xff0c;复合选择器是建立在基础选择器之上&#xff0c;对基本选择器进行组合形…

c语言练习70:反转两次的数字

反转两次的数字 题⽬描述&#xff1a; 反转 ⼀个整数意味着倒置它的所有位。 例如&#xff0c;反转 2021 得到 1202 。反转 12300 得到 321 &#xff0c;不保留前导零 。 给你⼀个整数 num &#xff0c;反转 num 得到 reversed1 &#xff0c;接着反转 reversed1 得到 revers…

使用KEIL自带的仿真器仿真遇到问题解决

*** error 65: access violation at 0x40021000 : no read permission 修改debug选项设置为下方内容。

Java之多线程的生产者消费者问题的详细解析

3.生产者消费者 3.1生产者和消费者模式概述【应用】 概述 生产者消费者模式是一个十分经典的多线程协作的模式&#xff0c;弄懂生产者消费者问题能够让我们对多线程编程的理解更加深刻。 所谓生产者消费者问题&#xff0c;实际上主要是包含了两类线程&#xff1a; 一类是生产者…

MJ 种的摄影提示词关键字

景别 Front view photo 正面照 Front view photo of a Boston Terrier with smileSide view photo 侧身照 Side view photo of a Boston Terrier with smileBack view photo 背影照 Back view photo of a Boston TerrierFull body 全身照 Full body photo of a Boston Ter…

electron之快速上手

前一篇文章已经介绍了如何创建一个electron项目&#xff0c;没有看过的小伙伴可以去实操一下。 接下来给大家介绍一下electron项目的架构是什么样的。 electron之快速上手 electron项目一般有两个进程&#xff1a;主进程和渲染进程。 主进程&#xff1a;整个项目的唯一入口&…

2.物联网射频识别,RFID通信原理,RFID读写器与标签无线交互方式、数据反馈方式,RFID调制与解调、编码方式,不同RFID标签与读写器

一。RFID无线识别的原理 1.RFID系统无线通信基本原理 如下图所示&#xff0c;左边是读写器&#xff08;刷卡器&#xff09;&#xff0c;右边是标签&#xff08;卡&#xff09;&#xff0c;中间通过无线通信方式。 标签&#xff1a;&#xff08;卡&#xff09; 读写器&#xff…

Sound/播放提示音, Haptics/触觉反馈, LocalNotification/本地通知 的使用

1. Sound 播放提示音 1.1 音频文件: tada.mp3&#xff0c; badum.mp3 1.2 文件位置截图: 1.3 实现 import AVKit/// 音频管理器 class SoundManager{// 单例对象 Singletonstatic let instance SoundManager()// 音频播放var player: AVAudioPlayer?enum SoundOption: Stri…

python二维码识别tesseract

window安装tesseract 下载路径&#xff1a; https://digi.bib.uni-mannheim.de/tesseract/ 选择 双击安装在D:\sore\teeseract-OCR后&#xff1a; 配置环境变量 配置环境变量Path&#xff1a;D:\sore\teeseract-OCR 配置语言包的环境变量TESSDATA_PREFIX&#xff1a; D:\s…

搭建自己的搜索引擎之五

一、前言 接上文 搭建自己的搜索引擎之四&#xff0c;下面继续介绍茴香豆茴字的另外两种写法。 二、Jest Jest是ES的Java Http Rest客户端&#xff0c;它主要是为了弥补以前ES自有API缺少HttpRest接口客户端的不足&#xff0c;但因为现在ES官方已经提供了RestClient ,该项目已…

Dynamic CRM开发 - 实体窗体(二)主窗体

主窗体是功能最丰富,使用场景最多的窗体。 主窗体界面如下图: 下面按照图中的序号,简述一下窗体的主要功能: 0、窗体的主要布局部分,即用户看到的内容,可以拖动右侧的字段到窗体中想要放置的地方。 默认有标题、常规(选项卡)、页脚三部分,常规处于高亮状态,即可以…

第十二章 类和对象

C面向对象的三大特性为&#xff1a;封装、继承、多态 C认为万事万物都皆为对象&#xff0c;对象上有其属性和行为 例如&#xff1a; 人可以作为对象&#xff0c;属性有姓名、年龄、身高、体重...&#xff0c;行为有走、跑、跳、吃饭、唱歌... 车也可以作为对象&#xff0c;…

docker安装apisix全教程包含windows和linux

docker安装apisix 一、Windows安装1、首先需要安装docker和docker compose&#xff0c;如果直接安装docker desktop&#xff0c;会自动安装docker compose。2、重新启动电脑3、访问 Docker 的下载&#xff08;[https://www.docker.com/products/docker-desktop](https://www.do…

RocketMQ 版本升级测试

一、背景 RocketMQ 版本升级&#xff0c;3.6.4升级到5.1.3。 二、机器资源 应用端&#xff1a; 10.XX.67.249【机器 1】 cd /home/product/logs/dolphin_task_test_logs/ vim info.logMQ 服务端&#xff1a; 旧MQ 10.XX.108.249 broker-001。用于测试升级NameServer【机器 2…

react库的基础学习

React介绍 React.js是前端三大新框架&#xff1a;Angular.js、React.js、Vue.js之一&#xff0c;这三大新框架的很多理念是相同的&#xff0c;但是也有各自的特点。 React起源于Facebook的内部项目&#xff0c;因为该公司对市场上所有 JavaScript MVC 框架&#xff0c;都不满…

【数据库】形式化关系查询语言(一):关系代数Relational Algebra

目录 一、关系代数Relational Algebra 1. 基本运算 a. 选择运算&#xff08;Select Operation&#xff09; b. 投影运算&#xff08;Project Operation&#xff09; 组合 c. 并运算&#xff08;Union Operation&#xff09; d. 集合差运算&#xff08;Set Difference Op…

【C++】vector基本接口介绍

vector接口目录&#xff1a; 一、vector的初步介绍 1.1vector和string的联系与不同 1.2 vector的源码参数 二、vector的四种构造&#xff08;缺省填充元素迭代器拷贝构造&#xff09; 三、vecto的扩容操作与机制 3.1resize&#xff08;老朋友了&#xff0c;不会就去看str…

Linux文件查找,别名,用户组综合练习

1.文件查看: 查看/etc/passwd文件的第5行 [rootserver ~]# head -5 /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologi…

epoll与socket缓冲区的恩恩怨怨

文章目录 前言一、什么是socket缓冲区二、阻塞与非阻塞内核缓冲区1、如果发送缓冲区满了会怎么样阻塞非阻塞 2、如果接受缓冲区为空会怎么样阻塞非阻塞 三、epoll与缓冲区的恩恩怨怨水平触发边缘触发非阻塞阻塞 结论 前言 本文深挖网络编程中的缓冲区&#xff0c;从什么是缓冲…