数据结构——动态顺序表

news2025/3/12 23:09:00

数据结构的动态顺序表有以下几个操作:创建,销毁,初始化,增删查改和打印以及内存空间不够时的扩容

本文的宏定义:

#define SeqTypeData int

1.动态顺序表的创建

typedef struct SeqListInit{
	//动态顺序表的创建
	SeqTypeData* a;
	int size;//实际有效空间
	int capacity;//申请空间大小
}SL;

2.动态顺序表的销毁

void SeqListDestroy(SL* ps) {//顺序表销毁
	free(ps->a);
	ps->a = NULL;
	ps->capacity = ps->size = 0;
};

值得注意的是,ps->a要赋值NULL,避免野指针的出现。

3.动态顺序表的初始化

void SeqListInit(SL* ps){//顺序表初始化
	ps->a = NULL;
	ps->capacity = ps->size = 0;
};

4.动态顺序表的增加

插入时都要判断空间是否足够,是否需要扩容,以及ps->size要加一。

(1)头插

void SeqListPushFront(SL* ps, SeqTypeData x) {//顺序表头插
	SeqListCheckCapacity(ps);//判断是否需要扩容
	//挪动数据
	ps->size++;
	for (int i = 0; i < ps->size; i++) {
		ps->a[ps->size - i] = ps->a[ps->size - i - 1];
	}
	ps->a[0] = x;
}

头插也就是把数据都向后挪一位,再给第一位赋值。

(2)尾插

void SeqListPushBack(SL* ps, SeqTypeData x) {//顺序表尾插
	SeqListCheckCapacity(ps);//判断是否需要扩容
	ps->a[ps->size++] = x;
}

(3)任意位置插入

void SeqListInsert(SL* ps, int adr, SeqTypeData x)//adr为逻辑地址,等于数组下标加一
{
	if (adr > (ps->size + 1) || adr < 1)
	{
		printf("adr invalid\n");
		return;
	}
	SeqListCheckCapacity(ps);//判断是否需要扩容
	int end = ps->size ;
	while (end >= adr-1)
	{
		ps->a[end + 1] = ps->a[end];
		--end;
	}
	ps->a[adr-1] = x;
	ps->size++;
}

任意位置插入要记得判断插入位置的合法性,再将插入位置的数据向后移一位,再在插入位置赋值即可。

5.动态顺序表的删除

进行删除操作时,要判断表是否已经是空表,此时不可再删。删除成功时,ps->size减一。

(1)头删

void SeqListPopFront(SL* ps) {//顺序表头删
	if (ps->size == 0)
	{
		printf("顺序表为空,不可再删\n");
	}
	else
	{
		for (int i = 0; i < ps->size; i++) {
			ps->a[i] = ps->a[i+1];
		}
		ps->size--;
	}
}

(2)尾删


void SeqListPopBack(SL* ps) {//顺序表尾删
	if (ps->size--);
	else
	{
		printf("顺序表为空,不可再删\n");
	}
}

(3)任意位置删除

void SeqListErase(SL* ps, int adr) {
	if (ps->size == 0)
	{
		printf("顺序表为空,不可再删\n");
	}
	if (adr > (ps->size + 1))
	{
		printf("删除位置错误\n");
	}
	for (int i = adr; i < ps->size; i++) {
		ps->a[i-1] = ps->a[i];
	}
	ps->size--;
}

任意位置的删除也要检验删除位置的合法性。

6.动态顺序表的任意位置的修改

void SeqListCheck(SL* ps, int adr, SeqTypeData x) {//adr为逻辑地址,等于数组下标加一
	if(adr>(ps->size+1))
		printf("修改位置错误\n");
	else
	ps->a[adr - 1] = x;
}

任意位置的修改也要检验删除位置的合法性。

7.顺序表的打印

void SeqListPrint(SL ps) {//顺序表打印
	for (int i = 0; i < ps.size; i++)
	{
		printf("%d ", ps.a[i]);
	}
}

8.动态顺序表的扩容

void SeqListCheckCapacity(SL* ps) {//顺序表检查是否需要扩容
	if (ps->size == ps->capacity) {
		SeqTypeData newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		SeqTypeData* tem = (SeqTypeData*)realloc(ps->a, newcapacity * sizeof(SeqTypeData));
		if (tem == NULL) {
			printf("realloc fail\n");
			exit(-1);
		}
		ps->a = tem;
		ps->capacity = newcapacity;
	}
}

9.全部代码

#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"


