数据结构第二课 -----线性表之顺序表

news2024/11/27 4:38:17

作者前言

🎂 ✨✨✨✨✨✨🍧🍧🍧🍧🍧🍧🍧🎂
​🎂 作者介绍: 🎂🎂
🎂 🎉🎉🎉🎉🎉🎉🎉 🎂
🎂作者id:老秦包你会, 🎂
简单介绍:🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂
喜欢学习C语言和python等编程语言,是一位爱分享的博主,有兴趣的小可爱可以来互讨 🎂🎂🎂🎂🎂🎂🎂🎂
🎂个人主页::小小页面🎂
🎂gitee页面:秦大大🎂
🎂🎂🎂🎂🎂🎂🎂🎂
🎂 一个爱分享的小博主 欢迎小可爱们前来借鉴🎂


顺序表

  • **作者前言**
  • 线性表
  • 顺序表
  • 动态顺序表的使用
    • 动态顺序表开辟扩大问题
    • 顺序表的初始化
    • 顺序表的销毁
    • 顺序表的尾部插入
    • 顺序表的头部插入
    • 顺序表尾部删除
    • 顺序表的头部删除
    • 顺序表的随机插入
    • 顺序表的随机删除
    • 顺序表的查找
    • 顺序表的菜单操作
  • 总结

线性表

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

顺序表

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

  1. 静态顺序表:使用定长数组存储元素。
#include<stdio.h>
#define N 6
typedef int SLDatatype;
typedef struct SLSelist
{
	SLDatatype slt[N];//数组
	size_t count;//计算个数
} SLT;
int main()
{
	SLT selist = { {1,2,3},3 };
	printf("%d", selist.count);
	return 0;
}

在这里插入图片描述
一般静态的顺序表用处不大,这里主要介绍动态顺序表
2. 动态顺序表: 使用动态开辟的数组存储。

#include<stdio.h>
typedef int SLDatatype;
typedef struct SLSelist
{
	SLDatatype* Sel;
	size_t count;//个数
	size_t capacity;//容量
}SeList;

动态顺序表的使用

动态顺序表开辟扩大问题

在使用动态顺序表的大小,一般都是先开辟一定数量的空间,如果开辟的空间不够用时我们就可以利用realloc扩大空间,我们时常为扩大多少空间烦恼,在顺序表中是没有规定扩大多少,一个个扩大或几千或者几万的扩大都是可以的,但是为了节省空间,和减少扩大频率,我们默认一般都是把目前的空间扩大两倍,比如定义大小为100 下次扩大为200,下次为400,
在这里插入图片描述
遇到问题就要具体分析,空间的扩大没有限制,按实际情况来

顺序表的初始化

//初始化
void SLinit(SeList* SL)
{
	//方式1
	/*SL->Sel = NULL;
	SL->count = 0;
	SL->capacity = 0;*/
	//方式2
	SL->Sel = calloc(SIZE, sizeof(SLDatatype));
	SL->count = 0;
	SL->capacity = SIZE;
}

初始化有两种一种是没有给空间的初始化,一种是给空间的初始化。所以我们可以二选一

顺序表的销毁

因为我们是动态开辟。所以我们要使用free来释放空间,否则就会可能造成内存泄漏,这里用于结束顺序表

//销毁
void Desstroy(SeList* SL) 
{
	free(SL->Sel);
	SL->Sel = NULL;
	SL->count = 0;
	SL->capacity = 0;

}

顺序表的尾部插入

思路:第一步先判断空间是否满了。没满直接在最后面插入,满了就要先扩容,再插入,我们需要注意的是SL->capacity的个数是否为0

//尾插
void SLPushBack(SeList* SL, SLDatatype elemest)
{
	
	//扩大空间
	if (SL->capacity == SL->count)
	{
		//扩2倍
		size_t NewSize = ((SL->capacity * 2) > 0 ? (SL->capacity * 2) : 4);
		SLDatatype	* mdt = realloc(SL->Sel, sizeof(SLDatatype) * NewSize);
		if (mdt != NULL)
		{
			SL->Sel = mdt;
			SL->capacity = SL->capacity * 2;
		}
		else
		{
			perror("SLPushBack _ realloc");
			return;
		}
	}
	SL->Sel[SL->count] = elemest;
	SL->count++;
	

}

这里我们只要的知识还是顺序表,这个过程我们要使用到realloc函数,这个函数主要的作用是扩大动态开辟的空间,扩大的方式有两种,一种是原地扩容(效率高),一种是异地扩容(效率低,会找到一块符合条件的空间开辟,然后把原来的数据拷贝过来,free掉原来的地址)realloc是可以对NULL进行扩容相当于malloc
代码如下:

