数据结构-顺序表详解专题

news2024/11/17 11:41:51

目录

顺序表

1.简单了解顺序表

2.顺序表的分类

2.1静态顺序表

2.2动态顺序表

2.3typedef命名作用

3.动态顺序表的实现

SeqList.h

SeqList.c

test.c


顺序表

1.简单了解顺序表

顺序表是线性表的一种,线性表是在逻辑上是线性结构,在物理逻辑上并不是一定连续的

顺序表的低层结构是数组,对数组的封装,实现了对数据的增删查改等功能。

2.顺序表的分类

顺序表可以分为静态顺序和动态顺序表

2.1静态顺序表

#define MAX 100
typedef int SLDataType;
//静态顺序表
typedef struct SeqList
{
	SLDataType a[MAX];//这个是开辟100大小的空间,而不是已经使用有效的空间
	int size; //计算存放的有效数据
}SL;

静态顺序表缺陷:空间给少了不够用会造成数据丢失,给多了造成空间浪费。

2.2动态顺序表

//动态顺序表
typedef struct SeqList
{
	SLDataType * arr; //类似于数组指针,作为存储数据的低层结构
	int capacity;//容量,记录顺序表的空间大小,也就是要开辟的空间大小
	int size;//就是记录当前存放了多少有效数据。
}SL;
//两种相同的命名写法。
//typedef sturuct SeqLits SL;

动态顺序表能够实现需要使用空间时候开辟,这样更方便数据的管理,所以推荐用动态顺序表。

2.3typedef命名作用

为什么要用typedef呢

因为当你写int的一堆代码,如果想要把int改成char类型的时候,如果没用到typedeff的话,就要一个一个的改,如果使用了typedef的话直接修改int 换成char就可以了。

3.动态顺序表的实现

分成了三个板块,分别为SeqList.h , SeqList.c ,test.c

SeqList.h

//动态顺序表
typedef struct SeqList
{

	SLDataType * arr; //类似于数组指针,作为存储数据的低层结构
	int capacity;//容量,记录顺序表的空间大小,也就是要开辟的空间大小
	int size;//就是记录当前存放了多少有效数据。
}SL;
//两种相同的命名写法。
//typedef sturuct SeqLits SL;
void SLinit(SL *ps);
void SLPrint(SL* ps); //打印

void SLPushBack(SL * ps ,SLDataType x);  //尾插 
void SLPushFront(SL* ps, SLDataType x);  //头插
void SLCheckcapacity(SL* ps); //扩容

void SLPopBack(SL* ps); //尾删
void SLPopFront(SL* ps); //头删

void SLInsert(SL* ps, int pos, SLDataType x);//指定位置插入
void SLErase(SL* ps, int pos);//指定位置删除

SeqList.c

#include "Sqlist.h"
//初始化
void SLinit(SL* ps)
{
	ps->arr = NULL;
	ps->capacity = 0;
	ps->size = 0;

}
//打印
void SLPrint(SL* ps)
{
	for (int i = 0; i < ps->size; i++)
	{
		printf("%d  ", ps->arr[i]);
	}
	printf("\n");
}

/扩容放在这里,因为等下头插也会用到,设置成公共的,减少代码
void SLCheckcapacity(SL *ps)
{
	//扩容
	//先判断是不是空间满了
	if (ps->size == ps->capacity)
	{
		//扩容先给arr申请开劈空间 SLDataType * arr; 
		//realloc头文件 stdlib.h,  void  realloc (这是要在已有的空间情况下继续扩容,扩容的大小)
		//ps->arr = (SLDataType*)realloc(ps->arr,2* ps ->capacity  );//扩容2倍2* ps ->capacity
		//但是上面这个是不可取的,因为ps ->capacity刚刚被初始化现在为0。
		//因此要事先判断当 ps ->capacity为0 时,要先赋值,如果不为0 那么开辟2倍的空间
		int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity; //三目运算符
		/*ps->arr = (SLDataType*)realloc(ps->arr, newcapacity);*/
		//这样写还是不够准确,这个时候newcapacity是比特大小,不是字节,
		//这个时候要* 一个sizeof(SLDataType),因为要类型的大小字节不同
		/*ps->arr = (SLDataType*)realloc(ps->arr, newcapacity * sizeof(SLDataType));*/
		//即使这样还是不行,因为你不知道是否申请成功,所以还要创建一个临时变量,然后进行判断realloc是否成功
		SLDataType* tmp = (SLDataType*)realloc(ps->arr, newcapacity * sizeof(SLDataType));
		//判断realloc是否申请空间成功
		if (tmp == NULL)//如果没空那么是没成功
		{
			perror("realloc fail!"); //这个为啥这么写还真不知道
			exit(1); //扩容失败直接中断程序
		}
		//到这步说明已经申请空间成功
		//free(ps->arr);//不需要这个,realloc他会自己销毁
		ps->arr = tmp;
		ps->capacity = newcapacity;
	}
}


