史上最详细的改良顺序表讲解,看完不会你打我

目录

0.什么是顺序表

1.顺序表里结构体的定义

2.顺序表的初始化

3.顺序表的输入

4.增加顺序表的长度

5.1顺序表的元素查找(按位查找)

5.2顺序表的元素查找(按值查找)在顺序表进行按值查找,大概只能通过遍历的方式,这也算是顺序表的缺点吧!

6.顺序表的元素插入

7.顺序表的元素删除

8.顺序表的打印

9.求顺序表的表长

10.顺序表的销毁

11.运行结果 

 12.全部代码

0.什么是顺序表

  • 顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组
    上完成数据的增删查改。

  • 顺序表:可动态增长的数组,要求数据是连续存储的

1.顺序表里结构体的定义

typedef struct SList
{
	int length;
	int MaxSize;
	int* data;
}SList;

length为当前顺序表长度 MaxSize是顺序表最大长度 ,* data是定义顺序表中元素类型的数组指针

2.顺序表的初始化

#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#define InitSize 10

void InitSList(SList& L)
{
	L.data = (int*)malloc(sizeof(int) * InitSize);
	if (L.data == NULL)
	{
		printf("%s\n",strerror(errno));
	}
	L.length = 0;
	L.MaxSize = InitSize;
}

需要注意的是,malloc函数的返回的是无类型指针,在使用时一定要强制转换为所需要的类型。在使用malloc函数开辟的空间中,不能进行指针的移动,因为一旦移动之后可能出现申请的空间和释放空间大小的不匹配。

我们使用malloc函数申请大小为InitSize个字节的空间,成功申请会返回指向所申请空间的指针,如果申请失败会返回空指针NULL。

可能会空间开辟失败的情况,我们加上strerror函数。

strerror函数会返回错误码所对应的错误信息,返回值是一个指向描述错误的字符串的指针。

要使用它的话,必须包含errno.h这个头文件。

  • 每一个这样的错误码都对应着一个错误信息,sterror函数能把错误码所对应错误信息的首字符的地址返回。
  • 当C语言的库函数调用失败的时候,会将一个错误码存放在一个叫errno的变量中。
  • 当我们想知道调用库函数的时候发生了什么错误信息,就可以将errno中的错误码翻译成错误信息。

如图,当我们所要的空间太大,初始化失败时

 它会提示空间不够。

3.顺序表的输入

void WriteSList(SList& L)
{
	printf("请输入你要创建的顺序表的长度:>");
	scanf("%d", &L.length);
	printf("请输入你要创建的顺序表的元素:>");
	for (int j = 0; j < L.length; j++)
	{
		scanf("%d", &L.data[j]);
	}
}

这一部分没有什么好说的,我们先输入长度再将每个元素输入就行。

4.增加顺序表的长度

我们定义一个*p指针来指向原顺序表的地址,之后再使用malloc函数来开辟一块更大的空间,空间大小由我们来定义,再将*p指向的值,也就是原顺序表的内容挨个赋值给新的顺序表,最后将原来的空间删除即可。不要忘记让p指向空指针哦!

void IncreaseSize(SList& L)
{
	int len;
	int* p = L.data;
	printf("请输入你要增加的长度:>");
	scanf("%d", &len);
	L.data = (int*)malloc(sizeof(int) * (L.MaxSize+len));
	for (int i = 0; i < L.length; i++)
	{
		L.data[i] = p[i];
	}
	L.MaxSize = L.MaxSize + len;
	free(p);
    p=NULL;
}

5.1顺序表的元素查找(按位查找)

按位查找直接通过数组下标即可。 

bool GetElem(SList& L)
{
	int i;
	printf("你要找第几个元素:>");
	scanf("%d", &i);
	if (i<1 || i>L.length)
	{
		return false;
	}
	printf("第%d个元素是%d\n", i, L.data[i - 1]);
	return true;
}

布尔型(bool)变量的值只有 真 (true) 和假 (false)。一般将非零值看做true,将零值看做false。使用布尔型可以增加代码的可读性。

5.2顺序表的元素查找(按值查找)
在顺序表进行按值查找,大概只能通过遍历的方式,这也算是顺序表的缺点吧!

顺序表按值查找的时间复杂度为:O(n),效率比较低。

void LocateElem(SList& L)
{
	int e, i, k=1;
	printf("请输入你要查找的元素:>");
	scanf("%d", &e);
	for (i = 0; i < L.length; i++)
	{
		if (e == L.data[i])
		{
			k = 0;	
			printf("找到了,是第%d个元素\n", i + 1);
			break;
		}
	}
	if (k)
	{
		printf("找不到该元素\n");
	}
}

6.顺序表的元素插入

将顺序表元素的插入类比成为我们排队,当有一个人想要插入一个中间的位置时,后面的人一定会因为插队的人而后移一位。倒数第二个人会到原先倒数第一人的位置,而原先倒数第一的那个人会后移一位,所以最后表长会加一。

