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

news2024/9/24 21:21:45

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

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

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

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

        

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

        我们先要定义一个结构体来存储数据,这里我们先默认存的数据是整形,(这个不同的需求很容易修改存储的数据类型),我们在这里定义名字为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.coloradmin.cn/o/1387911.html

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

相关文章

交友脱单盲盒源码,纸条广场,支持单独抽取/连抽/同城

源码介绍 交友脱单盲盒源码&#xff0c;纸条广场&#xff0c;单独抽取/连抽/同城。 盲 盒交友脱单系统源码包含了学校、爱好、城市、地区、星座等 等信息&#xff0c;具有首页轮转广告和页面美化功能。 首页提供了两款 连抽和高质量底部连抽的选项&#xff0c;并且可以在后台…

❤ React报错问题分析

❤ React报错问题分析 ❤️ You passed a second argument to root.render(…) but it only accepts one argument. You passed a second argument to root.render(…) but it only accepts one argument. react-dom.development.js:86 Warning: You passed a second argumen…

transfomer中Decoder和Encoder的base_layer的源码实现

简介 Encoder和Decoder共同组成transfomer,分别对应图中左右浅绿色框内的部分. Encoder&#xff1a; 目的&#xff1a;将输入的特征图转换为一系列自注意力的输出。 工作原理&#xff1a;首先&#xff0c;通过卷积神经网络&#xff08;CNN&#xff09;提取输入图像的特征。然…

java如何修改windows计算机本地日期和时间?

本文教程&#xff0c;主要介绍&#xff0c;在java中如何修改windows计算机本地日期和时间。 目录 一、程序代码 二、运行结果 一、程序代码 package com;import java.io.IOException;/**** Roc-xb*/ public class ChangeSystemDate {public static void main(String[] args)…

MySQL面试题 | 10.精选MySQL面试题

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

WinForms TreeView 控件:保持节点选中状态即使失去焦点

WinForms TreeView 控件&#xff1a;保持节点选中状态即使失去焦点 在 Windows 窗体&#xff08;WinForms&#xff09;应用程序中&#xff0c;TreeView 控件是一种非常有用的界面元素&#xff0c;允许用户以层次结构的方式浏览信息。然而&#xff0c;一个常见的用户界面问题是&…

关于浮点数的四舍五入问题

最近有关注到&#xff0c;在C/C中&#xff0c;对于浮点数的四舍五入&#xff0c;与实际的有一些出入&#xff0c;我打算今天总结一下&#xff0c;并解释一下这是为啥&#xff0c; 好了&#xff0c;下面进入正题&#xff0c;都是干货哦&#xff0c;认真看完&#xff0c;留下你的…

非常好用的Mac清理工具CleanMyMac X 4.14.7 如何取消您对CleanMyMac X的年度订购

CleanMyMac X 4.14.7是Mac平台上的一款非常著名同时非常好用的Mac清理工具。全方位扫描您的Mac系统&#xff0c;让垃圾无处藏身&#xff0c;您只需要轻松单击2次鼠标左键即可清理数G的垃圾&#xff0c;就这么简单。瞬间提升您Mac速度。 CleanMyMac X 4.14.7下载地址&#xff1a…

Linux Mii management/mdio子系统分析之三 mii_bus注册、注销及其驱动开发流程

&#xff08;转载&#xff09;原文链接&#xff1a;https://blog.csdn.net/u014044624/article/details/123303174 本篇是mii management/mdio模块分析的第三篇文章&#xff0c;本章我们主要介绍mii-bus的注册与注销接口。在前面的介绍中也已经说过&#xff0c;我们可以将mii-b…

如何增加服务器的高并发

随着互联网的快速发展和普及&#xff0c;越来越多的应用程序需要支持高并发的请求处理。在这种情况下增加服务器的高并发能力成为了一个热门的话题。下面简单的介绍如果提高服务器的高并发能力。 负载均衡 是把请求分发到多个服务器上&#xff0c;来实现请求的平衡和分担。负…

compose 实验

cd /opt mkdir compose_nginx cd compose_nginx mkdir nginx cd nginx/ 此时顺便将nginx安装包拖进来 vim Dockerfile mkdir /opt/compose_nginx/wwwroot echo "<h1>this is test web</h1>" > /opt/compose_nginx/wwwroot/index.html docker netw…

如何配置mybatisplus基础环境?

1.在pom文件&#xff08;都加上吧&#xff0c;以防万一&#xff09; 2.若当初有mybatis的依赖&#xff0c;要删除 3.在Mapper接口加上"extends BaseMapper<实体类型>" 4.更改yml文件内容 别名扫描包&#xff1a;是指实体类型 5.添加"extends ServiceIm…

SQL语句详解四-DQL(数据查询语言-约束)

约束 概述&#xff1a;对表中的数据进行限定&#xff0c;保证数据的正确性&#xff0c;有效性和完整性。 约束分类 约束关键字约束意思primary key主键约束not null非空约束unique唯一约束foreign key外键约束 例子&#xff1a;sname varchar(40) not null, – 代表 sname 这…

【C语言】指针知识点笔记(2)

目录 一、野指针 二、assert断言 三、指针的使用和传址调用 四、数组名的理解 五、使用指针访问数组 一、野指针 二、assert断言 三、指针的使用和传址调用 四、数组名的理解 五、使用指针访问数组

Web 服务器渗透测试清单

Web 服务器渗透测试在三个重要类别下进行&#xff1a;身份、分析和报告漏洞&#xff0c;例如身份验证弱点、配置错误和协议关系漏洞。 1. “进行一系列有条不紊且可重复的测试”是测试网络服务器是否能够解决所有不同应用程序漏洞的最佳方法。 2.“收集尽可能多的信息”关于…

AtCoder Beginner Contest 336 G. 16 Integers(图计数 欧拉路径转欧拉回路 矩阵树定理 best定理)

题目 给16个非负整数&#xff0c;x[i∈(0,1)][j∈(0,1)][k∈(0,1)][l∈(0,1)] 求长为n3的01串的方案数&#xff0c;满足长度为4的ijkl&#xff08;2*2*2*2&#xff0c;16种情况&#xff09;串恰为x[i][j][k][l]个 答案对998244353取模 思路来源 https://www.cnblogs.com/tz…

多线程并发与并行

&#x1f4d1;前言 本文主要是【并发与并行】——并发与并行的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 &#x1f304;每日一句&…

03 顺序表

目录 线性表顺序表练习 线性表(Linear list)是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构&#xff0c;常见的线性表&#xff1a;顺序表、链表、栈、队列、字符串。。。 线性表在逻辑上时线性结构&#xff0c;是连续的一条直线。但在物理结…

【PostgreSQL内核学习(二十一)—— 执行器(InitPlan)】

执行器&#xff08;InitPlan&#xff09; 概述InitPlan 函数代码段解释ExecInitNode 函数 总结 声明&#xff1a;本文的部分内容参考了他人的文章。在编写过程中&#xff0c;我们尊重他人的知识产权和学术成果&#xff0c;力求遵循合理使用原则&#xff0c;并在适用的情况下注明…

力扣每日一练(24-1-16)

我一开始想到的是&#xff0c;如果数字相同则加一。 然而&#xff0c;对了一点点&#xff0c;而已。 高手的方法不是普通人在几分钟内能想得出来的&#xff0c;hh 继续补充&#xff1a; 如果数字不同则减一&#xff0c;如果计数到达了0&#xff0c;则更新数字&#xff0c;最…