你真的会数据结构吗:顺序表

news2024/11/16 11:40:11

❀❀❀ 文章由@不准备秃的大伟原创 ❀❀❀

♪♪♪ 若有转载,请联系博主哦~ ♪♪♪

❤❤❤ 致力学好编程的宝藏博主,代码兴国!❤❤❤

         又和大家见面啦!在大家看到这个标题的时候其实就已经发现了:我们的C语言的基础知识大部分已经学完了呢~真厉害,给自己鼓个掌吧,啪叽啪叽~ 现在开始我们要进击数据结构了!是不是很激动呢?诶,先憋激动,在开始前我们先了解一下数据结构是什么吧!

          我们在生活中无论什么事几乎都少不了逻辑吧,比如是先吃饭还是先睡觉,是先给大伟的文章点赞还是先收藏一下(^▽^ ),再更具体一点,我们的手机软件,比如电话啊,QQ啊,微信啊,里面不是都有联系人吗,我们可以在手机上对联系人进行一系列操作:修改信息,增加联系人,删除联系人,查找联系人等等等等.......这些啊其实都是我们的数据结构。

        而概念性来说:

数据结构(Data Structure)是计算机存储、组织数据的方式,指相互之间存在一种或多种特定关系的 数据元素的集合。

        我爱说实话,数据结构是非常非常重要的!无论是我们刷题目,以后面试,甚至是以后工作了之后,数据结构都是会一直会陪伴我们的,而大伟我也会一直陪着大家的(✿◡‿◡)

        那我们要如何学好数据结构呢?简单,像这样就行:b97051f1ef1e4e8191f898504d3e17a6.png

        哈哈,开个玩笑,别当真啦!其实呢,重要的是需要画图思考,虽然这两点在哪里都很重要就是了~

        好的,废话不多说,那我们就开始今天的内容:顺序表吧!

                顺序表

        在动手写码顺序表前,我们需要先来分清楚两个概念:线性表和顺序表:

        那有铁汁好奇了,线性表是啥呢?

线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是⼀种在实际中⼴泛使 ⽤的数据结构,常⻅的线性表:顺序表链表队列字符串... 线性表在逻辑上是线性结构,也就说是连续的⼀条直线。但是在物理结构上并不⼀定是连续的, 线性表在物理上存储时,通常以数组和链式结构的形式存储。

        简单来说,线性表就是在逻辑上是一条线,而实际的物理结构不一定是一条线。而我们今天要写的顺序表就是一个线性表,且他的底层就是数组,是对数组进行了封装。

         谈到顺序表,我们就有两个选择:静态顺序表和动态顺序表。那么这两个有什么区别呢?我们通过代码来看一看:

静态:

typedef int SQLDataType;//重命名int
#define N 10
typedef struct SeqList {
	SQLDataType arr[N];
	int size;//顺序表的实际大小
}SeqList;//重命名结构体

        动态: 

typedef int SQLDataType;
typedef struct SeqList {
	SQLDataType *arr;
	int size;
	int capacity;
}SeqList;

        不知道大家还记不记得typedef了,没错,typedef将int 和 struct SeqList进行重命名,而我为什么要这么做呢?大家可以思考一下,其实也就是typedef的好处是什么:


        鸡屁踢老弟给出了以下几种答案:

  1. 代码可读性:为复杂的数据类型创建简洁的别名,提高代码的可读性
  2. 平台无关性:在一些情况下,数据类型的大小可能因编译器和操作系统的不同而有所变化,可以为不同平台定义相同的别名,提高代码的可移植性
  3. 简化复杂声明:声明一个函数指针类型可能会变得更加清晰
  4. 抽象底层实现:使你的代码更容易维护。通过定义数据类型的别名,你可以在不影响代码其他部分的情况下更改底层实现
  5. 提高代码的一致性:确保在整个代码库中一致地使用相同的数据类型,减少错误和混淆的可能性

        umm,说的很好,不亏是鸡踢屁牢弟,简单来说,就是便于书写和阅读,可以以便后面根据需求修改类型,如可以直接把一大片的int改为char,且便于维护。

        那我们再回到上面的两段代码,我们会发现,静态顺序表是通过N来确定整个顺序表的最大容积;而动态顺序表是定义了个指针,后期可以通过动态内存开辟来实现最大容积的变化,还有size来确定有效数据,capacity来确定最大数据。

        这样一对比铁汁们就会发现哪个方法会更好呢?  当然是动态更好了,对吧?

        好的,我们确定了我们的顺序表是由动态开辟的,那我们可以玩(对动态表做什么)什么呢?

        来,让我们联想到微信联系人,我们可以加小姐姐的wx(增),可以删掉不喜欢的基佬(删),查找自己的好舍友(查),修改新加的朋友的备注(改)。诶~对了,我们实现的就是增删查改。

        代码实现:

    和之前的扫雷一样,我们还是开了三个文件,分别为:Sql.c  Sql.h test.c(当然了,名字是自己取的,我这么取的原因是顺序表英文为Sequence List,这样子更容易理解)

        这里插一嘴啊~ 其实关于C语言的命名有一定的规则,如:大驼峰命名法等,有兴趣的铁汁们下来自己查啊~(ง •_•)ง

        首先我们先定义个结构体(Sql.h),当然了别忘了重命名:

#include<stdio.h>
#include<assert.h>
#include<malloc.h>
typedef int SQLDataType;
typedef struct SeqList {
	SQLDataType *arr;//数组保存数据
	int size;//有效数据体积
	int capacity;//最大体积
}SeqList;

        然后是我们的声明增删查改(Sql.h),但是在此之外我们还多了一些操作:

//顺序表初始化
void SeqListInit(SeqList* ps);
//检查空间,如果满了,进行增容
void CheckCapacity(SeqList* ps);
// 顺序表尾插
void SeqListPushBack(SeqList* ps, SQLDataType x);
// 顺序表尾删
void SeqListPopBack(SeqList* ps);
// 顺序表头插
void SeqListPushFront(SeqList* ps, SQLDataType x);
// 顺序表头删
void SeqListPopFront(SeqList* ps);
// 顺序表查找
int SeqListFind(SeqList* ps, SQLDataType x);
// 顺序表在pos位置插入x
void SeqListInsert(SeqList* ps, size_t pos, SQLDataType x);
// 顺序表删除pos位置的值
void SeqListErase(SeqList* ps, size_t pos);
// 顺序表销毁
void SeqListDestory(SeqList* ps);
// 顺序表打印
void SeqListPrint(SeqList* ps);

         因为一开始只是一张白纸,所以初始化一下没问题吧,既然都初始化了,没有空间怎么可以呢,再来个检查空间也没问题吧,增的话,在头部增加,在尾部增加,在特定位置增加没话说吧,删的话,删头,删为,删特定位置也没话说吧,查找,修改,再打印个链表以便观察,最后再销毁,有始有终,完美!

        好,开码!

        Sql.c

初始化:

void SeqListInit(SeqList* ps)
{
	ps->arr = NULL;//一开始啥都没有
	ps->capacity = ps->size = 0;//一开始啥都没有
}

  检查空间:

void CheckCapacity(SeqList* ps)
{
	if (ps->capacity == ps->size)//若有效容积等于最大容积了
	{
		int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;//若顺序表为空,先给四个空间,若不为空,两倍空间
		SQLDataType* tmp = (SQLDataType*)realloc(ps->arr, newCapacity * sizeof(SQLDataType));//扩容(开辟空间)
		if (tmp == NULL)//若开辟失败
		{
			perror("malloc failed!");
			return;
		}
		ps->arr = tmp;//修改空间
		ps->capacity = newCapacity;//修改最大体积
	}
}

  头插:

void SeqListPushFront(SeqList* ps, SQLDataType x)
{
	assert(ps);//断言,若ps不为空
	CheckCapacity(ps);//检查体积够不够了
	for (int i = ps->capacity; i > 0; i--)
	{
		ps->arr[i] = ps->arr[i - 1];//从最后一个元素的后一个元素往前覆盖,直到第一个元素
	}
	ps->arr[0] = x;//修改首元素的值
	ps->size++;//修改size的值
}

尾插:

void SeqListPushBack(SeqList* ps, SQLDataType x)
{
	assert(ps);
	CheckCapacity(ps);
	ps->arr[ps->size] = x;//直接在最后一个有效元素有一个位置插入
	ps->size++;//修改size大小
}

特定位置插入:

void SeqListInsert(SeqList* ps, size_t pos, SQLDataType x)
{
	assert(ps);
	assert(pos >= 0 && pos < ps->size);//确保pos(下标)位置有效
	CheckCapacity(ps);
	for (int i = ps->size; i > pos ; i--)
	{
		ps->arr[i] = ps->arr[i - 1];//从最后一个元素后面一个元素开始往前覆盖,直到下标为pos位置
	}
	ps->arr[pos] = x;//修改pos位置的值
	ps->size++;//修改size
}

头删:

void SeqListPopFront(SeqList* ps)
{
	assert(ps);
	int i;
	for ( i = 0; i < ps->size-1; i++)
	{
		ps->arr[i] = ps->arr[i + 1];//从前往后一次覆盖
	}
	ps->arr[i] = -1;//将最后一个元素修改为-1(这句代码其实可以不需要,放上去也有问题,大家思考一下为什么)
	ps->size--;//修改size
}

尾删:

void SeqListPopBack(SeqList* ps)
{
	assert(ps);
	ps->arr[ps->size - 1] = -1;//(同样的,这句代码可以有问题并可以不要)
	ps->size--;//修改size
}

特定位置删除:

void SeqListErase(SeqList* ps, size_t pos)
{
	assert(ps);
	assert(pos >= 0 && pos < ps->size);
	int i;
	for ( i = pos; i < ps->size-1; i++)
	{
		ps->arr[i] = ps->arr[i + 1];//从pos位置往后,依次覆盖
	}
	ps->arr[i] = -1;//(多余,错误)
	ps->size--;//修改size
}

查找:

int SeqListFind(SeqList* ps, SQLDataType x)
{
	assert(ps);
	for (int i = 0; i < ps->size; i++)
	{
		if (ps->arr[i] == x)
			return i;//遍历,如果找到了,返回下标
	}
	return -1;//如果找不到,返回个无效的下标
}

打印:

void SeqListPrint(SeqList* ps)
{
	for (int i = 0; i < ps->size; i++)
	{
		printf("%d  ", ps->arr[i]);//遍历一下,没啥好说的
	}
	printf("\n");
}
void SeqListDestory(SeqList* ps)
{
	assert(ps);
	free(ps->arr);//释放空间
	ps->arr = 0;
	ps->capacity = ps->size = 0;
}

        OK,OK,上面就是我们的的动态单链表的代码实现,现在考验大家的大家的记性和认真程度了:还记得博主括号内的问题吗?不记得?呵,赶紧回去看!o( ̄ε ̄*)  。昂,看到了吧?简单来说问题就是 ps->arr[i] = -1 为什么有问题,为什么可以不需要?

        emm,怎么说捏,我们在插入数据的时候范围是不限的吧,所以我们也可以插入一个-1进去吧?那如果我们现在把这个位置设置为-1,那可不可以算是插入了个-1呢?’(°ー°〃),所以,我们完全可以直接不给他赋值,任由他自由,反正我们后面也不要关心他的值对吧~?

        所以啊,我们的代码实现可以多种多样,逻辑上和实用性上都要考虑。那我们顺序表的代码写完了,不得来玩一玩?┗|*`0′*|┛

test.c

#include"Sql.h"
int main()
{
	SeqList ps;
	SeqListInit(&ps);

 	 SeqListPushBack(&ps, 1);
	 SeqListPushBack(&ps, 2);
	 SeqListPushBack(&ps, 3);
	 SeqListPushBack(&ps, 4);
	 SeqListPrint(&ps);//1 2 3 4

	 SeqListPushFront(&ps, 7);
	 SeqListPushFront(&ps, 6);
	 SeqListPushFront(&ps, 5);
	 SeqListPrint(&ps);//5 6 7 1 2 3 4 

	  SeqListPopBack(&ps);
	  SeqListPopBack(&ps);
	  SeqListPrint(&ps);//5 6 7 1 2

	  SeqListPopFront(& ps);
	  SeqListPopFront(&ps);
	  SeqListPrint(&ps);// 7 1 2

	  if (SeqListFind(&ps, 1))
		  printf("1的下标为%d\n", SeqListFind(&ps, 1));
	  else
			  printf("找不到!");//1的下标为1

	 SeqListInsert(&ps, 1, 5);
	 SeqListPrint(&ps);// 7 5 1 2

	 SeqListErase(&ps, 2);
	 SeqListPrint(&ps);// 7 5 2

	 SeqListDestory(&ps);
	 SeqListPrint(&ps);//NULL

	return 0;
}

        让我们看看运行框内打印的是不是和我们想要的一样呢?5081831b6f96458e9178843f0761a0cd.png

        通过对比,我们发现实际输出的结果和我们想要的效果完全一样啊,而且代码返回为0,这也就说明了我们代码写的没有问题。

        害,累鼠博主了,看到这里还不给大伟来个一键三连?o(^▽^)o。今天的顺序表也就到此为止了啊,下次带大家来看看顺序表的实际应用~期待着吧!

        I have no secret of success but hard work. 除辛勤工作之外,我别无成功的秘诀。

        本篇博客也就到此为止了,送大家一碗鸡汤,勉励自己以及这世界上所有追逐梦想的赤子趁年华尚好努力提升自己,莫欺少年穷!          fb28922170e04390ad2f6e3e4a3856be.jpeg

 

 

 

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

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

相关文章

Shell脚本的if条件语句

目录 1.单分支结构 2.双分支结构 3.多分支结构 4.例题 1.单分支结构 实际上使用“&&”和“||”逻辑测试已经可以完成简单的判断并执行相应的操作&#xff0c;但是当需要选择执行的命令语句较多时&#xff0c;这种方式将使执行代码显得很复杂&#xff0c;不好理解。…

gdzwfw某省公共资源交易平台逆向学习

声明&#xff1a;本文中网站仅为学习技术使用&#xff0c;请勿暴力爬取数据。 学习地址&#xff1a;aHR0cHM6Ly95Z3AuZ2R6d2Z3Lmdvdi5jbi8jLzQ0L2p5Z2c 此网站采用请求头反爬&#xff0c;难点是请求头中几个参数是如何生成的&#xff08;别问为什么知道是请求头&#xff0c;一…

学单片机前先学什么?

学单片机前先学什么&#xff1f; 在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「单片机的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff…

77_组合

描述 给定两个整数 n 和 k&#xff0c;返回范围[1, n]中所有可能的 k 个数的组合。 你可以按任何顺序返回答案。 思路 数组问题 从横向上来看往往有 遍历、滑动窗口、动态规划等思路。但是&#xff0c;其实在遍历这种横向取数过程中&#xff0c;可以根据条件的判断形成树形操作…

一键拥有你的GPT4

这几天我一直在帮朋友升级ChatGPT&#xff0c;现在已经可以闭眼操作了哈哈&#x1f61d;。我原本以为大家都已经用上GPT4&#xff0c;享受着它带来的巨大帮助时&#xff0c;但结果还挺让我吃惊的&#xff0c;还是有很多人仍苦于如何进行升级。所以就想着写篇教程来教会大家如何…

山西电力市场日前价格预测【2024-01-24】

日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2024-01-24&#xff09;山西电力市场全天平均日前电价为320.98元/MWh。其中&#xff0c;最高日前电价为480.67元/MWh&#xff0c;预计出现在18:30。最低日前电价为0.00元/MWh&#xff0c;预计出…

RabbitMQ交换机与队列

交换机 RabbitMQ 消息传递模型的核心思想是: 生产者生产的消息从不会直接发送到队列。实际上&#xff0c;通常生产者甚至都不知道这些消息传递传递到了哪些队列中。 相反&#xff0c; 生产者只能将消息发送到交换机(exchange)&#xff0c;交换机工作的内容非常简单&#xff0c…

3.chrony服务器

目录 1. 简介 1.1. 重要性 1.2. Linux的两个时钟 1.3. 设置日期时间 1.3.1. timedatectl命令设置 1.3.2. date命令设置 1.4. NTP 1.5. Chrony介绍 2. 安装与配置 2.1. 安装&#xff1a; 2.2. Chrony配置文件分析 2.3. 同步时间服务器 2.3.1. 授时中心 2.3.2. 实验…

基于机会网络编码(COPE)的卫星网络路由算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 4.1机会网络编码&#xff08;COPE&#xff09;概述 4.2COPE算法原理 4.2.1 编码机会预测 4.2.2 编码决策 4.2.3 数据包编码 4.2.4 数据包传输 4.2.5 数据包解码 5.完整程序 1.程序功能…

notepad++ v8.5.3 安装插件,安装失败怎么处理?下载进度为0怎么处理?

notepad v8.5.3 安装插件&#xff0c;安装失败&#xff1f;下载进度为0&#xff0c;怎么处理&#xff1f; 安装 进度 进度条没有进度 &#xff0c;然后就退出了&#xff0c;自动打开程序&#xff0c;不知道什么问题&#xff0c;插件管理下面也没有插件显示 找到问题了&#x…

【python文件】生成的csv文件没两行数据之间有一个空行

问题描述 用python代码将数据写入csv文件&#xff0c;但生成的csv文件没两行数据之间有一个空行&#xff0c;如下图所示&#xff1a; 解决办法 在open函数中添加newline&#xff0c;如以下代码所示&#xff0c;即可解决这一问题。 with open(r"C:\Users\xxx\Desktop\DR…

PPP协议原理介绍+报文分析+配置指导-RFC1661

个人认为&#xff0c;理解报文就理解了协议。通过报文中的字段可以理解协议在交互过程中相关传递的信息&#xff0c;更加便于理解协议。 因此本文将在PPP协议报文的基础上进行介绍。 关于PPP协议基本原理&#xff0c;可参考RFC1661-The Point-to-Point Protocol (PPP)。 关于P…

建议CSDN不要这样吃人xue馒头

程序员裁员潮&#xff1a;技术变革下的职业危机 2023年以来&#xff0c;谷歌、阿里巴巴各个科技公司都在裁员&#xff0c;程序员的日子也不好过。 讨论在技术变革下&#xff0c;裁员对于程序员的影响到底有多大&#xff0c;是非常有意义的话题&#xff0c;但是为什么要用“一…

QT下载、安装详细教程[Qt5.15及Qt6在线安装,附带下载链接]

QT5.15及QT6的下载和安装 1.下载1.1官网下载1.2国内镜像网站下载 2.安装3.软件启动及测试程序运行3.1Qt Creator&#xff08;Community&#xff09; 1.下载 QT自Qt5.15版本后不在支持离线安装包下载(非商业版本&#xff0c;开源)&#xff0c;故Qt5.15及Qt6需要使用在线安装程序…

AppDesigner语音滤波器设计——IIR、IIR、维纳滤波、卡尔曼滤波、自适应滤波

1.AppDesigner简介 App Designer是一个可视化的集成开发环境&#xff0c;提供了仪表、旋钮等组件&#xff0c;采用面向对象的设计方法。利用App Designer可以快速开发出应用程序。App Designer提供了各种UI组件&#xff0c;如按钮、文本框、图表等&#xff0c;以及用于布局和设…

数据链路层——笔记·续

使用集线器的星形拓扑 传统以太网传输媒体&#xff1a;粗同轴电缆 -> 细同轴电缆 -> 双绞线。 采用双绞线的以太网采用星形拓扑。 在星形的中心则增加了一种可靠性非常高的设备&#xff0c;叫做集线器 (hub)。 传统以太网使用同轴电缆&#xff0c;采用总线形拓扑结构&am…

C++ Qt day1

提示并输入一个字符串&#xff0c;统计该字符中大写、小写字母个数、数字个数、空格个数以及其他字符个数(要求使用C风格字符串完成) #include <iostream> #include <string.h> #include <array> using namespace std;int main() {string str;cout <<…

100T数据存进服务器分几步?

大家好&#xff0c;我是豆小匠。 这期来聊聊数据存储相关的问题&#xff0c;包括&#xff1a; 容量评估。技术选型。容灾处理。 另外&#xff0c;文末赠送免费定制红包封面哦&#xff01; 1. 容量评估 通过对容量&性能的评估&#xff0c;可以把业务需求转化成技术语言描…

上位机图像处理和嵌入式模块部署(qt插件的使用)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 一个软件一般有很多的功能&#xff0c;但是主流程只有一个。但在软件开发的过程当中&#xff0c;一般来说功能是需要不断添加的&#xff0c;但是主…

C++ -- 入门(引用)

1.引用 1.1引用的概念 引用不是新定义一个变量&#xff0c;而是给已存在变量取了一个别名&#xff0c;编译器不会为引用变量开辟内存空间&#xff0c;它和它引用的变量共用同一块内存空间。 比如&#xff1a;李逵&#xff0c;在家称为"铁牛"&#xff0c;江湖上人称&q…