需要判断的有两点:

1.顺序表的空间是否够用。

2.所插入的位置是否合法,有没有越界。

bool InsertSList(SList& L)
{
	int i, e;
	printf("请输入要插入的位置和元素:>");
	scanf("%d%d", &i, &e);
	if (i<1 || i>L.length)
	{
		return false;
	}
	if (L.length > L.MaxSize)
	{
		return false;
	}
	for (int j = L.length; j >= i; j--)
	{
		L.data[j] = L.data[j - 1];
	}
	L.data[i - 1] = e;
	L.length++;
	printf("插入的元素是%d,插入的位置是%d\n", e, i);
	return true;
}

我们同样使用布尔型,在以上两种情况时返回一个false值。

让插入位置之后的元素挨个后移,在腾出的位置插入要插入的元素,返回一个true值。

7.顺序表的元素删除

依旧可以用排队的例子来说,队伍中有一个人有事要走,那么他的位置就会空出来,这时候他后面的人就要挨个向前一位来补齐这个位置。当然,最后表长会减一。

bool DeleteSList(SList& L)
{
	int i,j,e;
	printf("请输入你要删除的元素位置:>");
	scanf("%d", &i);
	if (i<1 || i>L.length)
	{
		return false;
	}
	if (!L.data)
	{
		return false;
	}
	e = L.data[i-1];
	
	for (j = i; j <= L.length;j++)
	{
		L.data[j-1] = L.data[j];
	}
	L.length--;
	printf("删除的元素是%d,它的位置是%d\n",e, i);
	return true;
}

8.顺序表的打印

首先判断表是否为空表,是空表时返回一个false。

bool PrintSList(SList &L)
{
	if (!L.data)
	{
		return false;
	}
	printf("数组里的元素有:>");
	for (int i = 0; i < L.length; i++)
	{
		printf("%d ", L.data[i]);
	}
	printf("\n");
	return true;
}

9.求顺序表的表长

int GetLength(SList& L)
{
	if (L.length == 0)
	{
		return 0;
	}
		return L.length;
}

10.顺序表的销毁

getchar的使用是很关键的,用来接收前面的回车,如果不加的话之后的scanf将会直接被跳过。

就如上篇博客所说,malloc开辟的空间是在堆区的,这片空间需要程序员主动去释放,不然会导致内存泄露的问题。大家感兴趣可以看看上篇博客。

我眼中的‘C’——动态内存+柔型数组_陈大大陈的博客-CSDN博客 

void DestroySList(SList& L)
{
	char c;
	getchar();
	printf("是否销毁顺序表(Y/N):>");
	scanf("%s", &c);
	if (c == 'Y')
	{
		L.length = 0;
		L.MaxSize = 0;
		free(L.data);
        L.data=NULL;
		printf("顺序表已销毁\n");
	}
}