//尾插
//参数列表中有一个指向SL结构体的指针ps,
//和一个用来存储数据的参数x。
//函数内部先用assert函数判断st是否为空,
//然后判断栈是否已经满了。如果栈满了,
//就进行扩容操作,将原数组大小翻倍(如果原来大小是0则扩容为4),
//然后利用realoc函数重新分配内存空间,并将原数组中的数据拷贝到新的空间中。,拷贝的时候要销毁空间
//最后将数据x压入栈的顶部,并将栈顶指针top加一。
void SLPushBack(SL* ps, SLDataType x) //用来存储数据的参数x,x是用来插入数据的内容
{
	//assert 如果不成立那么会直接中断报错,并且会说明在哪里错误。
	//assert(ps);
	assert(ps != NULL); 
	//温柔的判断解决,不会报错
	/*if (ps != NULL)
	{
		return;
	}*/
	//尾插分为情况
	//1.第一个是空间已经满了需要扩容
	//2.第二个是还有空间,直接在尾部,也就是ps -> size 位置插入即可。
	//空间不够
	SLCheckcapacity(ps);
	//空间没有满,直接进行尾插
	ps->arr[ps->size] = x; //为啥存放到arr里面,那capacity干嘛的
	//arr是结构体指针指向的是地址然后用来存放内容的,capacity只是用来存放目前空间大小的容量而已
	ps->size++;


}
//头插
void SLPushFront(SL* ps, SLDataType x)
{
	//头插也是两种情况,一种是满了要开空间,另一种是没满,要把旧数据往后移动,然后留首位置插入
	assert(ps != NULL);
	SLCheckcapacity(ps);

	//将旧数据往后移动,从后面开始移动
	for (int  i = ps->size ; i > 0 ; i--) //让i指向size位置。
	{
		ps->arr[i] = ps->arr[i - 1]; //让i-1位置移动到i位置,就是往后移动一个位置。
	}
	ps->arr[0] = x; //首位置放新元素,头插
	ps->size++;
}

//尾删
void SLPopBack(SL* ps)
{
	//两种情况,第一种是全为空,无法删除,第二种是直接可以删尾部数据
	assert(ps != NULL);
	assert(ps->size != 0);//顺序表不能为空

	//进行第二种情况
	//ps->arr[ps->size - 1] = NULL; 
	//当size --,那么即使size位置里面有数据,也不会影响打印,插入,删除
	//因为默认size位置是不进行处理的。相当于看不见等于没有
	ps->size--;

}

void SLPopFront(SL* ps)
{
	//两种情况,第一种是全为空,无法删除,第二种是删除头部,把数据往前移动
	assert(ps != NULL);
	assert(ps->size != 0);//顺序表不能为空

	for (int i = 0 ; i < ps ->size -1 ; i++) //因为size要往前移动一个,i最大只能说ps ->size-2
	{
		ps->arr[i] = ps->arr[i + 1];
	}
	ps->size--;
}
//在指定位置插入元素
void SLInsert(SL* ps, int pos, SLDataType x)
{
	
	assert(ps);
	//要限制pos的大小,不然会出错,pos要小于size,也要大于0
	assert(pos >= 0 && pos <= ps->size);
	//扩容
	SLCheckcapacity(ps);

	//首先要知道要插入的pos位置,然后把pos后面的数据往后移动,留pos位置插入
	for (int i = ps->size; i > pos; i--)
	{
		//最后一位size,所以从size开始
		ps->arr[i] = ps->arr[i - 1];//固定句式前面丢给后面
	}
	ps->arr[pos] = x;
	ps->size++;

}

//指定位置删除
void SLErase(SL* ps, int pos)
{
	assert(ps);
	assert(pos >= 0 && pos < ps->size );
	//让pos后面的数据往前移动
	for (int i = pos ; i < ps->size - 1 ; i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}
	ps->size--;
}



