顺序表(2)

目录

Test.c主函数

test5

test6

test7

菜单

Test.c总代码

SeqList.h头文件&函数声明

头文件

函数声明

SeqList.h总代码

SeqList.c函数实现

查找SeqListFind

某位置插入SeqListInsert

某位置删除SeqListErase

SeqList.c总代码

顺序表的问题及其思考

多文件调试小技巧


今天接着顺序表

Test.c主函数

int main()
{
	SL ps;//创建一个结构题变量-传地址调用🆗-形参是实参的一份临时拷贝
	test5(&ps);//任意位置插入
	test6(&ps);//任意位置删除
	test7(&ps);//查找
	return 0;
}

test5

void test5(SL* ps)//测试在任意位置插入数据
{
	SLInit(ps);
	SLPushBack(ps, 10);
	SLPushBack(ps, 20);
	SLPushBack(ps, 30);
	SLPushBack(ps, 40);
	SLInsert(ps, 3, 7);
	SLInsert(ps, 4, 9);
	SLPrint(ps);
	SLDestroy(ps);
}

test6

void test6(SL* ps)
{
	SLInit(ps);
	SLPushBack(ps, 10);
	SLPushBack(ps, 20);
	SLPushBack(ps, 30);
	SLPushBack(ps, 40);
	SLErase(ps, 1);
	SLPrint(ps);
	SLErase(ps, 2);
	SLPrint(ps);
    SLDestroy(ps);
}

test7

void test7(SL* ps)
{
	SLInit(ps);
	SLPushBack(ps, 10);
	SLPushBack(ps, 20);
	SLPushBack(ps, 30);
	SLPushBack(ps, 40);
	if (SLFind(ps, 10) == 1)
	{
		printf("找到了\n");
	}
	else
	{
		printf("未能找到\n");
	}
	SLDestroy(ps);
}

菜单

在前面我们写过【通讯录】的多文件代码,有人询问为什么这里不先写【菜单】建议是:最后把所有功能测试成功,再去写【菜单】,这样好【调试】。

写菜单可以使用:switch&case 或 if&else

如果我们要把用户输入的数据分布放到每个函数实现内部,菜单中代码会微少,用switch&case

如果我们要把用户输入的数据放到菜单里面,菜单中代码会多,用if&else

因为我们之前【三子棋】&【扫雷】&【通讯录】都使用switch&case,这里我们就用if&else写。还有补充,在数据结构当中我们一般是不写菜单的,只要功能正确即可。建议,写好函数,先单个测试,没问题,最后在写菜单。

void menu()
{
	printf("*******************************\n");
	printf("1、尾插数据  2、尾删数据\n");
	printf("3、头插数据  4、头删数据\n");
	printf("5、打印数据  0、退出  \n");
	printf("*******************************\n");
}

int main()
{
	SL s;
	SLInit(&s);

	int option = 0;
	do
	{
		menu();
		printf("请输入你的选择:>");
		scanf("%d", &option);
		if (option == 1)//尾插
		{
			printf("请依次输入你的要尾插数据个数和数据:>");
			int n = 0;
			scanf("%d", &n);
			for (int i = 0; i < n; i++)
			{
				int x = 0;
				scanf("%d", &x);
				SLPushBack(&s, x);
			}
		}
		else if (option == 2)//尾删
		{
			printf("请依次输入你的要尾删数据个数和数据:>");
			int n = 0;
			scanf("%d", &n);
			for (int i = 0; i < n; i++)
			{
				int x = 0;
				scanf("%d", &x);
				SLPopBack(&s, x);
			}
		}
		else if (option == 3)//头插
		{
			printf("请依次输入你的要头插数据个数和数据:>");
			int n = 0;
			scanf("%d", &n);
			for (int i = 0; i < n; i++)
			{
				int x = 0;
				scanf("%d", &x);
				SLPushFront(&s, x);
			}
		}
		else if (option == 4)//头删
		{
			printf("请依次输入你的要头删数据个数和数据:>");
			int n = 0;
			scanf("%d", &n);
			for (int i = 0; i < n; i++)
			{
				int x = 0;
				scanf("%d", &x);
				SLPopFront(&s, x);
			}
		}
		else if (option == 5)//打印
		{
			SLPrint(&s);
		}
		else if (option == 0)
		{
			break;
		}
		else
		{
			printf("无此选项,请重新输入\n");
		}
	} while (option != 0);

	SLDestroy(&s);

	return 0;
}


