顺序表(1)

news2024/12/23 17:00:42

目录

线性表

顺序表Sequential List

静态顺序表

动态顺序表 

主函数Test.c

test1

test2

test3

test4

头文件&函数声明SeqList.h

头文件

函数声明

函数实现SeqList.c

初始化SLInit

释放销毁SLDestroy

扩容SLCheckCapacity 

打印SLPrint 

尾插SLPushBack

头插SLPushFront

尾删SLPopBack

头删SLPopFront


今天介绍数据结构中的顺序表。

顺序表和链表都是最基础和最常见的实用的数据结构。

线性表

线性表(linear list)是n个具有相同特性的数据元素的有限序列。

线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串...
线性表在逻辑上是线性结构,也就说是连续的一条直线。(也就是说在逻辑上是依次存储的)但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组链式结构的形式存储。

顺序表Sequential List

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

顺序表简单来说就是一个数组,要求这个数组的空间是连续的,且存储的数据也必须是从头开始连续存储。

静态顺序表

静态顺序表:使用定长数组存储元素。

静态顺序表的长度是固定的。 虽然在不少的书籍和课本上都喜欢实用静态顺序表去讲解和测试。但是静态顺序表的空间是固定的,空间给大了,很浪费;空间给小了,不够实用。所以在我们后面的学习中,我们需要去学习动态的顺序表。它的实用性实践性更高,当然更加难。

动态顺序表 

动态顺序表:使用动态开辟的数组存储。

动态顺序表虽然可以规避一些空间浪费,但是还是会有一点点浪费。

实用动态内存开辟函数去开辟空间的时候,每次空间不够的时候都会扩容,每次扩容都会付出一定程度上的代价。所以每次扩容可以稍微多扩容一点点,减少扩容的频率。扩容是根据需求扩容,那我们最常用的扩容倍数就是:2倍 1.5倍但是不是一定要求是这些倍数。2倍数是一个相对合适的量,扩容的频率会越来越低,具体情况具体分析!

 

主函数Test.c

静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定大了,空
间开多了浪费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间
大小,所以下面我们实现动态顺序表。本章实现顺序表的头插 尾插 头删尾删等功能进行实现。

int main()
{
	SL ps;//创建一个结构题变量-传地址调用🆗-形参是实参的一份临时拷贝
	test1(&ps);//测试尾插 
	test2(&ps);//测试头插
	test3(&ps);//测试尾删
	test4(&ps);//测试头删
	return 0;
}

test1

#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);
}

test2

void test2(SL*ps)//测试头插
{
	SLInit(ps);
	SLPushFront(ps, 10);
	SLPushFront(ps, 20);
	SLPushFront(ps, 30);
	SLPushFront(ps, 40);
	SLPrint(ps);
	SLDestroy(ps);
}

test3

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);
}

test4

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);
}

头文件&函数声明SeqList.h

头文件

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

函数声明

  • SeqList声明 
//声明一个结构体
typedef int SLDataType;

typedef struct SeqList
{
	SLDataType* a;//如果后期a的类型改变就很方便
	int size;//有效数据
	int capacity;//空间容量
}SL;//SL是这个结构体的类型,用typedef定义更加方便了
  • SeqList初始化
//初始化
void SLInit(SL* ps);
  • SeqList释放&销毁 
//释放销毁
void SLDestroy(SL* ps);
  • SeqList展示
//展示
void SLPrint(SL* ps);
  •  尾插 头插 尾删 头删
void SLPushBack(SL* ps, SLDataType x);//尾插
void SLPushFront(SL* ps, SLDataType x);//头插
void SLPopBack(SL* ps);//尾删
void SLPopBack(SL* ps);//头删

函数实现SeqList.c

初始化SLInit

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

释放销毁SLDestroy

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

扩容SLCheckCapacity 

这个函数是我们自己封装,可以不用去函数声明,秘密。但是记住一定要在使用这个CheckCapacity 之前我们一定要声明或者放在使用之前。

 扩容就要用到我们在【动态内存管理】讲解的realloc函数了,扩容分为原地扩容异地扩容,忘记的小伙伴再复习一下哦,一定要熟悉【戳一戳】:C语言之动态内存管理篇(1)-CSDN博客

  • 原地扩容和异地扩容判断和最优写法
  • realloc函数存储空间起始位置是可以传NULL空指针的
  • realloc函数所需要开辟的空间一定要包含旧空间的大小
  • 异地扩容对之前的空间不需要手动free,而是操作系统已经帮助释放了原来旧的空间
//扩容
void SLCheckCapacity(SL* ps)
{
	if (ps->size == ps->capacity)//容量满了需要扩容的条件
	{
		int newcapacity = ps->capacity == 0 ? 4 : 2 * (ps->capacity);
		SLDataType* tmp = (SLDataType*)raelloc(ps->a, sizeof(SLDataType) * newcapacity);
		if (tmp == NULL)
		{
			perror("CheckCapacity");//
			return;
		}
		ps->a = tmp;
		ps->capacity = newcapacity;
	}
}

