详解动态顺序表

𝙉𝙞𝙘𝙚!!👏🏻‧✧̣̥̇‧✦👏🏻‧✧̣̥̇‧✦ 👏🏻‧✧̣̥̇:Solitary-walk

      ⸝⋆   ━━━┓
     - 个性标签 - :来于“云”的“羽球人”。 Talk is cheap. Show me the code
┗━━━━━━━  ➴ ⷯ

本人座右铭 :   欲达高峰,必忍其痛;欲戴王冠,必承其重。

👑💎💎👑💎💎👑 
💎💎💎自💎💎💎
💎💎💎信💎💎💎
👑💎💎 💎💎👑    希望在看完我的此篇博客后可以对你有帮助哟

👑👑💎💎💎👑👑   此外,希望各位大佬们在看完后,可以互赞互关一下,看到必回
👑👑👑💎👑👑👑     

目录 

一:顺序表的介绍

  1:顺序表定义

    顺序表是线性表的一种,首先顺序表是是用一段物理地址连续的存储单元依次存储数据元素的线性结构,多数情况下借助数组来存储

二:动态顺序表和静态顺序表区别

  1:静态顺序表:

   静态就体现了静态顺序表的特征,数组的空间大小是固定的

//静态顺序表的结构体的构造
#define N 10
typedef int SLDataTYpe;//便于实现各种数据类型,一改全改

typedef struct SeqList
{
	SLDataTYpe a[N];
	int size;//记录数据有效的个数
}SL;
 2:动态顺序表

 动态体现了是一个不断变化的过程,可以频繁进行扩容

//动态顺序表
typedef int SLDataType;//便于实现各种数据类型,一改全改
typedef struct SeqList
{
	SLDataType* a;
	int size;//记录数据有效的个数
	int capacity;//空间空间的容量
}SL;
3:二者区别

静态顺序表:以定长数组的形式存储

动态顺序表:以动态开辟的数组进行存储

本质上二者没有优劣之分,只不过动态顺序表多了一个成员:空间容量

三:动态顺序表的接口实现

1. 初始化

为了避免不必要的麻烦,我们在初始化的时候直接就对数组进行动态开辟

void SLInit(SL* psl)
{
	assert(psl);
	psl->a = (SLDataType*)malloc(sizeof(SLDataType) * 4);//先为数组开4 个空间
	if (psl->a == NULL)  //空间检查
	{
		printf("perror malloc\n");
		return;
	}
    // 开辟成功
	psl->size = 0;
	psl->capacity = 4;
}
2.销毁
void SLDestroy(SL* psl)
{
	assert(psl);
	free(psl->a);
	psl->a = NULL;
	psl->capacity = 0;
	psl->size = 0;
}
3.尾插

分析:首先我们在尾插之前需要先进行空间容量检查

 

void SLPushBack(SL* psl, SLDataType x)
{
	assert(psl);
	//先判断空间是否足够
	CheckCapacity(psl);
	//之后直接尾插
	psl->a[psl->size] = x;
	psl->size++;
}
4.头插

分析:

1)空间容量的检查

2) 数据的挪动:从后往前挪动(避免数据覆盖)

3)下标边界值的确定

 

void SLPushFront(SL* psl, SLDataType x)
{
	assert(psl);
	//先判断空间是否足够
	CheckCapacity(psl);
	 挪动数据:从后往前挪动数据 注意边界的问题
	int end = psl->size - 1;
	while (end >= 0)
	{
		psl->a[end + 1] = psl->a[end];
		end--;
	}
	psl->a[0] = x;

	
	 psl->size++;
}
 5.尾删

先进行判空,其次直接size--

void SLPopBack(SL* psl)
{
	assert(psl);
	//判断是否为空   温柔  / 暴力判断
	 if (psl->size == 0)
	{
		printf("为空 \n");
		return;
	}
	
	psl->size--;

}
6.头删

先进行判空

其次挪动数据:从前往后挪动

下标边界的确定

 

void SLPopFront(SL* psl)
{
	assert(psl);
	assert(psl->size);//判空
	// 挪动数据:从前往后挪数据
	int start = 0;
	while (start < psl->size - 1)
	{
		psl->a[start] = psl->a[start + 1];
		start++;
	}
	//SLEarse(psl, 0);
	//注意:别忘了size--
	psl->size--;


}
7.任意位置的插入

