C语言顺序表

news2024/9/20 18:53:08

文章目录

  • 前言
  • 线性表
  • 顺序表
    • 静态顺序表
    • 动态顺序表
  • 接口实现

前言

我们先补一下上篇博客落下的知识点:
首先说一下斐波那契的时间复杂度和空间复杂度:

long long Fac(size_t N)
{
    if(0 == N)
        return 1;
    return Fac(N-1)*N;
}

还是说一下size_t代表的类型是unsigned int,这里我们画个图来计算其时间复杂度:
在这里插入图片描述
如上图为斐波那契数列每一层递归的时间复杂度,我们需要把他们加在一起求出最后的时间复杂度。所以最终答案用大O法表达为为O(2^N)
而其空间复杂度是O(N)。
这里要说一下时间是累积的,一去不复返,而空间是可以重复利用的,通过上图我们可以看到Fib(N-1)之后创造的Fib(N-2)所用的空间其实是Fib(N)创造的,如下图所示:
在这里插入图片描述
而时间算完之后就流失了,不可重复利用,所以其时间复杂度为O(2^N),空间复杂度为
O(N)。

线性表

线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使
用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串…
线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,
线性表在物理上存储时,通常以数组和链式结构的形式存储。
(以上了解就好)
下图为顺序表和链表的模型。
在这里插入图片描述

顺序表

这里我们先说顺序表,其实顺序表大家了解就好,博主觉得数据结构最重要的地方是链表,顺序表当做对链表的铺垫就好,学好链表对后面学习栈和队列的帮助很大,但顺序表学好了貌似没多大作用(仅代表个人观点)。

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存
储。在数组上完成数据的增删查改。
而顺序表又分为静态顺序表和动态顺序表。

静态顺序表

#define N  10000
typedef int SLDataType;
typedef struct SeqList
{
	SLDataType a[N];
	int size; // 记录存储多少个有效数据
}SL;

这里再说一下,在学习数据结构的阶段,我们一般会对各种类型使用typedef来声明新的类型名。如上代码所示,我们对int重命名为SLDataType,将struct SeqList重命名为SL。还有就是我们在构建各个函数(接口)时,尽量用英文,这样显得比较正式,例如SeqList表示顺序表,不要写成struct shunxubiao(顺序表),这样在面试时会给面试官一个很不好的印象。

动态顺序表

本章我们主要说动态顺序表,代码案例也会以动态顺序表为主。

typedef int SLDataType;
typedef struct SeqList
{
	SLDataType* a;
	int size;       // 记录存储多少个有效数据
	int capacity;   // 空间容量大小 
}SL;

上述代码为动态顺序表的结构。
其与静态表的区别在于,静态表的空间由数组确定,而动态表的空间需要编写函数(接口来动态分配)。

接口实现

首先我们要构建一个动态顺序表:

typedef int SLDataType;
typedef struct SeqList
{
	SLDataType* a;
	int size;       // 记录存储多少个有效数据
	int capacity;   // 空间容量大小 
}SL;

之后对其初始化,将其的容量,有效数据个数置为0,指针指向空。
这里还要注意,传参一定要传地址,否则函数函数内部对其操作无效。

void SLInit(SL* ps)
{
	assert(ps);//assert断言

	ps->a = NULL;
	ps->size = 0;
	ps->capacity = 0;
}

这里在回忆一个知识点,assert断言,其作用是如果它的条件返回错误,则终止程序。
之后我们若要将数据放入表内,则需要构建一个插入数据的接口(函数)。

void SLPushBack(SL* ps, SLDataType x)
{
	assert(ps);

	if (ps->size == ps->capacity)//检查容量为0或顺序表是否是满数据
	{
		int newCapacity = (ps->capacity == 0 ? 4 : ps->capacity * 2);
		//这里首先判断其容量是否为0,若为0则先对其容量赋值,不为0则扩容
		SLDataType* tmp = (SLDataType*)realloc(ps->a, newCapacity * sizeof(SLDataType));//扩容
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(-1);
		}

		ps->a = tmp;//将扩容空间赋值给动态顺序表
		ps->capacity = newCapacity;//表内容量更新
	}

	ps->a[ps->size] = x;//将值赋给顺序表
	ps->size++;//表内有效数据加1
}

上述代码为将数据放入顺序表的函数(在本章函数和接口是一个意思)。这种方法其实又叫尾插法。
假如顺序表中某个数据无用,我们将其删除,也需要构建函数。

void SLPopBack(SL* ps)
{
	assert(ps);

	// 温柔的检查
	/*if (ps->size == 0)
	{
	return;
	}*/

	// 暴力的检查
	assert(ps->size > 0);

	//ps->a[ps->size - 1] = 0;
	ps->size--;
}

这里在对数据删减前要先判断表是否为空,判断其是否为空也有两种检查方法,一种是比较温柔的,即顺序表若为空则会结束函数,不会报错,而另一种则是稍微暴力的,用assert来判断若表为空表则会报错,并终止程序,这个判断方式根据个人喜好来设置,还有就是删减数据后不必使其变为0,也许要删减的数据本身就是0也说不准。
而我们也有可能想删除整个顺序表,那么就要销毁其空间:

void SLDestroy(SL* ps)
{
	assert(ps);

	if (ps->a)
	{
		free(ps->a);
		ps->a = NULL;
		ps->size = ps->capacity = 0;
	}
}

若其空间不为空那么则free掉,并使其指向NULL,其容量与有效数据个数归0。
我们可以看到,上述代码的命名都是以英文命名如销毁顺序表:SLDestroy,初始化顺序表:SLInit。
下面说一下头插法,代码如下

void SLPushFront(SL* ps,SLDataType x) 
{
	assert(ps);
	SLCheckCapacity(ps);//检查容量是否已满
	//挪动数据
	int end = ps->size - 1;
    while (end >= 0)
	{
		ps->a[end + 1] = ps->a[end]; 
		end--;
	}
	ps->a[0] = x;
	ps->size++;
}

这里SLCheckCapacity函数为检查顺序表是否还有容量,在本章博客未作实现(因为不是什么太难函数,在一个顺序表这里稍作了解就好。)end首先赋值为顺序表最后的元素下标,然后将顺序表元素一直后移,最后将要插入数据赋值给首元素。
再说一下中间插入:

void SLInsert(SL* ps, int pos,SLDataType x) {
	assert(ps);
	assert(pos >= 0);
	assert(pos <= ps->size);
	SLCheckcapacity(ps);
	int end = ps->size - 1;
	while (end >= pos)
	{
		ps->a[end + 1] = ps->a[end]; 
		end--;
	}
	ps->a[pos] = x; 
	ps->size++;
}

其原理与头插法相似。都是先让end为末尾元素下标,之后不断后移,将数据插入中间(这里的pos表示要将元素x插入的那个位置)。
最后为从中间删除:

void SLErase(SL* ps, int pos) {
	assert(ps);
	assert(pos >= 0);
	assert(pos < ps->size);
	//assert(ps->size > 0);//挪动数据覆盖
	int begin = pos + 1;
	while (begin < ps->size) {
		ps->a[begin - 1] = ps->a[begin];
		begin++;
	}
	ps->size--;
}

还是先判断顺序表是否为空,pos的值是不是有效值。
之后将begin赋值为要删除元素后一个元素的下标,之后不断的前移达到覆盖要删除元素的目的。
最后期待你的三连,若有错误欢迎私信指正。

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

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

相关文章

C#,数值计算——伽马微分(Gammadev)的计算方法与源程序