test.c

#include "Sqlist.h"
void slinit()
{
	SL sl;
SLinit(&sl);//ctrl +d 快速复制

SLPushBack(&sl, 1); //因为是int类型,一开始空间是四个
SLPushBack(&sl, 2);
SLPushBack(&sl, 3);
SLPushBack(&sl, 4);
/*SLPushBack(&sl, 1);
SLPushBack(&sl, 1);*/
SLPrint(&sl);
//当传过去的是null空地址
//SLPushBack(NULL, 4); //传空地址乱码,要用accert判断
/*SLPushBack(&sl, 5);
SLPrint(&sl);*/
SLPushFront(&sl, 5);
SLPushFront(&sl, 6);
SLPushFront(&sl, 7);
SLPrint(&sl);

/*SLPopBack(&sl);
SLPopBack(&sl);
SLPopBack(&sl);
SLPrint(&sl);*/

SLPopFront(&sl);
SLPopFront(&sl);
SLPrint(&sl);

SLInsert(&sl, 0, 102);
SLInsert(&sl, 3, 15);
SLInsert(&sl, 4, 22);
SLPrint(&sl);

SLErase(&sl, 0);
SLErase(&sl, 2);
SLPrint(&sl);
}
int main()
{
	slinit();
	return 0;
}

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

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

相关文章