/*printf("请输入你的要尾插的数据,以-1结束:>");
			int x = 0;
			scanf("%d", &x);
			while (x != -1)
			{
				SLPushBack(&s, x);
				scanf("%d", &x);
			}*/

Test.c总代码

#include"SeqList.h"
void test1(SL*ps)//测试尾插
{
	SLInit(ps);
	SLPushBack(ps, 10);
	SLPushBack(ps, 20);
	SLPushBack(ps, 30);
	SLPushBack(ps, 40);
	SLPrint(ps);
	SLDestroy(ps);
}
void test2(SL*ps)//测试头插
{
	SLInit(ps);
	SLPushFront(ps, 10);
	SLPushFront(ps, 20);
	SLPushFront(ps, 30);
	SLPushFront(ps, 40);
	SLPrint(ps);
	SLDestroy(ps);
}
void test3(SL*ps)//测试头删
{
	SLInit(ps);
	SLPushBack(ps, 10);
	SLPushBack(ps, 20);
	SLPushBack(ps, 30);
	SLPushBack(ps, 40);
	SLPopBack(ps);
	SLPopBack(ps);
	SLPrint(ps);
	SLDestroy(ps);
}
void test4(SL*ps)//测试尾删//
{
	SLInit(ps);
	SLPushBack(ps, 10);
	SLPushBack(ps, 20);
	SLPushBack(ps, 30);
	SLPushBack(ps, 40);
	SLPopFront(ps);
	SLPopFront(ps);
	SLPrint(ps);
	SLDestroy(ps);
}
void test5(SL* ps)
{
	SLInit(ps);
	SLPushBack(ps, 10);
	SLPushBack(ps, 20);
	SLPushBack(ps, 30);
	SLPushBack(ps, 40);
	SLInsert(ps, 3, 7);
	SLInsert(ps, 4, 9);
	SLPrint(ps);
	SLDestroy(ps);
}

void test6(SL* ps)
{
	SLInit(ps);
	SLPushBack(ps, 10);
	SLPushBack(ps, 20);
	SLPushBack(ps, 30);
	SLPushBack(ps, 40);
	SLErase(ps, 1);
	SLPrint(ps);
	SLErase(ps, 2);
	SLPrint(ps);
    SLDestroy(ps);
}
void test7(SL* ps)
{
	SLInit(ps);
	SLPushBack(ps, 10);
	SLPushBack(ps, 20);
	SLPushBack(ps, 30);
	SLPushBack(ps, 40);
	if (SLFind(ps, 10) == 1)
	{
		printf("找到了\n");
	}
	else
	{
		printf("未能找到\n");
	}
	SLDestroy(ps);
}
int main()
{
	SL ps;//创建一个结构题变量-传地址调用🆗-形参是实参的一份临时拷贝
	test1(&ps);//测试尾插 
	test2(&ps);//测试头插
	test3(&ps);//测试尾删
	test4(&ps);//测试头删
	test5(&ps);//任意位置插入
	test6(&ps);//任意位置删除
	test7(&ps);//查找
	return 0;
}

SeqList.h头文件&函数声明

头文件

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>//断言

函数声明

int SLFind(SL* ps, SLDataType x);//查找
void SLInsert(SL* ps);//任意位置插入
void SLErase(SL* ps);//任意位置删除

SeqList.h总代码

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>//断言
//声明一个结构体
typedef int SLDataType;

typedef struct SeqList
{
	SLDataType* a;//如果后期a的类型改变就很方便
	int size;//有效数据
	int capacity;//空间容量
}SL;//SL是这个结构体的类型,用typedef定义更加方便了

//初始化
void SLInit(SL* ps);

//释放销毁
void SLDestroy(SL* ps);

//展示
void SLPrint(SL* ps);

void SLPushBack(SL* ps, SLDataType x);//尾插

void SLPushFront(SL* ps, SLDataType x);//头插

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

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

void SLInsert(SL* ps,int pos, SLDataType x);//任意位置插入

void SLErase(SL* ps,int pos);//任意位置删除

int SLFind(SL* ps, SLDataType x);//查找

SeqList.c函数实现

查找SeqListFind

  •  遍历一遍数组去查找元素
//元素查找
//找到了返回1
//没有找到返回-1
int SLFind(SL* ps, SLDataType x)
{
	assert(ps);
	int i = 0;
	for (i = 0; i < ps->size - 1; i++)
	{
		if (ps->a[i] == x)
		{
			return 1;
		}
	}
	return -1;
}

 