#include <stdio.h>
#include <stdlib.h>
#include <assert.h>


void SeqListInit(SL* ps){//顺序表初始化
	ps->a = NULL;
	ps->capacity = ps->size = 0;
};

void SeqListDestroy(SL* ps) {//顺序表销毁
	free(ps->a);
	ps->a = NULL;
	ps->capacity = ps->size = 0;
};

void SeqListPrint(SL ps) {//顺序表打印
	for (int i = 0; i < ps.size; i++)
	{
		printf("%d ", ps.a[i]);
	}
	if (ps.size == 0)
		printf("顺序表为空");
	printf("\n");
}

//int SeqListCapacity(SL* ps) {//
//	return ps->capacity;
//}

void SeqListPushBack(SL* ps, SeqTypeData x) {//顺序表尾插
	SeqListCheckCapacity(ps);
	ps->a[ps->size++] = x;
}

void SeqListPushFront(SL* ps, SeqTypeData x) {//顺序表头插
	SeqListCheckCapacity(ps);
	//挪动数据
	ps->size++;
	for (int i = 0; i < ps->size; i++) {
		ps->a[ps->size - i] = ps->a[ps->size - i - 1];
	}
	ps->a[0] = x;
}

void SeqListCheckCapacity(SL* ps) {//顺序表检查是否需要扩容
	if (ps->size == ps->capacity) {
		SeqTypeData newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		SeqTypeData* tem = (SeqTypeData*)realloc(ps->a, newcapacity * sizeof(SeqTypeData));
		if (tem == NULL) {
			printf("realloc fail\n");
			exit(-1);
		}
		ps->a = tem;
		ps->capacity = newcapacity;
	}
}

void SeqListPopBack(SL* ps) {//顺序表尾删

	if (ps->size--);
	else
	{
		printf("顺序表为空,不可再删\n");
	}
}

void SeqListPopFront(SL* ps) {//顺序表头删
	if (ps->size == 0)
	{
		printf("顺序表为空,不可再删\n");
	}
	else
	{
		for (int i = 0; i < ps->size; i++) {
			ps->a[i] = ps->a[i+1];
		}
		ps->size--;
	}
}

void SeqListFind(SL ps, SeqTypeData x) {//顺序表查找
	/*int cnt;*/
	for (int i = 0; i < ps.size; i++) {
		if (ps.a[i] == x) {
			printf("%d", i + 1);//返回逻辑下标
			/*cnt++;*/
		}
	}
	/*if (cnt == 0)
		printf("没有这个数字");*/
}

void SeqListInsert(SL* ps, int adr, SeqTypeData x)//adr为逻辑地址,等于数组下标加一
{
	if (adr > (ps->size + 1) || adr < 1)
	{
		printf("adr invalid\n");
		return;
	}
	SeqListCheckCapacity(ps);
	int end = ps->size ;
	while (end >= adr-1)
	{
		ps->a[end + 1] = ps->a[end];
		--end;
	}
	ps->a[adr-1] = x;
	ps->size++;
}

void SeqListErase(SL* ps, int adr) {//adr为逻辑地址,等于数组下标加一
	if (ps->size == 0)
	{
		printf("顺序表为空,不可再删\n");
	}
	if (adr > (ps->size + 1))
	{
		printf("删除位置错误\n");
	}
	for (int i = adr; i < ps->size; i++) {
		ps->a[i-1] = ps->a[i];
	}
	ps->size--;
}

void SeqListCheck(SL* ps, int adr, SeqTypeData x) {
	if(adr>(ps->size+1))
		printf("修改位置错误\n");
	else
	ps->a[adr - 1] = x;
}

void menu()
{
	printf("请选择\n");
	printf("********1.头插  2.尾插********\n");
	printf("********3.头删  4.尾删********\n");
	printf("********5.随插  6.随删********\n");
	printf("********7.查找  8.打印********\n");
	printf("********9.修改  0.退出********\n");
	printf("请选择\n");
}


