纯c实现顺序表 数据结构大全

        我们已经知道数组是连续的内存地址,顺序表是由数组为基础的一种数据结构,拥有比数组更多的功能,在概念上属于线性结构,跟链表不同的是,顺序表在物理结构上也是线性的

        什么是数据结构? 当我们想要使⽤⼤量使⽤同⼀类型的数据时,通过手动定义⼤量的独立的变量对于程序来说,可读性非常差,我们可以借助数组这样的数据结构将⼤量的数据组织在⼀起,结构也可以理解为组织数据的方式。

        数组就是一种最为简单的数据结构,但是数组有着其局限性。

        求数组的⻓度,求数组的有效数据个数,随意变化数组的大小,向下标为数据有效个数的位置插⼊数据。假设数据量⾮常庞⼤,频繁的获取数组有效数据个数会影响程序执⾏效率。结论:最基础的数据结构能够提供的操作已经不能完全满⾜复杂算法实现。

        

        接着我带大家,来实现一个这样的数据结构,体会其特点

        我们先要定义一个结构体来存储数据,这里我们先默认存的数据是整形,(这个不同的需求很容易修改存储的数据类型),我们在这里定义名字为sl简化后面的代码

定义

struct dplist//动态 更常用
{
	int* a;
	int size;//有效数据个数;
	int capa;//顺序表当前大小
}sl;

初始化 

 然后是顺序表的初始化,正常操作

void begin(struct dplist* sl)//初始化
{
	sl->a = NULL;
	sl-> size = 0;
	sl-> capa = 0;
}

定义 

这里是定义,调用前面的begin函数

void sltest()//定义
{
	struct dplist sl;
	begin(&sl);
}

开辟内存 

然后是重要的检查空间跟有效数据个数,以此判断空间是否足够,是不是要多开辟的函数,后面的接口也会大量用到这个

这里采用的是两倍两倍的开辟新内存空间的方法

void checkcapa(struct dplist* sl)//检查空间是否足够 不够的话自动扩容
{
	if (sl->size == sl->capa)
	{
		int newcapa = sl->capa == 0 ? 4 : 2 * sl->capa;
		struct dplist* tmp = (struct dplist*)realloc(sl->a, newcapa * sizeof(struct dplist));
		if (tmp == NULL)
		{
			perror("fall");
			return ;
		}
		sl->a = tmp;
		sl->capa = newcapa;//因为本来sl->capa为0,所以定义newcapa
	}
}

销毁 

然后是数据结构经典的销毁函数,避免内存泄漏

void destroy(struct dplist* sl) //销毁空间,不要浪费
{
	if (sl->a)
		free(sl->a);
	sl->a = NULL;
	sl->capa = 0;
	sl->size = 0;
}

尾插 

然后是简单的尾插函数,记得把有效数据个数的size++

void pushback(struct dplist* sl,int x)//尾插
{
	//assert(sl)
	if (sl == NULL)//比assert柔和的方式
	{
		return;
	}

	//判断空间
	checkcapa(sl);//sl已经是指针了,直接传
	//插入数据 注意size的指向 要指向下一个,因为后面还要插
	sl->a[sl->size] = x;
	sl->size++;
}

头插 

然后是头插,把所有数据都向后移一位

void pushfront(struct dplist* sl,int x)//头插 历史数据后移
{
	if (sl == NULL)
	{
		return;
	}

	//判断空间
	checkcapa(sl);//直接调用函数

	//后移历史数据
	for (int i = sl->size; i > 0; i--)
	{
		sl->a[i] = sl->a[i - 1];
	}
	//头插
	sl->a[0] = x;
	sl->size++;
}

尾删 

然后是尾删接口,直接size--就可以,因为下一次size++的时候这个位置会赋值新的数了

void popback(struct dplist* sl)//尾删
{
	if (sl == NULL)
	{
		return;
	}

	//判断是否已经为空
	if (sl->size == 0)
	{
		return;
	}
	sl->size--;//在size的数据如果下次size到这里就会覆盖掉
}

头删 

然后是头删,数据集体向前移动来覆盖

void popfront(struct dplist* sl)//头删 数据直接向左移动来覆盖
{
	if (sl == NULL)
	{
		return;
	}

	//判断是否已经为空
	if (sl->size == 0)
	{
		return;
	}

	//向左移动
	for (int i = 0; i < sl->size ; i++)
	{
		sl->a[i] = sl->a[i + 1];
	}
}

 指定位置插入数据

然后是指定位置插入数据

一样是把指定的位置后面的数据向后移动就可以了

