C语言实现顺序表(图解增删查改+代码)

news2024/12/23 4:16:01

文章目录

  • 写在前面
  • 1. 顺序表的初始化和销毁
    • 1.1 顺序表的初始化(SLInit)
    • 1.2 顺序表的销毁(SLDestroy)
  • 2. 插入数据
    • 2.1 尾插数据(SLPushBack)
    • 2.2 头插数据(SLPushFront)
    • 2.3 指定位置插入数据(SLInsert)
  • 3. 删除数据
    • 3.1 尾删数据(SLPopBack)
    • 3.2 头删数据(SLPopFront)
    • 3.3 删除指定位置的数据(SLErase)
  • 4. 查找数据(SLFind)
  • 5. 修改指定位置的元素(SLModify)

写在前面

源码在这里–>顺序表源码
顺序表是一种基本的数据结构,它是一种线性表,其元素在内存中是连续存储的
在这里插入图片描述

本篇文章以c语言的形式实现了数据结构中的顺序表。顺序表分为静态和动态两个版本,静态版本是用数组来组织和存储数据的,这个版本的缺点是:空间给多了浪费,给少了不够用,下面是静态版本的定义:

#define N 50 //顺序表的容量
typedef int SlDataType;

struct SeqList
{
	SlDataType data[N];
	int size;//记录有效元素的个数
};

鉴于静态版本存在一定的缺陷,且实际用到的场景很少,因此这里就不实现静态的版本了。
动态版本的顺序表是通过malloc函数来动态申请一块连续的空间,刚开始空间给小一点,等空间不够了可以增容,因此动态版的顺序表能更加符合我们的需求,下面是动态版本的定义:

typedef struct Seqlist
{
	SlDataType* data;
	int size;//记录当前顺序表有效元素的个数
	int capacity;//记录当前顺序表的容量
}Seqlist;

该顺序表有三个成员变量,指针变量data是用来维护通过malloc函数动态申请的空间,size是用来记录当前顺序表中有效元素的个数,capacity是用来记录当前顺序表的容量。

1. 顺序表的初始化和销毁

1.1 顺序表的初始化(SLInit)

顺序表的初始化有多种方法,这里只是其中的一种,仅供参考。这里在初始化的时候给data分配了4个元素大小的空间,此时capacity就是4,size是指有效元素的个数,此时顺序表中没有元素,因此size等于0。代码如下:

void SLInit(Seqlist* psl)
{
	assert(psl);//检查参数的有效性
	SlDataType* tmp = malloc(sizeof(SlDataType)* 4);
	//判断是否成功申请空间
	if (tmp == NULL)
	{
		perror("SLInit()->malloc");
		return;
	}
	
	psl->data = tmp;
	psl->capacity = 4;
	psl->size = 0;
}

1.2 顺序表的销毁(SLDestroy)

由于data指向的空间是动态申请的,因此在程序结束之前,要将data指向的空间给释放,以避免造成内存泄漏,同时将data置为空指针,以避免野指针的问题。代码如下:

void SLDestroy(Seqlist* psl)
{
	assert(psl);//检查参数有效性
	
	free(psl->data);
	psl->data = NULL;
	psl->capacity = psl->size = 0;
}

顺序表是一种线性数据结构,它可以存储一组元素,并支持增加、删除、查找和修改元素的操作。下面详细介绍顺序表的增加(插入)、删除、查找和修改操作。

2. 插入数据

2.1 尾插数据(SLPushBack)

尾插数据的步骤如下:

  1. 判断顺序表是否已满,如果满了要进行扩容操作。
    由于后面的头插,和在指定位置插入数据都需要来判断顺序表是否已满,因此这里直接封装一个函数用来检查顺序表的容量。
    代码如下:
static void CheckCapacity(Seqlist* psl)
{
	assert(psl);//检查参数的有效性
	if (psl->size == psl->capacity)
	{
		//采取2倍扩容的方式
		SlDataType* tmp = realloc(psl->data, sizeof(SlDataType)* psl ->capacity * 2);
		if (tmp == NULL)
		{
			perror("CheckCapacity()->realloc");
			return;
		}
		psl->data = tmp;
		psl->capacity = psl->capacity * 2;
	}
}
  1. 在插入位置放置新元素。
    在这里插入图片描述

  2. 更新顺序表的大小。

尾插一个元素的代码如下:

void SLPushBack(Seqlist* psl, SlDataType x)
{
	assert(psl);//检查参数的有效性
	//判断顺序表是否已满
	CheckCapacity(psl);
	//尾插数据

	psl->data[psl->size] = x;
	psl->size++;

}

2.2 头插数据(SLPushFront)