打印SLPrint 

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

尾插SLPushBack

  • 首先在size位置放值x
  • size往后移动++

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

头插SLPushFront

在顺序表的前面插入数据,是没有向前扩容和插入空间这种做法的。这段空间整体是连续的,地址是连续的,又要求数据是连续的。所以我们唯一可用的方法就是把数据往后挪动。当然我们可以用函数memcpy和memove来实现,这里我们就手动来写。如果不想挪动数据,只有一种方法就是使用链表。

  • 首先把size-1的位置移动到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++;
}

还想补充到的是:尽量别频繁的使用头插法,大量的使用不太行。 

尾删SLPopBack

尾删也是非常简单的,有人可能会说把要删除的值赋值为-1或者NULL。但是我们并不能确定顺序表元素的类型,万一类型改变,这里再去改变就不方便了。而且万一这个值本来就是-1。所以直接size--即可。后期插入等操作会把这个值给覆盖掉。

  • size-- 意味着着只有--之后的数值有效。意味着我们头尾插会把无效数据覆盖。
  • 无效数据不需要free 
  1. 第一动态内存是不支持分期free。
  2. 第二后续操作会覆盖无效数据,空间可以重复利用。
  3. 第三单独free,顺序表的空间就不连续了

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

 

规避过度头删


头删SLPopFront

  • 头插是从后向前挪动数据覆盖
  • 头删是从前向后挪动数据覆盖
  • 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--;
}

✔✔✔✔✔最后,感谢大家的阅读,若有错误和不足,欢迎指正。下章继续顺序表。

  • 结构体传址调用,形式参数是实际参数的一份临时拷贝
  • size永远指向所存储元素的下一个位置,顺序表是数组,下标从0开始。
  • realloc函数的注意点
  • assert的点

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

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

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

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

相关文章

“智能科技·链接未来”2024中国国际人工智能产品展览会·智博会

2024年中国国际人工智能产品展览会&#xff08;简称世亚智博会&#xff09;将于3月份在上海举办&#xff0c;6月份在北京举办。本届展会以“智能科技链接未来”为主题&#xff0c;将集中展示全球前沿的人工智能技术和应用&#xff0c;以及人工智能在各个领域的新成果。 本届展会…

Unity 粒子特效-第二集-烟雾特效

一、烟雾特效预览 二、制作原理 资源在绑定资源里&#xff0c;我得审核通过以后才能改成免费&#xff0c;如果着急要&#xff0c;可以评论区发一下&#xff0c;我给你们发网盘 1.这个是序列帧图片粒子特效一起组合而成的 这就是一个单独整个的烟雾动画 如下&#xff0c;是这…

Google Play上的Android广告软件应用程序积累了200万次安装

大家好&#xff0c;今天我们要聊一聊Google Play上的一个热门话题——Android广告软件应用程序。最近&#xff0c;一些恶意应用程序在Google Play上累积了200万次的安装量&#xff0c;给用户推送了讨厌的广告&#xff0c;同时又隐藏了它们在受感染设备上的存在。 根据Doctor W…

保护生产中 Node.js 应用程序安全的 15 项最佳实践

在后端开发方面&#xff0c;Node.js 是开发人员最喜欢的技术之一。它的受欢迎程度不断上升&#xff0c;现已成为在线攻击的主要目标之一。这就是为什么保护 Node.js 免受漏洞和威胁至关重要。 在本指南中&#xff0c;您将看到为生产设计安全 Node.js 应用程序架构的 15 种最佳…

安防视频监控平台EasyCVR前端解码与后端解码的区别介绍

视频监控平台/视频存储/视频分析平台EasyCVR基于云边端一体化管理&#xff0c;支持多类型设备、多协议方式接入&#xff0c;具体包括&#xff1a;国标GB28181协议、RTMP、RTSP/Onvif、海康Ehome&#xff0c;以及海康SDK、大华SDK、华为SDK、宇视SDK、乐橙SDK、萤石SDK等&#x…

linux中etc目录中常用文件

1.查看当前系统版本信息情况 cat /etc/redhat-release 版本是7.5 2.查看当前系统用户基本信息文件 cat /etc/passwd 3.查看当前系统主机名配置文件 cat /etc/hostname 可以更改主机名 方法一&#xff1a;临时修改方法&#xff0c;退出后重新连接即可生效 语…

云服务器安装Hive

文章目录 1. 安装Hive(最小化部署)2. MySQL安装3. Hive元数据配置到MySQL4. HiveServer2服务5. Metastore服务运行模式6. 编写脚本来管理hive的metastore/hiveserver2服务的启动和停止1.7 Hive常用命令 7. Hive参数配置方式7.1 Hive常见的几个属性配置 安装Hive的前提是先安装H…