某位置插入SeqListInsert

  • pos是指我们从第一个位置往后数(数组下标是从0开始)
  • 数据往后挪动,从后往前依次向后挪动
  • 在pos-1的下标位置处放入元素,不要忘记size++哦
  • size是数据个数,看作下标的话,它是最后一个数据的下一个位置。

//任意位置插入
void SLInsert(SL* ps, int pos, SLDataType x)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	SLCheckCapacity(ps);
	int begin = ps->size;
	while (begin >= pos - 1)
	{
		ps->a[begin] = ps->a[begin - 1];
		begin--;
	}
	ps->a[pos - 1] = x;
	ps->size++;
}

某位置删除SeqListErase

  • pos是指我们从第一个位置往后数(数组下标是从0开始)
  • 数据往前挪动,从前往后依次向前挪动
  •  在pos-1的下标位置处放入元素,不要忘记size++哦
//任意位置删除
void SLErase(SL* ps, int pos)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	SLCheckCapacity(ps);
	int begin = pos - 1;
	while (begin < ps->size-1)
	{
		ps->a[begin] = ps->a[begin + 1];//会越界,注意循环条件
		begin++;
	}
	ps->size--;
}

SeqList.c总代码

#include"SeqList.h"
//初始化
void SLInit(SL* ps)
{
	ps->a = NULL;
	ps->size = 0;
	ps->capacity = 0;
}
//关于初始化 可以首先置为NULL  也可以首先放点值  
// memset一般用于数组初始化 直接初始化更加清晰

//销毁
void SLDestroy(SL* ps)
{
	if (ps->a != NULL)
	{
		free(ps->a);
		ps->a = NULL;
		ps->size = 0;
		ps->capacity = 0;
	}
}



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

//扩容
void SLCheckCapacity(SL* ps)
{
	if (ps->size == ps->capacity)//容量满了需要扩容的条件
	{
		int newcapacity = ps->capacity == 0 ? 4 : 2 * (ps->capacity);
		SLDataType* tmp = (SLDataType*)realloc(ps->a, sizeof(SLDataType) * newcapacity);
		if (tmp == NULL)
		{
			perror("CheckCapacity");//
			return;
		}
		ps->a = tmp;
		ps->capacity = newcapacity;
	}
}

//尾插
void SLPushBack(SL* ps, SLDataType x)
{
	SLCheckCapacity(ps);//扩容
	ps->a[ps->size] = x;
	ps->size++;
}

//头插
void SLPushFront(SL* ps, SLDataType x)
{
	SLCheckCapacity(ps);
	int end = ps->size - 1;
	while (end >= 0)//注意可以等于0 size为1 但是不能为负数会越界访问
	{
		ps->a[end+1] = ps->a[end];
		end--;
	}
	ps->a[0] = x;
	ps->size++;
}


//尾删
void SLPopBack(SL* ps)
{
	assert(ps->size);//本质问题就是害怕这个顺序表空了还在删除
	ps->size--;
}


//头删
void SLPopFront(SL* ps)
{
	assert(ps->size);
	int begin = 1;
	while (begin < ps->size)
	{
		ps->a[begin] = ps->a[begin + 1];
		begin++;
	}
	ps->size--;
}


//任意位置插入
void SLInsert(SL* ps, int pos, SLDataType x)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	SLCheckCapacity(ps);
	int begin = ps->size;
	while (begin >= pos - 1)
	{
		ps->a[begin] = ps->a[begin - 1];
		begin--;
	}
	ps->a[pos - 1] = x;
	ps->size++;
}


//任意位置删除
void SLErase(SL* ps, int pos)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	SLCheckCapacity(ps);
	int begin = pos - 1;
	while (begin < ps->size-1)
	{
		ps->a[begin] = ps->a[begin + 1];//会越界注意循环条件
		begin++;
	}
	ps->size--;
}



//元素查找
//找到了返回1
//没有找到返回-1
int SLFind(SL* ps, SLDataType x)
{
	assert(ps);
	int i = 0;
	for (i = 0; i < ps->size - 1; i++)
	{
		if (ps->a[i] == x)
		{
			return 1;
		}
	}
	return -1;
}

顺序表的问题及其思考

  • 中间/头部的插入删除,时间复杂度为O(N)
  • 增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗。
  • 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到200,我们再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间。

多文件调试小技巧

  • 连带错误❌
  • 退出码不为0❌
  • 不要每个函数都去查看,要找到具体错误地方再去一步步调试❌
  • 指针断言❌
  • free报错是 越界访问的问题---开了这么多访问多❌
  • 指向的释放位置错误----没开这么多以为有这么多❌
  • realloc报错是 越界访问的问题❌
  • 越界访问错误不一定会被检查出来,大概率会被检查出来而已❌(类比查酒驾)