1)空间容量检查

2)pos这个位置是否合法

3)数据挪动:和头插一样

 

void SLInsert(SL* psl, int pos, SLDataType x)
{
	assert(psl);
	// 先进行空间判断,以及位置的合法

	CheckCapacity(psl);
	
	assert(pos >= 0 && pos <= psl->size);  //这里可以取等,因为数组下标是连续的,可以在psl->size 这个位置插入
	
	int i = psl->size - 1;
	while (i >= pos)
	{
		psl->a[i + 1] = psl->a[i];
		i--;
	}
	psl->a[pos] = x;
	psl->size++;
	// 灵活运用: 头插,尾插就是此函数的一个特列

}
8.任意位置的删除

1)判空检查

2)pos是否合法

3)数据挪动:同头删一样

 

void SLEarse(SL* psl, int pos)
{
	assert(psl);
	//删除之前,先对pos这个位置判断是否合法,是否为空
	assert(pos >= 0 && pos < psl->size);  //注意这里没有必要取等  ,同时这个语句暗含着对判空的操作了
	int i = pos;
	//挪动数据:从前往后
	while (i < psl->size - 1)
	{
		psl->a[i] = psl->a[i + 1];
		i++;
	}
	//别忘了 size--

	psl->size--;

}

9.空间容量的检查

    当我们在进行头插,尾插,任意位置插入时都需要进行空间容量的检查,这里为了避免不必要的麻烦,写了一个函数

void CheckCapacity(SL* psl)
{
	assert(psl);
	if (psl->capacity == psl->size)
	{
		//realloc来扩容   void* realloc (void* ptr, size_t size);  第二个参数:扩容之后新的空间字节数,而不是要增加的字节数
		// 注意这样写是错误的,在free 的时候有问题  SLDataType* tmp = (SLDataType*)realloc(psl->a, (sizeof(SLDataType) *  4) * 2);//以原来2倍空间扩容
		SLDataType* tmp = (SLDataType*)realloc(psl->a, (sizeof(SLDataType) * psl->capacity) * 2);//以原来2倍空间扩容
		if (tmp == NULL)
		{
			printf("perror realloc\n");
			return;
		}
		// 扩容成功,进行更新
		psl->a = tmp;
		psl->capacity *= 2;

	}
}
10. 查找

1)前期的判断:位置是否合法?  顺序表是否为空表

2) 其实就是暴力求解,依次遍历顺序表即可,若是找到返回下标找不到返回-1

int  SLFind(SL* psl, SLDataType x)//查找
{
	assert(psl);
	assert(psl->size);//避免为空
	int i = 0;
	while (i < psl->size)
	{
		if (psl->a[i] == x)
		{
			return i;// 返回下标
		}
		i++;
	}
	return -1;//没有找到
}

11.任意位置修改 

1)依然是老生常谈,对位置以及顺序表进行判断

2)直接进行修改

void SLModify(SL* psl, int pos, SLDataType x) //指定位置修改
{
	assert(psl);
	assert(psl->size);//避免为空
	assert(pos >= 0 && pos <= psl->size - 1);
	psl->a[pos] = x;

}

完整代码:

SeqList.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"