#include<stdio.h>
int main()
{

	int* arr = (int*)malloc(100);
	if (arr == NULL)
	{
		perror("malloc");
		return 1;
	}
	int* tmp = realloc(arr, sizeof(int) * 1000);
	if (tmp != NULL)
	{
		arr = tmp;
	}
	else
	{
		perror("realloc");
	}
	return 0;
}

这里就可以简单的判断出是原地扩容还是异地扩容了,

顺序表的头部插入

思路:第一步先判断空间是否满了。没满直接在前面插入,满了就要先扩容,再插入,我们需要注意的是SL->capacity的个数是否为0

//扩大空间
void capacityadd(SeList* SL)
{
	//扩大空间
	if (SL->capacity == SL->count)
	{
		//扩2倍
		size_t NewSize = ((SL->capacity * 2) > 0 ? (SL->capacity * 2) : 4);
		SLDatatype* mdt = realloc(SL->Sel, sizeof(SLDatatype) * NewSize);
		if (mdt != NULL)
		{
			SL->Sel = mdt;
			SL->capacity = SL->capacity * 2;
		}
		else
		{
			perror("SLPushBack _ realloc");
			return;
		}
	}
}
// 头插
void SLPushFront(SeList* SL, SLDatatype elemest)
{
	capacityadd(SL);
	// 往后移动
	
	for (int i = SL->count; i > 0; i--)
	{
		SL->Sel[i] = SL->Sel[i - 1];
	}
	//插入
	SL->Sel[0] = elemest;
	SL->count++;

}

在这里的时间复杂度是O(n),但是我们如果插入n个数据,时间复杂度就是O(n^2),插入的数量越多时间复杂度就越高

顺序表尾部删除

思路:要判断顺序表的存储的数据是否为0,不判断可能SL->capacity为负数,后面插入数据就有可能会越界访问

//尾删
void SLPopBack(SeList* SL) 
{
	if (SL->count)
	{
		SL->count--;
	}
	else
	{
		return;
	}

}

这里我们不需要把空间删除我们只需把SL->capacity减1,就可以下次尾插或者头插就覆盖掉这个数据
​我们还可以使用assert函数来判断

顺序表的头部删除

思路:就是我们只需要把后面的往前覆盖就行,我们还要判断是否是SL->count为0

// 头删
void SLPopFront(SeList* SL)
{
	assert(SL && SL->count);
	int idx = 0;
	while (idx < SL->count - 1)
	{
		SL->Sel[idx] = SL->Sel[idx + 1];
		idx++;
	}
	SL->count--;


}

顺序表的随机插入

这里插入我们要注意顺序表的空间是连续的,存储数据也是连续的,不可以跳过一两个空间存储数据
只能紧挨这其他数据
在这里插入图片描述

/随机插入
void SLInsert(SeList* SL,int pos, SLDatatype elemest)
{
	assert(SL && pos >= 0 && pos <= SL->count);
	//判断容量是否正常
	capacityadd(SL);
	//往后移
	int i = SL->count - 1;
	while (i >= pos)
	{
		SL->Sel[i + 1] = SL->Sel[i];
	}
	SL->Sel[pos] = elemest;
	SL->count++;
	
}

顺序表的随机删除

和上面的思路是一样的

//随机删除
void SLErase(SeList* SL, int pos, SLDatatype elemest)
{
	assert(SL && pos >= 0 && pos < SL->count);
	//覆盖
	int i = pos;
	while (i < SL->count - 1)
	{
		SL->Sel[i] = SL->Sel[i + 1];
		i++;
	}
	SL->count--;

}

顺序表的查找

//查找
int SLFind(SeList* SL, SLDatatype elemest)
{
	assert(SL);
	int i = 0;
	for (i = 0; i < SL->count; i++)
	{
		if (SL->Sel[i] == elemest)
		{
			return i;
		}
	}
	return -1;
}

顺序表的菜单操作