通信原理板块——卷积码(原理、代数和几何表示、编码和解码)

微信公众号上线&#xff0c;搜索公众号小灰灰的FPGA,关注可获取相关源码&#xff0c;定期更新有关FPGA的项目以及开源项目源码&#xff0c;包括但不限于各类检测芯片驱动、低速接口驱动、高速接口驱动、数据信号处理、图像处理以及AXI总线等 1、卷积码定义 卷积码(convolution…

Python--快速入门一

Python--快速入门一 1.创建Python的项目 使用IDE&#xff1a;PyCharm 创建项目文件夹&#xff1a; 点击新建项目 将位置地址改为想要Python项目存放的位置 基础解释器选择最新版本的解释器&#xff08;此处为Python3.120 关闭创建main.py(此功能是自动一个初始文件&#x…

[量化投资-学习笔记004]Python+TDengine从零开始搭建量化分析平台-EMA均线

在之前的文章中用 Python 直接计算的 MA 均线&#xff0c;但面对 EMA 我认怂了。 PythonTDengine从零开始搭建量化分析平台-MA均线的多种实现方式 高数是我们在大学唯一挂过的科。这次直接使用 Pandas 库的 DataFrame.ewm 函数&#xff0c;便捷又省事。 并且用 Pandas 直接对之…

【ElasticSearch系列-02】ElasticSearch的概念和基本操作

ElasticSearch系列整体栏目 内容链接地址【一】ElasticSearch下载和安装https://zhenghuisheng.blog.csdn.net/article/details/129260827【二】ElasticSearch概念和基本操作https://blog.csdn.net/zhenghuishengq/article/details/134121631 深入理解ElasticSearch概念和基本操…

建筑模板-优质建筑模板厂家推荐

随着建筑行业的不断发展&#xff0c;优质的建筑模板成为了保障工程施工质量的重要一环。在众多建筑模板厂家中&#xff0c;广西贵港市能强优品木业凭借其优质的产品和良好的口碑赢得了业界的认可与信赖。 广西贵港市能强优品木业是一家专注于建筑模板生产的企业&#xff0c;公司…

#stm32整理(二)关于MDK的编译过程及文件类型全解

参考野火开发指南如有侵权即刻删除&#xff0c;只是为了学习交流使用 1、编译 1、编译过程简介 (1&#xff09;编译&#xff0c;MDK 软件使用的编译器是 armcc 和 armasm&#xff0c;它们根据每个 c/c 和汇编源文件编译 成对应的以“.o”为后缀名的对象文件 (Object Code&…

设计模式—创建型模式之工厂模式

设计模式—创建型模式之工厂模式 工厂模式&#xff08;Factory Pattern&#xff09;提供了一种创建对象的最佳方式。我们不必关心对象的创建细节&#xff0c;只需要根据不同情况获取不同产品即可。 简单工厂模式 比如我们有造车的工厂&#xff0c;来生产车&#xff0c;我们先…

b站so层sign算法

前言 大家好呀,欢迎来到我的博客!!! 本期我将带来b站so层sign算法实现 设备: pixel4 android10 下载地址: aHR0cHM6Ly93d3cud2FuZG91amlhLmNvbS9hcHBzLzI4MTI5MS9oaXN0b3J5X3Y2MTgwNTAw 版本: 6.18.0 工具: charles(抓包) socksdroid(流量转发) jadx(反编译dex) ida(反编…

中微CMS8S3680/69xx系列单片机

最近在使用中微CMS8S3680/69xx系列8位单片机来进行电源控制软件开发。 总体觉得这款单片机简单易用&#xff0c;特别是它的数字功能可以映射到任意脚&#xff0c;甚至包括程序的烧录脚&#xff0c;对于PCB布局特别灵活。另外它的存储器资源也是很丰富的&#xff0c;16K字节ROM…

实战 | SQL注入

一、资产搜集 我们都知道sql注入的传参有些是明文的&#xff0c;有些是经过编码或者加密的&#xff0c;所以我们搜索的时候不要仅限于inurl:.php?id1&#xff0c;可以额外的尝试搜搜1的base64编码值MQ&#xff0c;即可以搜索inurl:.php?idMQ&#xff0c;或者搜索1的md5加密值…

C代码的单元测试

C代码中集成gtest单元测试_gtest测试c语言_山河故人~的博客-CSDN博客 Linux安装gtest_gtest安装_山河故人~的博客-CSDN博客 一&#xff1a;安装gtest: 1. 安装gtest 采用源码安装的方式&#xff0c;需确保cmake已经安装。 git clone https://github.com/google/googletest …

网络安全(黑客)—小白自学路线

1.网络安全是什么 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 2.网络安全市场 一、是市场需求量高&#xff1b; 二、则是发展相对成熟…