int main()
{
	int input;
	SL ps;
	SeqTypeData x;
	int adr;
	SeqListInit(&ps);
	do {
		menu();
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("请输入头插数字\n");
			scanf("%d", &x);
			SeqListPushFront(&ps, x);
			break;
		case 2:
			printf("请输入尾插数字\n");
			scanf("%d", &x);
			SeqListPushBack(&ps, x);
			break;
		case 3:
			SeqListPopFront(&ps);
			break;
		case 4:
			SeqListPopBack(&ps);
			break;
		case 5:
			printf("请输入插入位置和数字\n");
			scanf("%d%d", &adr, &x);
			SeqListInsert(&ps, adr, x);
			break;
		case 6:
			printf("请输入删除位置\n");
			scanf("%d", &adr);
			SeqListErase(&ps, adr);
			break;
		case 7:
			printf("请输入查找数字\n");
			scanf("%d", &x);
			SeqListFind(ps, x);
			break;
		case 8:
			SeqListPrint(ps);
			break;
		case 9:
			printf("请输入修改位置和数字\n");
			scanf("%d%d", &adr, &x);
			SeqListCheck(&ps, adr, x);
			break;
		case 0:
			printf("正在退出中");
			break;
		}
	} while (input);
	return 0;
}

10.效果展示

由于图片大小问题,只展示了部分功能。

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

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

相关文章

双指针算法_复写零

题目&#xff1a; 给一个固定长度的数组arr&#xff0c;将数组中出现的每一个0都复写一遍&#xff0c;并且将其余元素都往右移动 且不要再超过数组长度的位置写入元素&#xff0c;在数组上直接修改 示例&#xff1a; 双数组模拟操作&#xff1a; 从示例来看&#xff0c;因为…

【状态压缩DP】第十三届蓝桥杯省赛C++ B组《积木画》(C++)

【题目描述】 小明最近迷上了积木画&#xff0c;有这么两种类型的积木&#xff0c;分别为 I 型&#xff08;大小为 2 个单位面积&#xff09;和 L 型&#xff08;大小为 3 个单位面积&#xff09;&#xff1a; 同时&#xff0c;小明有一块面积大小为 2N 的画布&#xff0c;画布…

模板进阶:非类型模板参数,特化

一、非类型模板参数 非类型模板参数&#xff0c;就是用一个常量作为 类/函数 的模板参数&#xff0c;在 类/函数 中可以被当成常量使用。 template<class T, size_t N>// N 为一个非类型模板参数 class Stack { public:Stack(){_a new T[N];} protected:T* _a; };int m…

腾讯云服务器入站规则端口开放使用指南(CentOS系统)

第一步&#xff1a;开放安全组入站规则 来源处0.0.0.0/0是对IPv4开发&#xff0c;::/0是对IPv6开放&#xff1b; 协议端口按照提示填写即可。云服务器防火墙开放 第三步&#xff1a;本地防火墙开放 sudo firewall-cmd --zonepublic --add-port你的端口号/tcp --perma…

RTT——stm32f103的can总线通信

1.创建工程 2.配置时钟和引脚 引脚配置使能CAN 时钟配置&#xff0c;采用外部高速时钟 生成MDK工程后复制相关初始化函数到RTT-studio中 将void HAL_CAN_MspInit(CAN_HandleTypeDef* canHandle)函数复制至broad.c文件中 将时钟配置函数复制到drv_clk.c中&#xff0c;只复制函数…

Java8中Stream流API最佳实践Lambda表达式使用示例

文章目录 一、创建流二、中间操作和收集操作筛选 filter去重distinct截取跳过映射合并多个流是否匹配任一元素&#xff1a;anyMatch是否匹配所有元素&#xff1a;allMatch是否未匹配所有元素&#xff1a;noneMatch获取任一元素findAny获取第一个元素findFirst归约数值流的使用中…

Linux下的多线程编程:原理、工具及应用(2)

&#x1f3ac;慕斯主页&#xff1a;修仙—别有洞天 ♈️今日夜电波&#xff1a;Flower of Life—陽花 0:34━━━━━━️&#x1f49f;──────── 4:46 &#x1f504; ◀️ ⏸ ▶️ ☰ …

【C++ RB树】

文章目录 红黑树红黑树的概念红黑树的性质红黑树节点的定义红黑树的插入代码实现总结 红黑树 AVL树是一颗绝对平衡的二叉搜索树&#xff0c;要求每个节点的左右高度差的绝对值不超过1&#xff0c;这样保证查询时的高效时间复杂度O( l o g 2 N ) log_2 N) log2​N)&#xff0c;…

钉钉小程序 - - - - - 如何通过一个链接打开小程序内的指定页面

方式1 钉钉小程序 scheme dingtalk://dingtalkclient/action/open_mini_app?miniAppId123&pagepages%2Findex%2Findex%3Fx%3D%25E4%25B8%25AD%25E6%2596%2587 方式2 https://applink.dingtalk.com/action/open_mini_app?type2&miniAppIdminiAppId&corpIdcorpId&…