1 文本格式 using System; namespace Legalsoft.Truffer { public class Gammadev : Normaldev { private double alph { get; set; } private double oalph { get; set; } private double bet { get; set; } private double a1 { g…

2023年第十届中文自修杯汉字小达人比赛安排、常见问题和试卷题型

好消息&#xff01;面向上海市小学生的2023年第十届中文自修杯汉字小达人比赛开始了&#xff01; 这个活动从2014年开始举办第一届&#xff0c;迄今已经举办了九届&#xff0c;活动的影响力越来越大&#xff0c;深受上海市的小学生们欢迎。而且&#xff0c;有一些外省市的学校…

软件测评报告需要提交什么材料?

软件测评报告 软件测评/软件测试的经典定义是在规定条件下对程序进行操作&#xff0c;以发现错误&#xff0c;对软件质量进行评估。因为软件是由文档、数据以及程序组成的&#xff0c;所以软件测试的对象也就不仅仅是程序本身&#xff0c;而是包括软件形成过程的文档、数据以及…

Liunx系统下载安装Nginx下载安装

目录 版本介绍 Liunx下安装步骤 补充&#xff1a;Docker安装nginx 版本介绍 Nginx开源版 http://nginx.org/en/ 官方原始的Nginx版本 Nginx plus商业版 开箱即用&#xff0c;集成了大量功能 Open Resty https://openresty.org/cn/ OpenResty是一个基于Nginx与 Lua 的高性…

ModuleNotFoundError: No module named ‘transformers.modeling_bert‘解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

【LeetCode题目详解】第九章 动态规划part17 647. 回文子串 ● 516.最长回文子序列(day57补)

本文章代码以c为例&#xff01; 一、力扣第647题&#xff1a;回文子串 题目&#xff1a; 给你一个字符串 s &#xff0c;请你统计并返回这个字符串中 回文子串 的数目。 回文字符串 是正着读和倒过来读一样的字符串。 子字符串 是字符串中的由连续字符组成的一个序列。 具…

html5学习笔记21-css简略学习

CSS https://www.runoob.com/css/css-tutorial.html CSS (Cascading Style Sheets&#xff0c;层叠样式表&#xff09;&#xff0c;是一种用来为结构化文档&#xff08;如 HTML 文档或 XML 应用&#xff09;添加样式&#xff08;字体、间距和颜色等&#xff09;的计算机语言&a…

Ngnix封禁IP与ip段

Ngnix IP封禁以及实现自动封禁IP 小白教程&#xff0c;一看就会&#xff0c;一做就成。 1.创建文件&#xff08;被封禁的ip写里面&#xff09; 在ngnix的conf目录下创建一个blockip.conf文件&#xff0c;里面放需要封禁的IP与ip段&#xff0c;格式如下&#xff08;deny是禁用…

C++ 将off格式文件转换成ply格式存储

文章目录 引言off格式文件ply格式文件C标准库实现off转ply 引言 三维模型是计算机图形学中的一个重要概念&#xff0c;它是由一系列三维坐标点构成的点云或多边形网格。 OFF格式是一种用于描述三维模型的文件格式&#xff0c;它可以描述点云和多边形网格等不同类型的三维模型。…

抖音小程序开发教学系列(5)- 抖音小程序数据交互

第五章&#xff1a;抖音小程序数据交互 5.1 抖音小程序的网络请求5.1.1 抖音小程序的网络请求方式和API介绍5.1.2 抖音小程序的数据请求示例和错误处理方法 5.2 抖音小程序的数据缓存和本地存储5.2.1 抖音小程序的数据缓存机制和使用方法5.2.2 抖音小程序的本地存储和数据持久化…

【工作记录】MQTT介绍、安装部署及springboot集成@20230912

背景 近期公司可能会有物联网设备相关项目内容&#xff0c;提前对用到的mqtt协议做预研和初步使用。 最初接触到mqtt协议应该是早些年的即时通讯吧&#xff0c;现在已经是物联网设备最热门的协议了。 作为记录&#xff0c;也希望能帮助到需要的朋友。 MQTT介绍 《MQTT 协议规…

HAlcon例子

气泡思想 * This example shows the use of the operator dyn_threshold for * the segmentation of the raised dots of braille chharacters. * The operator dyn_threshold is especially usefull if the * background is inhomogeneously illuminated. In this example, *…

开源日报 0830 | 免费计算机科学自学路径:系统化教育与全球支持

ossu/computer-science Stars: 141.9k License: MIT 这个开源项目是一个自学计算机科学的免费路径。它提供了一套完整的在线教育材料&#xff0c;旨在为那些希望获得全面、扎实基础和良好习惯的人们提供支持。该课程按照本科计算机专业要求设计&#xff0c;并且选取了来自哈佛…

抖音小游戏运营攻略:运营能力、用户获取和用户留存

抖音小游戏运营攻略&#xff1a;运营能力、用户获取和用户留存 前言一&#xff0c;运营能力1.1 录屏分享1.2 分享设置 二&#xff0c;用户获取2.1 新游冷启计划2.2 游戏中心推广素材2.3 搜索关键词2.4 搜索结果图2.5 游戏特征2.6 剪映视频模板 三&#xff0c;用户留存3.1 游戏加…

Redis哨兵集群的介绍及搭建

Redis 是一款开源的、内存中的数据结构存储系统&#xff0c;它可以用作数据库、缓存和消息中间件。然而&#xff0c;作为一个单点服务&#xff0c;Redis 在面临硬件故障或者网络问题时可能会导致服务不可用。为了解决这个问题&#xff0c;Redis 提供了哨兵模式&#xff0c;一个…

【玩玩Vue】使用elementui页面布局和控制页面的滚动

原文作者&#xff1a;我辈李想 版权声明&#xff1a;文章原创&#xff0c;转载时请务必加上原文超链接、作者信息和本声明。 文章目录 前言一、页面布局二、页面滚动1.禁用body的滑动2.禁用el-aside的滚动3.启动el-main的滚动 前言 一、页面布局 这里布局使用vueelementui&…

如何对安卓设备执行免Root设置?免Root后如何远程控制?

使用AirDroid个人版的远程控制功能时&#xff0c;对被控的安卓设备执行免Root设置是比较常用的一种方式&#xff08;安卓7.0及以上系统的设备可以选择通过辅助权限&#xff08;无障碍&#xff09;控制安卓设备&#xff09; 如何执行免Root设置&#xff1f; 前提条件 1&#…

每日一博 - Stack OveFlow Arch In Reality

文章目录 概述猜测 &#xff1f;Truth 概述 Stack Overflow 是一个与程序相关的 IT 技术问答网站&#xff0c;其技术架构主要采用微软的技术栈&#xff0c;包括 C#、ASP.NET、SQL Server 等。此外&#xff0c;Stack Overflow 还使用了一些开源框架&#xff0c;例如 HAProxy、R…

SpringBoot-logback不同业务模块输出不同的日志文件

工作中有些业务模块日志输出比较频繁&#xff0c;影响其他业务模块问题排查&#xff0c;可以使用logback实现根据不同的业务输出到不同的日志文件 1、在resource下创建文件logback-spring.xml 2、在logback.xml中添加如下配置 <?xml version"1.0" encoding"…

GIS入门:GIS到底是什么,GIS的概念、构成结构、功能和应用

地理信息系统&#xff08;Geographic Information System, 简称GIS&#xff09; GIS从广义上讲&#xff0c;是一门集地理学与地图学以及遥感和计算机科学等众多学科于一体的综合性前沿交叉学科&#xff1b; 从狭义上说&#xff0c;它是在计算机硬、软件系统支持下&#xff0c;对…