void SLInit(SL* psl)
{
	assert(psl);
	psl->a = (SLDataType*)malloc(sizeof(SLDataType) * 4);//先为数组开4 个空间
	if (psl->a == NULL)
	{
		printf("perror malloc\n");
		return;
	}
	psl->size = 0;
	psl->capacity = 4;
}
void SLDestroy(SL* psl)
{
	assert(psl);
	free(psl->a);
	psl->a = NULL;
	psl->capacity = 0;
	psl->size = 0;
}
void CheckCapacity(SL* psl)
{
	assert(psl);
	if (psl->capacity == psl->size)
	{
		//realloc来扩容   void* realloc (void* ptr, size_t size);  第二个参数:扩容之后新的空间字节数,而不是要增加的字节数
		// 注意这样写是错误的,在free 的时候有问题  SLDataType* tmp = (SLDataType*)realloc(psl->a, (sizeof(SLDataType) *  4) * 2);//以原来2被空间扩容
		SLDataType* tmp = (SLDataType*)realloc(psl->a, (sizeof(SLDataType) * psl->capacity) * 2);//以原来2被空间扩容
		if (tmp == NULL)
		{
			printf("perror realloc\n");
			return;
		}
		// 扩容成功,进行更新
		psl->a = tmp;
		psl->capacity *= 2;

	}
}
void SLPushBack(SL* psl, SLDataType x)
{
	assert(psl);
	//先判断空间是否足够
	CheckCapacity(psl);
	//之后直接尾插
	/*psl->a[psl->size] = x;
	psl->size++;*/
	if (psl->size == 0)
	{
		psl->a[psl->size] = x;
		psl->size++;
	}
	else
	{
		SLInsert(psl, psl->size, x);
		//注意这里不用size++,因为SLInsert这个函数以及涉及到了
	}
}
void SLPushFront(SL* psl, SLDataType x)
{
	assert(psl);
	//先判断空间是否足够
	CheckCapacity(psl);
	 挪动数据:从后往前挪动数据 注意边界的问题
	//int end = psl->size - 1;
	//while (end >= 0)
	//{
	//	psl->a[end + 1] = psl->a[end];
	//	end--;
	//}
	//psl->a[0] = x;

	SLInsert(psl, 0, x);
	// psl->size++;
}
void SLPopBack(SL* psl)
{
	assert(psl);
	//判断是否为空   温柔  / 暴力判断
	 /*if (psl->size == 0)
	{
		printf("为空 \n");
		return;
	}*/
	assert(psl->size);
	psl->size--;

}
void SLPopFront(SL* psl)
{
	assert(psl);
	assert(psl->size);//判空
	// 挪动数据:从前往后挪数据
	int start = 0;
	while (start < psl->size - 1)
	{
		psl->a[start] = psl->a[start + 1];
		start++;
	}
	//SLEarse(psl, 0);
	//注意:别忘了size--
	psl->size--;


}
void SLPrint(SL* psl)
{
	assert(psl);
	int i = 0;
	while (i < psl->size)
	{
		printf("%d ", psl->a[i]);
		i++;
	}
	printf("\n");
}
void SLEarse(SL* psl, int pos)
{
	assert(psl);
	//删除之前,先对pos这个位置判断是否合法,是否为空
	assert(pos >= 0 && pos < psl->size);  //注意这里没有必要取等  ,同时这个语句暗含着对判空的操作了
	int i = pos;
	//挪动数据:从前往后
	while (i < psl->size - 1)
	{
		psl->a[i] = psl->a[i + 1];
		i++;
	}
	//别忘了 size--

	psl->size--;

}
void SLInsert(SL* psl, int pos, SLDataType x)
{
	assert(psl);
	// 先进行空间判断,以及位置的合法

	CheckCapacity(psl);
	
	assert(pos >= 0 && pos <= psl->size);  //这里可以取等,因为数组下标是连续的,可以在psl->size 这个位置插入
	
	int i = psl->size - 1;
	while (i >= pos)
	{
		psl->a[i + 1] = psl->a[i];
		i--;
	}
	psl->a[pos] = x;
	psl->size++;
	// 灵活运用: 头插,尾插就是此函数的一个特列

}
SeqList.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>

//顺序表分类:静态顺序表  动态顺序表
 
//静态的:空间开大了浪费,空间开小了不够用


/*静态顺序表的结构体的构造
#define N 10
typedef int SLDataTYpe;//便于实现各种数据类型,一改全改

typedef struct SeqList
{
	SLDataTYpe a[N];
	int size;//记录数据有效的个数
}SL;
*/

//动态顺序表
typedef int SLDataType;//便于实现各种数据类型,一改全改
typedef struct SeqList
{
	SLDataType* a;
	int size;//记录数据有效的个数
	int capacity;//空间空间的容量
}SL;
//接口函数的实现

void SLInit(SL* psl);
void SLDestroy(SL* psl);
void SLPushBack(SL* psl, SLDataType x);
void SLPushFront(SL* psl, SLDataType x);
void SLPopBack(SL* psl);
void SLPopFront(SL* psl);
void SLPrint(SL* psl);
void SLEarse(SL* psl,int pos);
void SLInsert(SL* psl, int pos, SLDataType x);

结束语:

以上就是我今日要为大家分享的,希望各位大佬随时指正,咱一波关注走起,看到必回

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ES6之Promise的链式调用