MySQL行锁核心知识介绍

MySQL的行锁是数据库中用于控制并发访问的一种机制。它允许在数据库的行级别上实现锁定&#xff0c;从而允许多个事务同时修改不同行的数据&#xff0c;而不会相互干扰。这种锁机制可以提高数据库的并发性能&#xff0c;减少锁争用&#xff0c;提高事务的吞吐量。在本教程中&am…

一周学会Django5 Python Web开发-Jinja3模版引擎-安装与配置

锋哥原创的Python Web开发 Django5视频教程&#xff1a; 2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~共计35条视频&#xff0c;包括&#xff1a;2024版 Django5 Python we…

.Net Core 中间件验签

文章目录 为什么是用中间件而不是筛选器&#xff1f;代码实现技术要点context.Request.EnableBuffering()指针问题 小结 为什么是用中间件而不是筛选器&#xff1f; 为什么要用中间件验签&#xff0c;而不是筛选器去验签? 1、根据上图我们可以看到&#xff0c;中间件在筛选器之…

Selenium控制已运行的Edge和Chrome浏览器——在线控制 | 人机交互(详细启动步骤和bug记录)

文章目录 前期准备1. 浏览器开启远程控制指令&#xff08;1&#xff09;Edge&#xff08;2&#xff09;Chrome 2. 执行python代码&#xff08;1&#xff09;先启动浏览器后执行代码&#xff08;2&#xff09;通过代码启动浏览器&#xff08;3&#xff09;Bug问题记录1&#xff…

前端和后端权限控制【笔记】

前端权限设置【笔记】 前言版权推荐前端权限设置需求效果实现资源 后端权限控制1.给所有前端请求都携带token2.添加拦截器3.配置到WebMvcConfiguration4.更多的权限验证 最后 前言 2024-3-15 18:27:26 以下内容源自《【笔记】》 仅供学习交流使用 版权 禁止其他平台发布时删…

鸿蒙Harmony应用开发—ArkTS声明式开发(容器组件:FormLink)

提供静态卡片交互组件&#xff0c;用于静态卡片内部和提供方应用间的交互&#xff0c;当前支持router、message和call三种类型的事件。 说明&#xff1a; 该组件从API Version 10开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 该组件仅可…

Gitlab CI/CD 自动化打包部署前端(vue)项目

一、虚拟机安装 1.vmware下载 2.镜像下载 3.Ubuntu 4.新建虚拟机 一直点下一步&#xff0c;直到点击完成。 5.分配镜像 二、Gitlab CI/CD 自动化部署项目 1.配置GitLab CI/CD&#xff1a; A.在你的Vue.js项目中&#xff0c;创建一个名为.gitlab-ci.yml的文件&#xff0…

Javaweb--CSS

一&#xff1a;概述 CSS &#xff08;Cascading Style Sheet&#xff08;层叠样式表&#xff09;&#xff09;是一门语言&#xff0c;用于控制网页表现。 W3C标准规定了网页是由以下组成&#xff1a; 结构&#xff1a;HTML 表现&#xff1a;CSS 行为&#xff1a;JavaScrip…

【计算机网络】UDP/TCP 协议

TCP 协议 一、传输层1. 再谈端口号2. 端口号范围划分3. 进程和端口号4. netstat5. pidof 二、UDP 协议1. UDP 协议端格式(报文)2. UDP 的特点3. 面向数据报4. UDP 的缓冲区 三、TCP 协议1. 认识 TCP2. TCP 协议段格式&#xff08;1&#xff09;4 位首部长度&#xff08;2&#…

(三)丶RabbitMQ的四种类型交换机

前言&#xff1a;四大交换机工作原理及实战应用 1.交换机的概念 交换机可以理解成具有路由表的路由程序&#xff0c;仅此而已。每个消息都有一个称为路由键&#xff08;routing key&#xff09;的属性&#xff0c;就是一个简单的字符串。最新版本的RabbitMQ有四种交换机类型&a…

用真值表、逻辑表达式和卡诺图来表示数字电路中的逻辑关系

真值表&#xff08;Truth Table&#xff09; 真值表是一种直观的方式&#xff0c;通过列出所有可能的输入值及其对应的输出值来表示逻辑关系。以下是使用真值表表示逻辑关系的步骤&#xff1a; 1. 确定输入变量&#xff1a;列出数字电路中所有的输入变量。 2. 定…