11.运行结果 

 12.全部代码

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#define InitSize 10
typedef struct SList
{
	int length;
	int MaxSize;
	int* data;
}SList;
void InitSList(SList& L)
{
	L.data = (int*)malloc(sizeof(int) * InitSize);
	if (L.data == NULL)
	{
		perror("malloc");
	}
	L.length = 0;
	L.MaxSize = InitSize;
}
void WriteSList(SList& L)
{
	printf("请输入你要创建的顺序表的长度:>");
	scanf("%d", &L.length);
	printf("请输入你要创建的顺序表的元素:>");
	for (int j = 0; j < L.length; j++)
	{
		scanf("%d", &L.data[j]);
	}
}
void IncreaseSize(SList& L)
{
	int len;
	int* p = L.data;
	printf("请输入你要增加的长度:>");
	scanf("%d", &len);
	L.data = (int*)malloc(sizeof(int) * (L.MaxSize+len));
	for (int i = 0; i < L.length; i++)
	{
		L.data[i] = p[i];
	}
	L.MaxSize = L.MaxSize + len;
	free(p);
	p = NULL;
}
bool GetElem(SList& L)
{
	int i;
	printf("你要找第几个元素:>");
	scanf("%d", &i);
	if (i<1 || i>L.length)
	{
		return false;
	}
	printf("第%d个元素是%d\n", i, L.data[i - 1]);
	return true;
}
void LocateElem(SList& L)
{
	int e, i, k=1;
	printf("请输入你要查找的元素:>");
	scanf("%d", &e);
	for (i = 0; i < L.length; i++)
	{
		if (e == L.data[i])
		{
			k = 0;	
			printf("找到了,是第%d个元素\n", i + 1);
			break;
		}
	}
	if (k)
	{
		printf("找不到该元素\n");
	}
}
bool InsertSList(SList& L)
{
	int i, e;
	printf("请输入要插入的位置和元素:>");
	scanf("%d%d", &i, &e);
	if (i<1 || i>L.length)
	{
		return false;
	}
	if (L.length > L.MaxSize)
	{
		return false;
	}
	for (int j = L.length; j >= i; j--)
	{
		L.data[j] = L.data[j - 1];
	}
	L.data[i - 1] = e;
	L.length++;
	printf("插入的元素是%d,插入的位置是%d\n", e, i);
	return true;
}
bool DeleteSList(SList& L)
{
	int i,j,e;
	printf("请输入你要删除的元素位置:>");
	scanf("%d", &i);
	if (i<1 || i>L.length)
	{
		return false;
	}
	if (!L.data)
	{
		return false;
	}
	e = L.data[i-1];
	
	for (j = i; j <= L.length;j++)
	{
		L.data[j-1] = L.data[j];
	}
	L.length--;
	printf("删除的元素是%d,它的位置是%d\n",e, i);
	return true;
}
bool PrintSList(SList &L)
{
	if (!L.data)
	{
		return false;
	}
	printf("数组里的元素有:>");
	for (int i = 0; i < L.length; i++)
	{
		printf("%d ", L.data[i]);
	}
	printf("\n");
	return true;
}
int GetLength(SList& L)
{
	if (L.length == 0)
	{
		return 0;
	}
		return L.length;
}
void DestroySList(SList& L)
{
	char c;
	getchar();
	printf("是否销毁顺序表(Y/N):>");
	scanf("%s", &c);
	if (c == 'Y')
	{
		L.length = 0;
		L.MaxSize = 0;
		free(L.data);
		L.data = NULL;
		printf("顺序表已销毁\n");
	}
}
int main()
{
	SList L;
	InitSList(L);
	WriteSList(L);
	PrintSList(L);
	IncreaseSize(L);
	InsertSList(L);
	PrintSList(L);
	DeleteSList(L);
	PrintSList(L);
	GetElem(L);
	LocateElem(L);
	int len = GetLength(L);
	printf("顺序表的长度是%d\n", len);
	DestroySList(L);
	return 0;
}

 这篇博客旨在总结我自己阶段性的学习,要是能帮助到大家,那可真是三生有幸!如果觉得我写的不错的话还请点个赞和关注哦~我会持续输出编程的知识的!😘😘😘

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

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

相关文章

HFish蜜罐的介绍和简单测试(三)

在学习蜜罐时&#xff0c;HFish是个不错的选择。首先是免费使用&#xff0c;其次易于安装管理&#xff0c;然后文档支持比较丰富&#xff0c;最后还有更多扩展功能。第三篇的话作为本系列的最终篇章进行总结&#xff0c;具体是看到哪里写到哪里。 0、HFish平台管理 0.1、报告…

基于SpringBoot实现冬奥会运动会科普平台【源码+论文】

基于SpringBoot实现冬奥会科普平台演示开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#…

一文吃透SpringBoot整合mybatis-plus(保姆式教程)

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

23.3.26总结

康托展开 是一个全排列与自然数的映射关系&#xff0c;康托展开的实质是计算当前序列在所有从小到大的全排列中的顺序&#xff0c;跟其逆序数有关。 例如&#xff1a;对于 1,2,3,4,5 来说&#xff0c;它的康托展开值为 0*4&#xff01;0*3&#xff01;0*2&#xff01;0*1&…

Android 之 打开相机 打开相册

Android 之 打开系统摄像头拍照 打开系统相册&#xff0c;并展示1&#xff0c;清单文件 AndroidManifest.xml<uses-permission android:name"android.permission.INTERNET" /><!--文件读取权限--><uses-permission android:name"android.permiss…

网络编程2(套接字编程)

套接字编程UDP协议通信&#xff1a;TCP通信&#xff1a;套接字编程&#xff1a;如何编写一个网络通信程序 1.网络通信的数据中都会包含一个完整的五元组&#xff1a; sip&#xff0c;sport&#xff0c;dip&#xff0c;dport&#xff0c;protocol&#xff08;源IP&#xff0c;源…

【linux】多线程控制详述

文章目录一、进程控制1.1 POSIX线程库1.2 创建线程pthread_create1.2.1 创建一批线程1.3 终止线程pthread_exit1.4 线程等待pthread_jion1.4.1 线程的返回值&#xff08;退出码&#xff09;1.5 取消线程pthread_cancel1.6 C多线程1.7 分离线程pthread_detach二、线程ID值三、线…

C/C++内存管理

内存管理在C中无处不在&#xff0c;内存泄漏几乎在每个C程序中都会发生。因此&#xff0c;要学好C&#xff0c;内存管理这一关势在必得&#xff01; 目录 1.C/C内存分布 2.C语言中动态内存管理方式 3.C内存管理方式 3.1.new和delete操作内置类型 3.2.new和delete操作自定义类型…