✨ 专栏介绍 在现代Web开发中&#xff0c;JavaScript已经成为了不可或缺的一部分。它不仅可以为网页增加交互性和动态性&#xff0c;还可以在后端开发中使用Node.js构建高效的服务器端应用程序。作为一种灵活且易学的脚本语言&#xff0c;JavaScript具有广泛的应用场景&#x…

老品牌新玩法?经济内循环下逆势开出100多家门店,他被央视青睐!

2023年12月26日&#xff0c;CCTV-2整点财经栏目以“抢抓复苏机遇&#xff0c;连锁品牌主打新活力”为主题&#xff0c;播报我国老品牌发展现状&#xff0c;新消费时代以来&#xff0c;消费者的选择多样化、分众化、小众化、个性化&#xff0c;给“老品牌”发展带来前所未有的挑…

Android Context在四大组件及Application中的表现

文章目录 Android Context在四大组件及Application中的表现Context是什么Context源码Activity流程分析Service流程分析BroadcastReceiver流程分析ContentProvider流程分析Application流程分析 Android Context在四大组件及Application中的表现 Context是什么 Context可以理解…

【代码随想录】刷题笔记Day43

前言 刚过完非常愉快的元旦假期&#xff0c;唔想反工啊啊啊&#xff0c;先刷刷题找回学习的状态吧 416. 分割等和子集 - 力扣&#xff08;LeetCode&#xff09; dp[target] target为目标&#xff0c;weight和value相同的01背包问题&#xff0c;用一维遍历dp[j]为容量为j的背…

为什么德国如此重视可持续性有机葡萄酒种植?

可持续性在德国葡萄栽培中越来越重要&#xff0c;它包括对葡萄酒行业的生态、经济和社会问题给予同等的考虑。在过去的几年里&#xff0c;世界范围内出现了许多不同的可持续葡萄酒生产项目。 以可持续发展为导向的酒庄是如何运营的&#xff1f;作为可持续发展整体方法的一部分&…

酒店预订订房小程序源码系统+多商户入驻 完全开源可二开 附带完整的搭建教程

在传统的酒店预订流程中&#xff0c;用户往往需要通过电话、第三方平台或者酒店官网进行预订&#xff0c;这些方式或多或少存在操作繁琐、信息不同步、服务不及时等问题。而小程序的出现&#xff0c;为酒店预订提供了一个全新的解决方案。它无需下载安装&#xff0c;即用即走&a…

租房数据分析可视化大屏+58同城 Django框架 大数据毕业设计(附源码)✅

毕业设计&#xff1a;2023-2024年计算机专业毕业设计选题汇总&#xff08;建议收藏&#xff09; 毕业设计&#xff1a;2023-2024年最新最全计算机专业毕设选题推荐汇总 &#x1f345;感兴趣的可以先收藏起来&#xff0c;点赞、关注不迷路&#xff0c;大家在毕设选题&#xff…

STM32CubeMX教程11 RTC 实时时钟 - 入侵检测和时间戳

目录 1、准备材料 2、实验目标 3、实验流程 3.0、前提知识 3.1、CubeMX相关配置 3.1.1、时钟树配置 3.1.2、外设参数配置 3.1.3、外设中断配置 3.2、生成代码 3.2.1、外设初始化调用流程 3.2.2、外设中断调用流程 3.2.3、添加其他必要代码 4、常用函数 5、烧录验…

php ext-sodium 拓展安装 linux+windows

php编译安装(linux)&#xff0c;可以参考&#xff1a;php编译安装 一、windows soduim源码包自带&#xff0c;直接修改php.ini&#xff0c;取消extensionsodium注释即可 二、linux 1.安装依赖 apt-get install libsodium-dev2.进入源码目录 这里写自己的源码目录 cd /us…

【CASS精品教程】CASS11坐标换带方法(单点计算、批量计算)

参考阅读:【Pix4d精品教程】Pix4d中央子午线细化设置(测区跨两个分带) 文章目录 一、坐标换带概述二、CASS坐标换带1. 单点转换2. 批量转换三、应用场景一、坐标换带概述 坐标换带是将一个投影带的平面直角坐标系换算成另外一个投影带的平面直角坐标系的过程。这一过程主要…