void slinsert(struct dplist* sl, int pos, int x)//指定位置插入数据 pos为下标
{
	if (sl == NULL)
	{
		return;
	}
	checkcapa(sl);

	//把pos及后面的数据向后挪
	for (int i = sl->size; i > pos; i--)
	{
		sl->a[i] = sl->a[i - 1];
	}

	//对pos加以限制,避免程序崩溃
	if (pos < 0 || pos > sl->size)
	{
		return;
	}
	//注意size的值 因为又插入了值
	sl->a[pos] = x;
	sl->size++;
}

 指定位置删除数据

与指定位置插入数据相对应的就是指定位置删除数据,让其后面的数据向前移动覆盖就可以了

void sldelete(struct dplist* sl, int pos)//指定位置删除数据 也是覆盖 往前移动
{
	//经典判断
	if (sl == NULL)
	{
		return;
	}

	//判断是否已经为空
	if (sl->size == 0)
	{
		return;
	}

	//对pos加以限制,避免程序崩溃
	if (pos < 0 || pos >= sl->size)
	{
		return;
	}

	//往前覆盖
	for (int i = pos; i < sl->size - 1; i++)
	{
		sl->a[i] = sl->a[i + 1];
	}

	sl->size--;//数据减少
}

 查找数据是否存在

然后是查找数据是否存在,简单遍历就可以了

int slfind(struct dplist* sl,int x)//查找数据是否存在 存在返回1 否则-1
{
	// 经典判断
	if (sl == NULL)
	{
		return;
	}

	for (int i = 0; i < sl->size; i++)
	{
		if (sl->a[i] == x)
		{
			return 1;
		}
	}
	return -1;
}

打印顺序表 

然后是打印函数,可以检查前面的操作正不正确

void slprint(struct dplist* sl)//打印顺序表 看操作是否正确
{
	for (int i = 0; i < sl->size; i++)
	{
		printf("%d ", sl->a[i]);
	}
	printf("\n");
}

最后给出完整代码

#define _CRT_SECURE_NO_WARNINGS

//顺序表  静态和动态
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "sep.h"

struct seplist//静态
{
	int aa[100];
	int size;//有效数据个数
};

struct dplist//动态 更常用
{
	int* a;
	int size;//有效数据个数;
	int capa;//顺序表当前大小
}sl;

void begin(struct dplist* sl)//初始化
{
	sl->a = NULL;
	sl-> size = 0;
	sl-> capa = 0;
}
void sltest()//定义
{
	struct dplist sl;
	begin(&sl);
}
void destroy(struct dplist* sl) //销毁空间,不要浪费
{
	if (sl->a)
		free(sl->a);
	sl->a = NULL;
	sl->capa = 0;
	sl->size = 0;
}
void checkcapa(struct dplist* sl)//检查空间是否足够 不够的话自动扩容
{
	if (sl->size == sl->capa)
	{
		int newcapa = sl->capa == 0 ? 4 : 2 * sl->capa;
		struct dplist* tmp = (struct dplist*)realloc(sl->a, newcapa * sizeof(struct dplist));
		if (tmp == NULL)
		{
			perror("fall");
			return ;
		}
		sl->a = tmp;
		sl->capa = newcapa;//因为本来sl->capa为0,所以定义newcapa
	}
}
void pushback(struct dplist* sl,int x)//尾插
{
	//assert(sl)
	if (sl == NULL)//比assert柔和的方式
	{
		return;
	}

	//判断空间
	checkcapa(sl);//sl已经是指针了,直接传
	//插入数据 注意size的指向 要指向下一个,因为后面还要插
	sl->a[sl->size] = x;
	sl->size++;
}
void pushfront(struct dplist* sl,int x)//头插 历史数据后移
{
	if (sl == NULL)
	{
		return;
	}

	//判断空间
	checkcapa(sl);//直接调用函数

	//后移历史数据
	for (int i = sl->size; i > 0; i--)
	{
		sl->a[i] = sl->a[i - 1];
	}
	//头插
	sl->a[0] = x;
	sl->size++;
}
void popback(struct dplist* sl)//尾删
{
	if (sl == NULL)
	{
		return;
	}

	//判断是否已经为空
	if (sl->size == 0)
	{
		return;
	}
	sl->size--;//在size的数据如果下次size到这里就会覆盖掉
}
void popfront(struct dplist* sl)//头删 数据直接向左移动来覆盖
{
	if (sl == NULL)
	{
		return;
	}

	//判断是否已经为空
	if (sl->size == 0)
	{
		return;
	}

	//向左移动
	for (int i = 0; i < sl->size ; i++)
	{
		sl->a[i] = sl->a[i + 1];
	}
}
void slinsert(struct dplist* sl, int pos, int x)//指定位置插入数据 pos为下标
{
	if (sl == NULL)
	{
		return;
	}
	checkcapa(sl);

	//把pos及后面的数据向后挪
	for (int i = sl->size; i > pos; i--)
	{
		sl->a[i] = sl->a[i - 1];
	}

	//对pos加以限制,避免程序崩溃
	if (pos < 0 || pos > sl->size)
	{
		return;
	}
	//注意size的值 因为又插入了值
	sl->a[pos] = x;
	sl->size++;
}
void sldelete(struct dplist* sl, int pos)//指定位置删除数据 也是覆盖 往前移动
{
	//经典判断
	if (sl == NULL)
	{
		return;
	}

	//判断是否已经为空
	if (sl->size == 0)
	{
		return;
	}

	//对pos加以限制,避免程序崩溃
	if (pos < 0 || pos >= sl->size)
	{
		return;
	}

	//往前覆盖
	for (int i = pos; i < sl->size - 1; i++)
	{
		sl->a[i] = sl->a[i + 1];
	}

	sl->size--;//数据减少
}
int slfind(struct dplist* sl,int x)//查找数据是否存在 存在返回1 否则-1
{
	// 经典判断
	if (sl == NULL)
	{
		return;
	}

	for (int i = 0; i < sl->size; i++)
	{
		if (sl->a[i] == x)
		{
			return 1;
		}
	}
	return -1;
}
void slprint(struct dplist* sl)//打印顺序表 看操作是否正确
{
	for (int i = 0; i < sl->size; i++)
	{
		printf("%d ", sl->a[i]);
	}
	printf("\n");
}
int main()
{

	return 0;
}

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

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