void menu()
{
	printf("****************************\n");
	printf("**** 0.exit   1.pushback ***\n");
	printf("**** 2.pushfront 3.popback**\n");
	printf("**** 4.popfront 5.inser **\n");
	printf("**** 6.ereat   7.print    **\n");
	printf("****        8.find        **\n");
	printf("***************************/\n");

}
int main()
{
	/*Test();*/
	int input = 0;
	printf("是否开始:1/0:");
	scanf("%d", &input);
	SeList S1;
	SLinit(&S1);
	do
	{
		menu();
		int select = 0;
		printf("请选择你的决定:>");
		scanf("%d", &select);
		if (select == 0)
		{
			printf("退出程序\n");
			break;


		}
		
		else if (select == 1)
		{
			int elemest = 0;
			printf("请输入你要尾插数据个数和数据:>");
			scanf("%d", &elemest);
			while (elemest)
			{
				int data = 0;
				scanf("%d", &data);
				SLPushBack(&S1, data);
				elemest--;
			}
		}
		else if (select == 2)
		{
			int elemest = 0;
			printf("请输入你要头插数据个数和数据:>");
			scanf("%d", &elemest);
			while (elemest)
			{
				int data = 0;
				scanf("%d", &data);
				
				SLPushFront(&S1, data);
				elemest--;
			}
		}
		else if (select == 3)
		{
			int elemest = 0;
			printf("请输入你要尾部删除数据个数:>");
			scanf("%d", &elemest);
			while (elemest)
			{
				SLPopBack(&S1);
				elemest--;
			}
		}
		else if (select == 4)
		{
			int elemest = 0;
			printf("请输入你要头部删除数据个数:>");
			scanf("%d", &elemest);
			while (elemest)
			{
				SLPopFront(&S1);
				elemest--;
			}
		}
		else if (select == 5)
		{
			int position = 0;
			int elemest = 0;
			printf("请输入你要插入的位置和数据:>");
			scanf("%d %d", &position, &elemest);
		    SLInsert(&S1, position, elemest);
		}
		else if (select == 6)
		{
			int position = 0;
			printf("请输入你要删除的位置:>");
			scanf("%d", &position);
			SLErase(&S1, position);
			continue;
		
		}
		else if (select == 7)
		{
			SLPrint(&S1);
		}
		else if (select == 8)
		{
			int position = 0;
			printf("请输入你要查找的数据:>");
			scanf("%d", &position);
			int a = SLFind(&S1, position);
			if (a == -1)
			{
				printf("找不到\n");
			}
			else 
			{
				printf("下标为%d\n", a);
			}
			continue;
		}
		else
		{
			printf("输入有误,请重新输入\n");
		}
	} while (input);
	SLDesstroy(&S1);

	

	return 0;
}

总结

这里主要介绍了顺序表,有不懂的小可爱可以私聊我

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

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

相关文章