【进阶】【Python网络爬虫】【19.爬虫框架】scrapy分布式采集,增量式,Redis数据库安装(附大量案例代码)(建议收藏)

Python网络爬虫 Scrapy分布式1. 分布式概述什么是分布式&#xff1f;scrapy分布式scrapy和scrapy-redis的区别 2. Redis数据库及可视化工具安装Redis是什么安装Redis数据库windowsLinuxMac电脑请参考如下教程 安装可视化工具Redis基本数据库语法 3. 编码流程&#xff08;重点&a…

控制障碍函数(Control Barrier Function,CBF) 一、定义

近年来&#xff0c;非线性系统的安全分析与控制已成为控制领域中的热门研究方向&#xff0c;而障碍函数则是该方向的一种重要工具&#xff0c;基于障碍函数的安全分析与控制方法具有计算效率高、鲁棒性强等优点。 由于篇幅限制&#xff0c;我们将介绍分为几个部分进行。 一、…

论文阅读:基于MCMC的能量模型最大似然学习剖析

On the Anatomy of MCMC-Based Maximum Likelihood Learning of Energy-Based Models 相关代码&#xff1a;点击 本文只介绍关于MCMC训练的部分&#xff0c;由此可知&#xff0c;MCMC常常被用于训练EBM。最后一张图源于Implicit Generation and Modeling with Energy-Based Mod…

三、C语言中的分支与循环—循环嵌套 (9)

嵌套循环指的是一个循环内部包含另一个循环。外层循环每执行一次&#xff0c;内层循环会执行完其所有的迭代。嵌套循环经常被用来处理多维数据结构&#xff0c;如多维数组&#xff0c;或者在进行复杂的算法操作时&#xff0c;如排序和搜索算法。 嵌套循环可以是任意类型的循环…

WeNet语音识别+Qwen-72B-Chat Bot+Sambert-Hifigan语音合成

WeNet语音识别Qwen-72B-Chat Bot&#x1f47e;Sambert-Hifigan语音合成 简介 利用 WeNet 进行语音识别&#xff0c;使用户能够通过语音输入与系统进行交互。接着&#xff0c;Qwen-72B-Chat Bot作为聊天机器人接收用户的语音输入或文本输入&#xff0c;提供响应并与用户进行对话…

光伏、储能一体化监控及运维解决方案 安科瑞 许敏

前言&#xff1a;今年以来&#xff0c;在政策利好推动下光伏、风力发电、电化学储能及抽水蓄能等新能源行业发展迅速&#xff0c;装机容量均大幅度增长&#xff0c;新能源发电已经成为新型电力系统重要的组成部分&#xff0c;同时这也导致新型电力系统比传统的电力系统更为复杂…

VS Code 远程连接云机器训练配置

VS Code 远程连接云机器 Visual Studio Code&#xff08;以下简称 VS Code&#xff09;是一个由微软开发的代码编辑器。VS Code 支持代码补全、代码片段、代码重构、Git 版本控制等功能。 安装 VSCode步骤简单且网上有很多教程&#xff0c;这里不过多重复了。 VS Code 现已支…

python3 识别人像照片并纠正照片正反

实现效果&#xff1a; 本程序可以将下图第二张照片进行人脸识别&#xff0c;发现相片是否是正向&#xff0c;如果不是就进行相片转正形成下图第一张图。 代码 安装配置 模型下载 首先在我的这篇文件下载相应的人脸识别模型&#xff0c;一般 64标记点就够用&#xff0c;当然…

1月2日代码随想录二叉树的最小深度及层序遍历总结

个人认为这么一个层序遍历的章节放这么多基本一样的题目算是很没意思的了 填充每个节点的下一个右侧节点和二叉树最大深度和前面的代码几乎完全一样&#xff0c;所以我就跳过了 代码随想录 (programmercarl.com) 代码随想录 (programmercarl.com) 111.二叉树的最小深度 给…

android开发百度地图api实现定位图标随手机方向转动

该功能的实现依赖于手机中的传感器元件如陀螺仪、加速度计等&#xff0c;具体开发详见android的官方开发文档&#xff1a; 传感器概览 | Android 开发者 | Android Developershttps://developer.android.com/guide/topics/sensors/sensors_overview?hlzh-cn要自定义一个传…