SQL注入之HTTP请求头注入

Ps&#xff1a; 先做实验&#xff0c;在有操作的基础上理解原理会更清晰更深入。 一、实验 sqli-lab 1. User-Agent注入 特点&#xff1a;登陆后返回用户的 User-Agent --> 服务器端可能记录用户User-Agent 输入不合法数据报错 payload: and updatexml(1,concat("~&…

异或相关算法

文章目录1. 异或的性质2. 题目一3. 题目二4. 题目三5. 题目四1. 异或的性质 我们知道&#xff0c;异或的定义是&#xff1a;相同为0&#xff0c;相异为1。所以也被称为无进位相加&#xff0c;根据这定义&#xff0c;我们可以得出三个性质&#xff1a; 1. N ^ N0。2. N ^ 0N。3…

13-C++面向对象(纯虚函数(抽象类)、多继承、多继承-虚函数、菱形继承、虚继承、静态成员)

虚析构函数 存在父类指针指向子类对象的情况&#xff0c;应该将析构函数声明为虚函数&#xff08;虚析构函数&#xff09; 纯虚函数 纯虚函数&#xff1a;没有函数体且初始化为0的虚函数&#xff0c;用来定义接口规范 抽象类&#xff1a; 含有纯虚函数的类&#xff0c;不可以实…

Prometheus监控实战系列十七:探针监控

目前对于应用程序的监控主要有两种方式&#xff0c;一种被称为白盒监控&#xff0c;它通过获取目标的内部信息指标&#xff0c;来监控目标的状态情况&#xff0c;我们前面介绍的主机监控、容器监控都属于此类监控。另一种则是“黑盒监控”&#xff0c;它指在程序外部通过探针的…

【Linux】Linux下权限的理解

前言&#xff1a;在之前我们已经对基本的指令进行了深入的学习&#xff0c;接下来我将带领大家学习的是关于权限的相关问题。在之前&#xff0c;我们一直是使用的【root】用户&#xff0c;即为“超级用户”&#xff0c;通过对权限的学习之后&#xff0c;我们就会慢慢的切换到普…

【数据结构】双向链表实现

Yan-英杰的主页 悟已往之不谏 知来者之可追 C程序员&#xff0c;2024届电子信息研究生 目录 一、什么是双向链表 二、双向链表的实现 一、什么是双向链表 双向链表也叫双链表&#xff0c;是链表的一种&#xff0c;它的每个数据节点中都有两个指针&#xff0c;分别指向直接后…

【数据结构初阶】单链表

目录一、思路>>>>>>>>>>>>过程<<<<<<<<<<<<<<<1.打印2.尾插3.尾删4.头插5.头删6.查找7.指定位置后插入8.指定位置后删除9.链表的销毁二、整个程序1.SLTlist.c2.SLTlist.c一、思路 #define …

点云可视化:使用open3d实现点云连续播放

模型训练完成后除了看ap等定量的指标是否变好外,还需要将结果可视化出来,直接观察模型的输出结果,往往我们的数据会比较多,如果单帧的看的话会比较麻烦,需要频繁的关闭窗口,最好是能直接连续的播放数据和模型的推理结果。有三种方法: clear_geomotry()和update_render()…

SpringBoot 解决id使用字符串类型可以解决精度问题

1. 问题引入 当主键超过19位长度的数值型的属性值后三位会被四舍五入 2. 使用雪花算法解决 雪花算法长度最大只有19位的10进制&#xff0c;所以不会丢失精度问题&#xff01;SpringBoot 解决主键雪花算法配置https://liush.blog.csdn.net/article/details/129779627 ① appli…

Linux的基础知识

根目录和家目录根目录&#xff1a;是Linux中最底层的目录&#xff0c;用"/"表示家目录&#xff1a;当前用户所在的路径&#xff0c;用“~”表示&#xff0c;root用户的家目录和普通用户的家目录不一样&#xff0c;普通用户的家目录在/home路径下&#xff0c;每一个用…

eNSP 网络地址转换配置实验

关于本实验当使用私有IP地址的内部主机访问外网时&#xff0c;需要使用NAT将其私有IP地址转换为公有IP地址&#xff0c;此时需要在网关路由器上配置NAT来提供相应的地址转换服务。当网关路由器连接ISP的接口上未使用固定IP地址&#xff0c;而是动态地从ISP获取IP地址时&#xf…

沁恒CH32V307使用记录:SPI基础使用

文章目录目的基础说明使用演示其它补充总结目的 SPI是单片机中比较常用的一个功能。这篇文章将对CH32V307中相关内容进行说明。 本文使用沁恒官方的开发板 &#xff08;CH32V307-EVT-R1沁恒RISC-V模块MCU赤兔评估板&#xff09; 进行演示。 基础说明 SPI的基础概念见下面文…