相关文章

【教3妹学编程-算法题】3006. 找出数组中的美丽下标 I

3妹&#xff1a;呜呜&#xff0c;烦死了&#xff0c; 脸上长了一个痘 2哥 : 不要在意这些细节嘛&#xff0c;不用管它&#xff0c;过两天自然不就好了。 3妹&#xff1a;切&#xff0c;你不懂&#xff0c;影响这两天的心情哇。 2哥 : 我看你是不急着找工作了啊&#xff0c; 工作…

AI-基于Langchain-Chatchat和chatglm3-6b部署私有本地知识库

目录 参考概述部署安装环境准备原理和流程图一键启动启动WebAPI 服务启动WebUI服务 Docker部署知识库管理常见问题本地知识库怎么微调&#xff1f;回答不准确 参考 手把手教你搭建本地知识库问答AI机器人 LangChain-Chatchat&#xff1a;基于LangChain和ChatGLM2-6B构建本地离…

【小笔记】时序数据分类算法最新小结

2024.1.15 最近基于时序数据训练分类算法&#xff0c;对其进行了一番了解&#xff0c;主要围绕以下几点&#xff1a; 时序数据算法有哪些细分类&#xff1f;时序数据分类算法经典模型&#xff1f;当下时序分类算法模型强baseline&#xff1f;有没有现成的工具&#xff1f; 1…

Python - 深夜数据结构与算法之 位运算

目录 一.引言 二.位运算简介 1.二进制与十进制 2.左/右移 3.位运算 4.异或 XOR 5.指定位置的位运算 6.实战要点 三.经典算法实战 1.Number-1-of-bits [191] 2.Power-Of-Two [231] 3.Reverse-2-Bits [190] 4.N-Queens [51] 四.总结 一.引言 通常情况下我们计数采…

RequestResponse

1.Request 请求 作用:使用Request对象来获取请求数据 1.Request获取请求数据的方法 2.通用方式获取请求参数 3.POST请求参数中文乱码解决 4.请求转发 概念: 一种在服务器内部的资源跳转方式 2.Response 响应 作用:使用response对象设置响应数据 1.Response设置响应数据功能 …

【Emgu.CV教程】5.3、几何变换之金字塔变换

这一段文字描述来自百度百科&#xff1a; 图像金字塔是图像多尺度表达的一种&#xff0c;是一种以多分辨率来解释图像的有效但概念简单的结构。一幅图像的图像金字塔是一系列以金字塔形状&#xff08;自下而上&#xff09;逐步降低&#xff0c;且来源于同一张原始图的图像分辨率…

OpenCV-25sobel算子(索贝尔算子)

前面所提到的滤波都是用于降噪的&#xff0c;去掉噪声&#xff0c;而算子是用来找边界&#xff0c;来识别图像的边缘。 一、概念 边缘是像素值发生跃迁的值&#xff0c;是图像的显著特点之一&#xff0c;在图像特征提取&#xff0c;对象检测&#xff0c;模式识别等方面都有重…

数据结构与算法教程,数据结构C语言版教程!(第四部分、字符串,数据结构中的串存储结构)二

第四部分、字符串&#xff0c;数据结构中的串存储结构 串存储结构&#xff0c;也就是存储字符串的数据结构。 很明显&#xff0c;字符串之间的逻辑关系也是“一对一”&#xff0c;用线性表的思维不难想出&#xff0c;串存储结构也有顺序存储和链式存储。 提到字符串&#xff…

Java 日志体系泣血总结