最后为什么数组的下标从0开始?? 【指针和数组是相互融洽的】

思考:如何解决以上顺序表的问题?下章博客我们将介绍链表的结构来看看。

代码---------→【唐棣棣 (TSQXG) - Gitee.com】

联系---------→【邮箱:2784139418@qq.com】

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

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

相关文章

Vue项目创建与启动(2023超详细的图文教程)

目录 一、下载node.js 二、下载vue-cli与webpack插件 三、项目初始化(项目配置详细信息) 四、项目启动 五、Vue项目工程结构&#xff08;扩展知识&#xff09; 一、下载node.js 1.检测是否已经安装过node.js 打开控制台,输入 npm -v如果有会显示对应版本 如果没有会显示…

如何看待腾讯云双11活动3年轻量服务器突然涨价?

腾讯云双十一优惠活动提供的3轻量应用服务器涨价了&#xff0c;最初双11优惠活动3年轻量2核4G5M服务器从566.6元涨价到756元三年&#xff0c;3年轻量2核2G4M服务器从366.6元恢复到540元三年&#xff0c;大家抓紧吧&#xff0c;三年轻量已经库存已经不多了&#xff0c;看看隔壁阿…

基于Electron27+React18+ArcoDesign客户端后台管理EXE

基于electron27.xreact18搭建电脑端exe后台管理系统模板 electron-react-admin 基于electron27整合vite.jsreact18搭建桌面端后台管理程序解决方案。 前几天有分享electron27react18创建跨平台应用实践&#xff0c;大家感兴趣可以去看看。 https://blog.csdn.net/yanxinyun1990…

云安全-云原生基于容器漏洞的逃逸自动化手法(CDK check)

0x00 docker逃逸的方法种类 1、不安全的配置&#xff1a; 容器危险挂载&#xff08;挂载procfs&#xff0c;Scoket&#xff09; 特权模式启动的提权&#xff08;privileged&#xff09; 2、docker容器自身的漏洞 3、linux系统内核漏洞 这里参考Twiki的云安全博客&#xff0c;下…

快讯|2024 财年第一季度 Tubi 收益增长了 30%

2024 财年第一季度 Tubi 收益增长了 30%&#xff0c;月活跃用户达到了 7000 万 近日&#xff0c;在 2024 财年第一季度财务收益电话会议上&#xff0c;Fox 执行主席兼 CEO Lachlan Murdoch 对 Tubi 的增长表示赞赏&#xff1a;“Tubi 又多了一个令人羡慕的季度&#xff0c;收入…

3D模型格式转换工具HOOPS Exchange:如何将3D PDF转换为STEP格式?

3D CAD数据在制造、工程和设计等各个领域都扮演着重要的角色。为了促进不同软件应用程序之间的协作和互操作性&#xff0c;它通常以不同的格式进行交换。 HOOPS Exchange是一个强大的软件开发工具包&#xff0c;提供了处理和将3D CAD数据从一种格式转换为另一种格式的解决方案…

谭巍主任重点科普HPV病毒最怕的消毒液

HPV病毒&#xff0c;也称为人类乳头瘤病毒&#xff0c;是一种常见的性传播病毒。它感染人体皮肤和黏膜&#xff0c;导致各种疾病&#xff0c;包括尖锐湿疣、宫颈癌等。为了有效控制HPV病毒的传播&#xff0c;劲松中西医医院皮肤性病科主任谭巍认为了解消杀HPV病毒的消毒液是非常…

win10 + vs2017 + cmake3.17编译OSG-3.4.1

参考教程&#xff1a;https://blog.csdn.net/bailang_zhizun/article/details/120992244 1. 下载与解压 2. 修改configure 1&#xff09;Ungrouped Entries -- 》ACTUAL_3RDPARTY_DIR: 设置为&#xff1a; D:/Depend_3rd_party/OSG341/3rdParty 2&#xff09; Ungrouped E…

django如何连接sqlite数据库?

目录 一、SQLite数据库简介 二、Django连接SQLite数据库 1、配置数据库 2、创建数据库表 三、使用Django ORM操作SQLite数据库 1、定义模型 2、创建对象 3、查询对象 总结 本文将深入探讨如何在Django框架中连接和使用SQLite数据库。我们将介绍SQLite数据库的特点&…

设计模式第一课-单例模式(懒汉模式和饿汉模式)