头插数据的步骤如下:

  1. 判断顺序表是否已满,如果满了要进行扩容操作。
  2. 从插入位置开始,依次将后续元素向后移动一个位置,以腾出空间。
  3. 在插入位置放置新元素。
  4. 更新顺序表的大小。

例如,在 {1,2,3,4} 的中头插元素 0,实现过程如下:

  • 找到目标位置,如下图所示:
    在这里插入图片描述

  • 将元素 1 以及后续元素 2 、3、4 整体向后移动一个位置,如下图所示:
    在这里插入图片描述

  • 将新元素 0 放入腾出的位置,如下图所示:
    在这里插入图片描述

代码如下:

void SLPushFront(Seqlist* psl, SlDataType x)
{
	assert(psl);//检查参数有效性

	//判断顺序表是否已满
	CheckCapacity(psl);
	//从后往前移动数据
	int end = psl->size - 1;
	while (end >= 0)
	{
		psl->data[end + 1] = psl->data[end];
		end--;
	}
	
	psl->data[0] = x;//将数据插入目标位置
	psl->size++;//更新顺序表有效元素个数
}

2.3 指定位置插入数据(SLInsert)

指定位置插入数据的步骤如下:

  1. 检查插入位置的有效性,确保位置在合理范围内。
  2. 判断顺序表是否已满,如果满了要进行扩容操作。
  3. 从插入位置开始,依次将后续元素向后移动一个位置,以腾出空间。
  4. 在插入位置放置新元素。
  5. 更新顺序表的大小。

例如,在 {0,1,2,3,4,5,6,7} 的下标为 3 的位置上插入元素 8,实现过程如下:

  • 找到目标位置,如下图所示:
    在这里插入图片描述
  • 将元素 3 以及后续元素 4 、5、6、7 整体向后移动一个位置,如下图所示:
    在这里插入图片描述
  • 将新元素 8 放入腾出的位置,如下图所示:
    在这里插入图片描述

代码如下:

void SLInsert(Seqlist* psl, int pos, SlDataType x)
{
	assert(psl);//检查参数的有效性
	assert(pos >= 0 && pos <= psl->size);//检查插入位置的有效性

	//判断顺序表是否已满
	CheckCapacity(psl);

	//从后往前移动数据,直到挪动到pos位置
	int end = psl->size - 1;
	while (end >= pos)
	{
		psl->data[end + 1] = psl->data[end];
		end--;
	}
	
	psl->data[pos] = x;//将数据插入到指定位置
	psl->size++;//更新顺序表有效元素个数
}

3. 删除数据

3.1 尾删数据(SLPopBack)

尾删数据的步骤如下:

  1. 检查线性表是否为空,不为空在进行删除。
  2. size代表当前有效元素的个数,直接将size - 1,就访问不到最后一个元素了,即达到了尾删数据的目的了。
    代码如下:
void SLPopBack(Seqlist* psl)
{
	assert(psl);//检查参数有效性
	assert(psl->size > 0);//判断线性表是否为空

	psl->size--;//尾删数据
}

3.2 头删数据(SLPopFront)

头删数据的步骤如下:

  1. 检查线性表是否为空,不为空在进行删除。
  2. 从删除位置开始,依次将后续元素向前移动一个位置,以填补删除的位置。
  3. 更新顺序表的大小。
    例如,头删 {1,2,3,4} 中的 1,实现过程如下:

在这里插入图片描述

  • 后续元素整体前移一个位置,会直接将目标元素覆盖以实现删除元素的目的。
    在这里插入图片描述

代码如下:

void SLPopFront(Seqlist* psl)
{
	assert(psl);//检查参数有效性
	assert(psl->size > 0);//判断线性表是否为空

	//后续元素往前移动一个位置
	int start = 1;
	while (start < psl->size)
	{
		psl->data[start - 1] = psl->data[start];
		start++;
	}
	psl->size--;//更新顺序表有效元素个数
}

3.3 删除指定位置的数据(SLErase)

删除指定位置数据的步骤如下:

  1. 检查线性表是否为空,不为空在进行删除。
  2. 检查删除位置的有效性,确保位置在合理范围内。
  3. 从删除位置开始,依次将后续元素向前移动一个位置,以填补删除的位置。
  4. 更新顺序表的大小。

例如,在 {0,1,2,3,4,5,6,7} 中删除下标为3的元素,实现过程如下:

  • 找到目标位置,如下图所示:
    在这里插入图片描述

  • 从删除位置开始,依次将后续元素向前移动一个位置,以填补删除的位置。
    在这里插入图片描述

代码如下:

void SLErase(Seqlist* psl, int pos)
{
	assert(psl);//检查参数有效性
	assert(pos >= 0 && pos < psl->size);//检查位置的有效性(间接检查了判断线性表是否为空)
	
	//后续元素往前移动一个位置
	int start = pos + 1;
	while (start < psl->size)
	{
		psl->data[start - 1] = psl->data[start];
		start++;
	}
	psl->size--;//更新顺序表有效元素个数
}

4. 查找数据(SLFind)

查找元素的一般步骤:

  1. 检查查找条件的有效性,确保条件合理。
  2. 根据条件,从顺序表的头部开始逐个元素进行比较,直到找到满足条件的元素或者遍历整个顺序表。
  3. 找到了返回元素的所在位置的下标, 找不到返回 -1。

代码如下:

void SLFind(Seqlist* psl, SlDataType x)
{
	assert(psl);//检查参数有效性

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

5. 修改指定位置的元素(SLModify)

修改元素的一般步骤:

  1. 检查修改位置的有效性,确保位置在合理范围内。
  2. 更新指定位置的元素的值为新值。

代码如下:

void SLModify(Seqlist* psl, int pos, SlDataType x)
{
	assert(psl);//检查参数有效性
	assert(pos >= 0 && pos < psl->size);//检查位置的有效性

	psl->data[pos] = x;

}

顺序表的实现可能因编程语言而异,但上述操作的核心思想是相似的。

至此,本片文章就结束了,若本篇内容对您有所帮助,请三连点赞,关注,收藏支持下。
创作不易,白嫖不好,各位的支持和认可,就是我创作的最大动力,我们下篇文章见!
如果本篇博客有任何错误,请批评指教,不胜感激 !!!
在这里插入图片描述

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

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

相关文章

DDR3笔记 频率配置

可参考 基于FPGA的DDR3设计&#xff08;2&#xff09;DDR3各时钟频率及带宽分析 - 知乎 (zhihu.com) DDR3的时钟频率配置要看两个手册&#xff1a; 1.DDR3器件的手册。 2.开发板芯片的手册 器件 器件名称&#xff1a;MT41J128M16JT-125:K tCK 1.25ns&#xff0c;就可以算出…

冒泡排序应用过程中遇到的问题

冒泡排序思想&#xff1a;相邻的两个数据两两比较&#xff0c;然后按顺序排出 代码展示1&#xff1a; #include<stdio.h>void sort(int arr1[],int sz) {for (int i 0; i < sz-1; i){for (int j i1; j < sz; j){if (arr1[i] > arr1[j]) {int temp 0;temp a…

Wordpress - Xydown独立下载页面插件

Wordpress - Xydown独立下载页面插件&#xff1b; 1.使用ftp将demo.php和download.php上传到网站根目录&#xff08;两个文件中设计网站信息的代码可根据实际情况修改为自己的信息&#xff09; 使用ftp将demo.php和download.php上传到网站根目录&#xff08;两个文件中设计…

消息服务MNS之初见

消息服务MNS 说到消息服务MNS&#xff0c;那么消息服务MNS是什么呢&#xff1f;为什么会有消息服务MNS这款产品的产生呢&#xff1f; 什么是消息服务MNS 消息服务-阿里云消息服务MNS&#xff08;Message Service&#xff09;是一种高效、可靠、安全、便捷和可弹性扩展的分布…

GB28181学习(十)——视音频文件下载

要求 SIP服务器接收到媒体接收者发送的视音频文件下载请求后向媒体流发送者发送媒体文件下载命令&#xff0c;媒体流发送者采用RTP将视频流传输给媒体流接收者&#xff0c;媒体流接收者直接将视频流保存为媒体文件&#xff1b;媒体流接收者或SIP服务器可通过配置查询等方式获取…

算法模板之双链表图文详解

文章目录 &#x1f4cb;前言一. ⛳️使用数组模拟双链表讲解1.1 &#x1f514;为什么我们要使用数组去模拟双链表&#xff1f;1.2 &#x1f514;用数组模拟实现双链表1.2.1 &#x1f47b;整体框架说明1.2.2 &#x1f47b;双链表查找和修改1.2.3 &#x1f47b;双链表插入结点1.2…

云数据仓库实践:AWS Redshift在大数据储存分析上的落地经验分享

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;CSDN领军人物&#xff0c;全栈领域优质创作者✌&#xff0c;CSDN博客专家&#xff0c;阿里云社区专家博主&#xff0c;2023年6月CSDN上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师…

【RNA structures】RNA-seq 分析: RNA转录的重构和前沿测序技术

文章目录 RNA转录重建1 先简单介绍一下测序相关技术2 Map to Genome Methods2.1 Step1 Mapping reads to the genome2.2 Step2 Deal with spliced reads2.3 Step 3 Resolve individual transcripts and their expression levels 3 Align-de-novo approaches3.1 Step 1: Generat…

C语言------接续符和转义符

接续符和转义符--------- \ C语言中的\符号可以表示接续符和转义符。 C语言中的接续符( \ )放在一行代码的结尾&#xff0c;可以将下一行的内容提到这一行来。 \符号还有另一个作用 — 转义符。 C语言中的转义符()主要用于表示无回显字符&#xff0c;也可用于表示常规字符。 …

原型链继承

方式一&#xff1a;原型链继承 1.套路&#xff1a; &#xff08;1&#xff09;定义父类型构造函数 &#xff08;2&#xff09;给父类型的原型添加方法 &#xff08;3&#xff09;定义子类型的构造函数 &#xff08;4&#xff09;创建父类型的对象赋值给子类型的原型 &…

基于SpringBoot的家具商城管理系统

基于SpringBoot的家具商城管理系统的设计与实现【文末源码】 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBootMyBatisVue工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 主页 家具详情 通知公告 登录界面 管理员界面 摘要 一段关于基于…

Windows下安装PyTorch(GPU版本)

PyTorch环境配置及安装 初步机器学习&#xff0c;这里记录下一些学习经过&#xff0c;之后以便于自己查看&#xff0c;同时欢迎各位大佬点评&#xff0c;本节是机器计算的一个包的安装和简单验证。 1.流程 确定自己的硬件信息-确定电脑有英伟达&#xff08;NVIDIA&#xff…

给视频批量添加背景图,轻松简单的操作方法

当我们需要给多个视频添加相同的背景图片时&#xff0c;一个一个地添加未免太过于繁琐和低效。幸运的是&#xff0c;我们可以使用固乔剪辑助手这款软件来实现批量添加背景图片的操作。下面就是详细的步骤指南。 首先&#xff0c;我们需要在浏览器搜索“固乔科技”&#xff0c;然…

面试官心声:个个都说会自动化,结果面试一问细节全露馅了

今年我们部门计划招聘几名自动化测试工程师&#xff0c;为此我进行了面试和培训&#xff0c;发现了一个让我感到担忧的趋势&#xff0c;许多候选人可以轻松地回答有关脚本编写、元素定位、框架API等问题。然而一问到实际项目&#xff0c;比如“如何从0开始搭建自动化体系”、“…

【C语言】用函数实现模块化程序设计

前言&#xff1a;如果把所有的程序代码都写在一个主函数(main函数)中&#xff0c;就会使主函数变得庞杂、头绪不清&#xff0c;使阅读和维护程序变得困难。此外&#xff0c;有时程序中要多次实现某一功能&#xff0c;如果重新编写实现此功能就会使得程序冗长、不精炼。 &#x…

day02_numpy_demo

Numpy Numpy的优势ndarray属性基本操作 ndarray.func() numpy.func()ndarray的运算&#xff1a;逻辑运算、统计运算、数组间运算合并、分割、IO操作、数据处理,不过这个一般使用的是pandas Numpy的优势 Numpy numerical数值化 python 数值计算的python库&#xff0c;用于快…

Node.js--》简易资金管理系统后台项目实战(后端)

今天开始使用 node vue3 ts搭建一个简易资金管理系统的前后端分离项目&#xff0c;因为前后端分离所以会分两个专栏分别讲解前端与后端的实现&#xff0c;后端项目文章讲解可参考&#xff1a;前端链接&#xff0c;我会在前后端的两类专栏的最后一篇文章中会将项目代码开源到我…

arduino 记录

​ 知识整理 Arduion U8G2简要说明 u8g2显示分为全页显示与分页显示和U8X8的无ram显示 全页显示需要单片机提供1024字节的ram&#xff0c;分页显示分为需要256字节和125字节的ram U8X8不需要ram,但不可画图&#xff0c;只能显示文字 全页使用 clearbuff senddbuff 分页…

javaweb中的转发与重定向

2023.10.22 在一个web应用中应该如何完成资源的跳转&#xff1f; 转发重定向 转发和重定向有什么区别&#xff1f; 转发是由服务器端进行的页面跳转&#xff0c;而重定向是由浏览器端进行的页面跳转。 ①代码上的区别&#xff1a; 转发&#xff1a; // 获取请求转发器对象…

Sublime Text forMac/Windows:高效代码编辑器的终极指南

你是否曾为寻找一款高效、强大且用户友好的代码编辑器而感到困扰&#xff1f;现在&#xff0c;让我们一起探索Sublime Text的魅力。Sublime Text是一款流行的代码编辑器&#xff0c;以其强大的功能和简洁的设计赢得了开发者的喜爱。本文将带你了解Sublime Text的各项特性&#…