基于springboot+vue的校园资料分享平台(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目背景…

Nginx与keepalived实现集群

提醒一下&#xff1a;下面实例讲解是在mac虚拟机里的Ubuntu系统演示的&#xff1b; Nginx与keepalived实现集群实现的效果 两台服务器都安装Nginx与keepalived&#xff1a; master服务器的ip(192.168.200.2) backup服务器的ip(192.168.200.4) 将 master服务器Nginx与keepalive…

JavaEE-自定义SSM-编写核心-解析yml文件

3.3.1 加载yml文件 编写yaml工厂&#xff0c;用于加载yml文件 package com.czxy.yaml;import java.io.InputStream;/*** 用于处理 application.yml文件* 1. 加载application.yml文件* 2. yaml工具类进行解析* Map<String, Map<String, Map<....>> >* …

线性代数----------学习记录

线性代数发展历程 &#xff08;1&#xff09;线性方程组&#xff1a;例如二元一次方程组&#xff1b; &#xff08;2&#xff09;行列式&#xff1a;determinant,克莱默&#xff0c;莱布尼兹&#xff1b; &#xff08;3&#xff09;矩阵&#xff1a;方程个数与未知数的个数可…

webug存在的越权漏洞-水平越权以及垂直越权的漏洞复现(超详解)

越权漏洞-webug、 1.登录 账号&#xff1a;admin 密码&#xff1a;admin 2.进入逻辑漏洞 3.进入越权修改密码靶场 &#xff08;1&#xff09;输入账号密码 进入进去会发现没有权限进入 方法一&#xff1a; 这里我们只需要将 127.0.0.1:8080/control/a/auth_cross/cross_a…

编程那么难,为什么不弄一个大众一学就会的计算机语言呢?

大家好&#xff01;今天要和大家聊聊一个有趣的想法&#xff1a; 想象一下&#xff0c;如果编程变得像拼乐高积木一样简单&#xff0c;那将是多么美妙的事情啊&#xff01;不需要费尽心思去学习繁杂的语法规则和复杂的逻辑&#xff0c;只需要将代码块像积木一样拼接起来&#x…

小土堆pytorch学习笔记003 | 下载数据集dataset 及报错处理

目录 1、下载数据集 2、展示数据集里面的内容 3、DataLoader 的使用 例子&#xff1a; 结果展示&#xff1a; 1、下载数据集 # 数据集import torchvisiontrain_set torchvision.datasets.CIFAR10(root"./test10_dataset", trainTrue, downloadTrue) test_set …

Java后端开发:学籍系统核心逻辑

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

Apache Doris (六十九):JDBC Catalog

🏡 个人主页:IT贫道-CSDN博客 🚩 私聊博主:私聊博主加WX好友,获取更多资料哦~ 🔔 博主个人B栈地址:豹哥教你学编程的个人空间-豹哥教你学编程个人主页-哔哩哔哩视频 目录 1. 创建Catalog

第六课:Prompt

文章目录 第六课&#xff1a;Prompt1、学习总结&#xff1a;Prompt介绍预训练和微调模型回顾挑战 Pre-train, Prompt, PredictPrompting是什么?prompting流程prompt设计 课程ppt及代码地址 2、学习心得&#xff1a;3、经验分享&#xff1a;4、课程反馈&#xff1a;5、使用Mind…

【电子通识】学习网上《初学者学习电子的常见误区文章》有感

学习硬件电子电路过程中&#xff0c;特别是初级阶段&#xff0c;可能会走进一些误区&#xff0c;会比较迷茫和困惑。如果这时不能正确对待好这些困惑&#xff0c;就会影响正常的学习&#xff0c;干扰学习的进程&#xff0c;严重时可能会半途而废。今天我从网络上看到为初学者写…

什么是单元测试?谁来做?怎么写?

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;薪资嘎嘎涨 一、什么是单元测试&#xff1f; 单元测试&#xff08;unit testing&#xff09;&#xff0c…

pytorch-metric-learning度量学习工具官方文档翻译

基于Pytorch实现的度量学习方法 开源代码&#xff1a;pytorch-metric-learning官网文档&#xff1a;PyTorch Metric Learning官方文档 度量学习相关的损失函数介绍&#xff1a; 度量学习DML之Contrastive Loss及其变种度量学习DML之Triplet Loss度量学习DML之Lifted Structu…

幻兽帕鲁服务器多少钱一台?腾讯云新版报价

腾讯云幻兽帕鲁服务器4核16G、8核32G和16核64G配置可选&#xff0c;4核16G14M带宽66元一个月、277元3个月&#xff0c;8核32G22M配置115元1个月、345元3个月&#xff0c;16核64G35M配置580元年1个月、1740元3个月、6960元一年&#xff0c;腾讯云百科txybk.com分享腾讯云幻兽帕鲁…

谷歌Chrome浏览器将通过人工智能技术升级了3项重大功能改变,Chrome (M121) 版本可以在浏览器上生成内容

从今天开始发布的 Chrome (M121) 版本起&#xff0c;Chrome 将引进一系列实验性的生成式 AI 功能。这些功能包括智能组织标签页、利用文本生成图像模型生成个性化壁纸图片&#xff0c;以及辅助写作。这些新功能将为用户提供更便捷、智能的浏览体验。 Chrome官方介绍网址&#x…

php mysql字段默认值使用问题

前提是使用了事务&#xff0c;在第一个阶段 是A表操作保存&#xff0c;第二阶段操作B表&#xff0c;操作B表的时候使用了A表的一个字段&#xff0c;这个字段在第一阶段没有设置值&#xff0c;保存的时候使用字段默认值。 【这种情况 最好是在第一阶段 把后面要使用的字段设置好…

Vue中使用TypeScript:全面指南和最佳实践

🚀 欢迎来到我的专栏!专注于Vue3的实战总结和开发实践分享,让你轻松驾驭Vue3的奇妙世界! 🌈✨在这里,我将为你呈现最新的Vue3技术趋势,分享独家实用教程,并为你解析开发中的难题。让我们一起深入Vue3的魅力,助力你成为Vue大师! 👨‍💻💡不再徘徊,快来关注…

ChatGPT 官方中文页面上线

根据页面显示&#xff0c;OpenAI 现已推出 ChatGPT 的多语言功能 Alpha 版测试&#xff0c;允许用户选择不同语言的界面进行交互。 如下图所示&#xff0c;ChatGPT 会检测系统当前所使用的语言&#xff0c;并提示用户进行语言切换。 用户也可通过设置页面选择其他语言。目前&a…

【JavaEE】网络原理:UDP数据报套接字编程和TCP流套接字编程

目录 1.UDP数据报套接字编程 1.1 DatagramSocket 1.2 DatagramPacket 1.3 InetSocketAddress 1.4 基于UDP实现回响服务器 2.TCP流套接字编程 2.1 ServerSocket 2.2 Socket 2.3 基于TCP实现回响服务器 1.UDP数据报套接字编程 API 介绍 1.1 DatagramSocket DatagramS…

【C++中STL】set/multiset容器

set/multiset容器 Set基本概念set构造和赋值set的大小和交换set的插入和删除set查找和统计 set和multiset的区别pair对组两种创建方式 set容器排序 Set基本概念 所有元素都会在插入时自动被排序。 set/multist容器属于关联式容器&#xff0c;底层结构属于二叉树。 set不允许容…