单例模式 个人理解&#xff1a;单例模式实际就是通过类加载的方式获取到一个对象&#xff0c;并且保证这个对象在使用中只有一个&#xff0c;不允许再次被创建 一、懒汉模式 1、懒汉模式的基础写法 代码解释&#xff1a; &#xff08;1&#xff09;、编写LazySingleton类的…

HT5010 音频转换器工作原理

HT5010是一款低成B的立体声DA转换器&#xff0c;内部集成了内插滤波器、DA转换器和输出模拟滤波等电路。其可支持多种音频数字输入格式&#xff0c;支持24-bit字节。 该HT5010 基于一个多比特位的Δ-Σ调制器&#xff0c;将数字信号转化成两个声道的模拟信号并经过模拟滤波器滤…

Python 框架学习 Django篇 (八) 代码优化、数据库冗余处理

我们开发软件系统的时候&#xff0c;需要不断的反思我们代码里面是否有可以优化的地方。而优化的重点之一&#xff0c;就是把冗余的代码优化为可以复用的库。我们在前面编写了一些功能&#xff0c;但是其中存在很多冗余的方法 mgr/medicine.py mgr/k8s.py mgr/medicine.py 打开…

从科幻走向现实,LLM Agent 做到哪一步了?

LLM 洪流滚滚&#xff0c;AI 浪潮席卷全球&#xff0c;在这不断冲击行业认知的一年中&#xff0c;Agent 以冉冉新星之态引起开发者侧目。OpenAI 科学家 Andrej Karpathy 曾言“OpenAI 在大模型领域快人一步&#xff0c;但在 Agent 领域&#xff0c;却是和大家处在同一起跑线上。…

造物者:专注游戏音乐创造——奏响游戏世界乐章

游戏的世界宛如一幅壮丽的画卷&#xff0c;由华丽的图像和引人入胜的故事构成&#xff0c;然而&#xff0c;其完美之作还有一部分不可或缺的元素&#xff0c;那就是音乐。在这个数字时代&#xff0c;北京造物者科技有限公司&#xff08;以下简称造物者&#xff09;正崭露头角&a…

IntelliJ IDEA Services工具栏运行不显示端口问题解决

问题 如Spring Boot服务启动时&#xff0c;端口不显示。 解决 1、 清理所有缓存 2、 关闭IntelliJ IDEA后&#xff0c;到C:\Users\&#xff08;你自己的用户名&#xff09;\AppData\Local\Temp路径把所有文件都删除&#xff0c;因为时一个缓存&#xff0c;不影响其他软件…

RHCSA --- 第二天

一、查看IP地址 [rootlocalhost ~] ip ad 对应四张网卡 第一张&#xff1a;环回网卡&#xff08;用于测试&#xff09; 第二张&#xff08;主要&#xff09;&#xff1a;以太网网卡&#xff08;ens160&#xff09; 2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP>…

静态库的概念及影响

1、目标文件的生成&#xff1a; 由编译器针对源文件编译生成&#xff0c;生成的.o或者.so(动态库)或者.a(静态库)也可以看作是目标文件&#xff1b; 2、静态库的生成&#xff1a; 由给定的一堆目标文件以及链接选项&#xff0c;链接器可以生成两种库&#xff0c;分别是静态库…

双绞线(寻线仪,测线仪),光纤测试工具(红光笔,OTDR,光功率计)

网络测试方式&#xff1a; 根据测试中是否向被测网络注入测试流量&#xff0c;可以将网络测试方法分为主动测试和被动测试。 主动测试&#xff1a;利用测试工具有目的地主动问被测网络注入测试流量&#xff0c;根据测试流量的传送情况分析网络技术参数。优点是具备良好的灵活…

年底赶项目?买核心板送开发板!T113核心板2款芯片6种配置选择

全志T113系列芯片是目前比较受欢迎的国产入门级嵌入式工业芯片。米尔是基于T113芯片开发较早、提供配置最全的厂家&#xff0c;是目前唯一一家提供T113-S和T113-i两种芯片核心板的厂家。更好的消息是&#xff0c;T113-i的核心板兼容T113-S的核心板&#xff0c;同一个硬件设计&a…

pom.xml详解

我们在开发Java应用程序时&#xff0c;pom.xml文件是项目中的核心配置文件之一&#xff0c;它结合Maven实现对项目依赖的拉取&#xff0c;今天就详细了解一下pom.xml文件的配置 Maven是一种构建工具&#xff0c;它用于构建、管理和发布Java项目pom.xml文件包含了项目的所有重要…