2022年06月 Python(三级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python等级考试(1~6级)全部真题・点这里 一、单选题(共25题,每题2分,共50分) 第1题 如下所示的2行代码,最后print()函数打印出来的结果是?( ) c = [[赵大,21,男,北京],

【论文阅读】Equivariant Contrastive Learning for Sequential Recommendation

【论文阅读】Equivariant Contrastive Learning for Sequential Recommendation 文章目录 【论文阅读】Equivariant Contrastive Learning for Sequential Recommendation1. 来源2. 介绍3. 前置工作3.1 序列推荐的目标3.2 数据增强策略3.3 序列推荐的不变对比学习 4. 方法介绍4…

力扣每日一题94:二叉树的中序遍历

题目描述&#xff1a; 给定一个二叉树的根节点 root &#xff0c;返回 它的 中序 遍历 。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[1,3,2]示例 2&#xff1a; 输入&#xff1a;root [] 输出&#xff1a;[]示例 3&#xff1a; 输入&#x…

速学数据结构 | 循环队列怎么写才最高效?只需要掌握这些技巧

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏:《Linux深造日志》《C干货基地》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 &#x1f4cb; 前言一、什么是循环队列&#xff1f;二、如何实现循环队列&#xff1f;2.1 循环队列的结构2.2 循环…

leetcode:268. 丢失的数字(异或运算)

一、题目 函数原型&#xff1a; int missingNumber(int* nums, int numsSize) 二、思路&#xff1a; 0 - n缺失一个数字&#xff0c;那么将数组中所有的数字按位异或&#xff0c;再按位异或0 - n的所有数字&#xff0c;由于 x ^ x 0&#xff0c;0 ^ x x&#xff0c;因此最终运…

Win10/Win11总是自动更新,如何关闭自动更新?

参考:https://www.zhihu.com/search?q%E5%85%B3%E9%97%ADwindows%E8%87%AA%E5%8A%A8%E6%9B%B4%E6%96%B0&search_sourceSuggestion&utm_contentsearch_suggestion&typecontent 手动关闭 1 Windows服务 1.1 WinR输入services.msc打开服务 1.2 找到Windows Update…

黑马程序员项目-黑马点评

黑马点评1 短信登录 基于Session实现登录流程 发送验证码&#xff1a; 用户在提交手机号后&#xff0c;会校验手机号是否合法&#xff0c;如果不合法&#xff0c;则要求用户重新输入手机号 如果手机号合法&#xff0c;后台此时生成对应的验证码&#xff0c;同时将验证码进行…

从MFC初始化过程看rc文件的行为,并剖析关联控件变量的实质

以MFC对话框程序为例: 当我们打开资源编辑器时就可以很容易的添加各种控件窗口,资源编辑器实际上操作的是rc文件;那么这些控件窗口是何时被MFC创建与管理的 没有关联控件变量前,在资源编辑器中依然可以容易拖动控件,并显示出来;这个控件窗口是如何被创建和管理的: 资源编…

【C语法学习】13 - fscanf()函数

文章目录 1 函数原型2 参数3 返回值4 比较5 示例5.1 示例15.2 示例2 1 函数原型 fscanf()&#xff1a;从指定流stream读取格式化输入&#xff0c;函数原型如下&#xff1a; int fscanf(FILE *stream, const char *format, ...)2 参数 fscanf()函数参数包括三部分&#xff1a…

Node.js 中解析 HTML 的方法介绍

在 Web 开发中&#xff0c;解析 HTML 是一个常见的任务&#xff0c;特别是当我们需要从网页中提取数据或操作 DOM 时。掌握 Node.js 中解析 HTML 的各种方式&#xff0c;可以大大提高我们提取和处理网页数据的效率。本文将介绍如何在 Node.js 中解析 HTML。 基本概念 HTML 解析…

【广州华锐互动】VR野外求生技能学习,让你感受真实的冒险之旅!

随着科技的迅速发展&#xff0c;虚拟现实(VR)技术为人们提供了一个全新的、身临其境的探险体验。通过将用户带入一个仿真的、沉浸式的虚拟环境&#xff0c;VR互动体验让人们在安全的氛围中感受到野外探险的乐趣。本文将从视觉呈现、沉浸式体验、交互性和应用范围四个方面&#…

MATLAB颜色索引表---持续更新中--各个平台都可使用

MATLAB颜色索引表—持续更新中–各个平台都可使用

探索ChatGPT在学术写作中的应用与心得

随着人工智能的迅猛发展&#xff0c;ChatGPT作为一种强大的自然语言处理模型&#xff0c;逐渐在学术界引起了广泛的关注。本文将探讨ChatGPT在学术写作中的应用&#xff0c;并分享使用ChatGPT进行学术写作时的一些经验和心得。 01 — ChatGPT在学术写作中的应用 1.文献综述和…

【ChatOCR】OCR+LLM定制化关键信息抽取(附开源大语言模型汇总整理)

目录 背景技术方案存在的问题及解决思路关键信息提取结果其他解决方案替换文心一言LangChain大型多模态模型&#xff08;Large Multimodal Model, LMM&#xff09; 开源大模型汇总LLaMA —— Meta 大语言模型Stanford Alpaca —— 指令调优的 LLaMA 模型Lit-LLaMA —— 基于 na…

基于单片机的语音存储与回放系统设计

博主主页&#xff1a;单片机辅导设计 博主简介&#xff1a;专注单片机技术领域和毕业设计项目。 主要内容&#xff1a;毕业设计、简历模板、学习资料、技术咨询。 文章目录 主要介绍一、控制系统设计1.1 系统方案设计1.2 系统工作原理 二、硬件电路设计总电路设计图 三、 软件设…

shufflenet v2 yolo

设计理念 1x1卷积进行平衡输入和输出的通道大小&#xff1b;组卷积要谨慎使用&#xff0c;注意分组数&#xff1b;避免网络的碎片化&#xff1b;减少元素级运算。 ShuffleNet v2中弃用了1x1的group convolution操作&#xff0c;而直接使用了input/output channels数目相同的…

win10系统nodejs的安装npm教程

1.在官网下载nodejs&#xff0c;https://nodejs.org/en 2&#xff0c;双击nodejs的安装包 3&#xff0c;点击 next 4&#xff0c;勾选I accpet the terms in…… 5&#xff0c;第4步点击next进入配置安装路径界面 6,点击next&#xff0c;选中Add to PATH &#xff0c;旁边…

高压检测设备

比如&#xff1a;高压数字表、高压差分探头、指针式高压表、电流探枪、高压探棒 这些设备都是用来测量高压的&#xff0c;有的测电压&#xff0c;有的测电流。 高压数字表&#xff1a; 单独使用&#xff0c;功能很简单&#xff0c;有2个正负极探爪&#xff0c;把2个探爪连接到…

Linux 安装 RocketMq

RocketMq是阿里出品&#xff08;基于MetaQ&#xff09;的开源中间件&#xff0c;已捐赠给Apache基金会并成为Apache的顶级项目。基于java语言实现&#xff0c;十万级数据吞吐量&#xff0c;ms级处理速度&#xff0c;分布式架构&#xff0c;功能强大&#xff0c;扩展性强。 官网…

大厂面试题-IO和NIO区别

从下面几个方面来回答&#xff1a; 首先&#xff0c;I/O&#xff0c;指的是IO流&#xff0c;它可以实现数据从磁盘中的读取以及写入。 实际上&#xff0c;除了磁盘以外&#xff0c;内存、网络都可以作为I/O流的数据来源和目的地。 在Java里面&#xff0c;提供了字符流和字节…