目录 一. 前言 二. Log 日志体系 2.1. 背景/发展史 2.2. 关系/依赖 2.2.1. JCL&#xff08;Jakarta Commons Logging&#xff09; 2.2.2. SLF4J 2.2.3. SLF4J 的适配 2.2.4. Spring 统一输出 三. 总结 一. 前言 本文的目的是搞清楚 Java 中各种日志 Log 之间是怎样的关…

spring boot mybatis-plus dynamic-datasource 配置文件 相关依赖环境配置

spring boot mybatis-plus dynamic-datasource 配置文件 相关依赖环境配置 ##yaml配置 server:port: 8866servlet:context-path: /yymtomcat:max-threads: 300connection-timeout: 57000max-connections: 500connection-timeout: 57000 spring:datasource:dynamic:primary: m…

MyBatis 查询数据库

一. MyBatis 框架的搭建 本篇所用sql 表: drop table if exists userinfo; create table userinfo(id int primary key auto_increment,username varchar(100) not null,password varchar(32) not null,photo varchar(500) default ,createtime timestamp default current_tim…

SpringBoot 全局异常统一处理:BindException(绑定异常)

概述 在Spring Boot应用中&#xff0c;数据绑定是一个至关重要的环节&#xff0c;它负责将HTTP请求中的参数映射到控制器方法的入参对象上。在这个过程中如果遇到任何问题&#xff0c;如参数缺失、类型不匹配或验证失败等&#xff0c;Spring MVC将会抛出一个org.springframewo…

Hive 数据迁移

一、需求 同步集团的数据到断直连环境。 二、思路 三、同步数据&#xff08;方案&#xff09; 1、环境&#xff1a;断直连模拟环境 2、操作机器&#xff1a;ETL 机器 XX.14.36.216 3、工作路径&#xff1a;cd /usr/local/fqlhadoop/hadoop/bin 4、执行命令&#xff1a; 命令…

python 元组的详细用法

当前版本&#xff1a; Python 3.8.4 文章目录如下 1. 介绍元组 2. 定义元组 3. 访问元组 4. 查询元组 1. 介绍元组 元组&#xff08;Tuple&#xff09;是一个有序的、不可变的数据序列。它可以包含各种类型的数据&#xff0c;例如数字、字符串、列表等。元组使用圆括号()来…

书生·浦语大模型实战营第四节课笔记及作业

XTuner 大模型单卡低成本微调实战 1 Finetune简介 大语言模型LLM是在海量的文本内容基础上&#xff0c;以无监督或半监督方式进行训练的。海量的文本内容赋予了大模型各种各样的行业知识。但是如果直接把大模型的知识用于生产实践&#xff0c;会发现回答不大满意。微调的目的…

【RL】(task1)绪论、马尔科夫过程、动态规划、DQN(更新中)

note 文章目录 note一、马尔科夫过程二、动态规划DQN算法时间安排Reference 一、马尔科夫过程 递归结构形式的贝尔曼方程计算给定状态下的预期回报&#xff0c;这样的方式使得用逐步迭代的方法就能逼近真实的状态/行动值。 有了Bellman equation就可以计算价值函数了马尔科夫过…

微服务架构设计核心理论:掌握微服务设计精髓

文章目录 一、微服务与服务治理1、概述2、Two Pizza原则和微服务团队3、主链路规划4、服务治理和微服务生命周期5、微服务架构的网络层搭建6、微服务架构的部署结构7、面试题 二、配置中心1、为什么要配置中心2、配置中心高可用思考 三、服务监控1、业务埋点的技术选型2、用户行…

Burp Suite如何拦截站点请求

Burp Suite是一款强大的Web渗透测试工具&#xff0c;可以用于拦截、修改和分析Web应用程序的请求和响应。要使用Burp Suite拦截站点请求有两个方案。我会倾向选用方案二&#xff0c;因为它不会影响本地电脑代理配置。 1. 方案一 安装Burp Suite&#xff1a;首先&#xff0c;您…

【C语言】ipoib驱动 - ipoib_cm_post_receive_nonsrq_rss函数

一、ipoib_cm_post_receive_nonsrq_rss函数定义 static int ipoib_cm_post_receive_nonsrq_rss(struct net_device *dev,struct ipoib_cm_rx *rx, int id) {struct ipoib_dev_priv *priv ipoib_priv(dev);struct ipoib_recv_ring *recv_ring priv->recv_ring rx->ind…

提升开发效率的google插件

在如今的软件开发领域&#xff0c;Google Chrome浏览器的开发者插件扮演着至关重要的角色&#xff0c;为开发人员提供了丰富的工具和功能&#xff0c;从而提高了开发效率。下面介绍几款强大的 Google 插件&#xff0c;它们在不同方面为开发者提供了便利&#xff0c;并能显著提升…
最新文章