【数据结构】顺序表的实现

news2025/1/15 7:31:26

文章目录

    • **线性表(linear):**
    • **顺序表**
      • **下列是需要实现的接口(Seqlist.h)**
        • **顺序表的初始化**
        • **顺序表的插入数据**
        • **顺序表的扩容(为插入数据提供保障)**
        • **顺序表的尾插**
        • **顺序表的头插**
        • **顺序表的删除数据**
        • **顺序表的尾删**
        • **顺序表的头删**
        • **查找指定位置的下标**
        • **顺序表的任意位置插入(pos是下标)**
        • **顺序表的判空**
        • **顺序表的打印**
        • **顺序表的销毁**

请添加图片描述

线性表(linear):

线性表(linear list):n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使 用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串…

线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的, 线性表在物理上存储时,通常以数组和链式结构的形式存储

顺序表

顺序表属于线性表的其中一种。顺序表在逻辑、物理结构上是连续顺序表底层逻辑一般是数组。(物理结构上连续是指一段物理地址连续的存储单元依次存储数据元素的结构)

顺序表分为两种:静态顺序表和动态顺序表,每一种都属于它自己的价值,在实际中。一般使用动态顺序表做的,比如我们经常用的通讯录(因为静态顺序表只适合事前知道需要多少内存的情况下,不然会出现申请多少内存问题)

请添加图片描述

当我们有所了解顺序表的结构,接下来是实现顺序表的相关接口,比如增删查改

实现的过程中,创建两个源文件和一个头文件,分别为实现顺序表功能和测试顺序表功能,头文件一般用于声明函数(将在文章结尾处,贴出test.c文件)

注意:头文件只负责声明,在源文件中就是预编译阶段将多个头文件整合到一起

小技巧:

  • 在循环中如果不知道结束条件的话,带入临界值去尝试是否符合条件
  • 每一个接口都需要断言下传过来的指针是否为空指针->判断是否是一个有效的结构体变量

下列是需要实现的接口(Seqlist.h)

请添加图片描述

顺序表的初始化

void SLInit(SL* phead)
{
	assert(phead);
	phead->a = NULL;
	phead->size = phead->capacity = 0;
}

在实现该接口时:

  • 这里空间上可以给数值
顺序表的插入数据
  • 插入分为三类:头插 尾插 任意位置插入(其中任意位置插入,在实现查找功能先放着)
  • **前期准备:**在插入数据过程中,这里空间上可以给数值。当空间不足时,需向系统申请空间
顺序表的扩容(为插入数据提供保障)
void SLChekckCapacity(SL* phead)
{
	assert(phead);
	if (phead->size == phead->capacity)
	{
		int newcapacity =phead->capacity==0?4:phead->capacity * 2;
		SLDataType* pphead = (SLDataType*)realloc(phead->a, sizeof(SLDataType) * newcapacity);
		if (pphead == NULL)
		{
			perror("realloc fail!!");
			return 1;
		}
		phead->a = pphead;
		phead->capacity = newcapacity;
	}
}

在实现该接口时:

  • 为存储数据而申请的一块空间,那么需要交给这个数据类型去维护
  • Capacity代表当前空间大小,Size代表当前有效数据,当有效数据充满了当前空间大小就需要申请内存空间(这里需要实现多次插入函数,这里单独实现SLChekckCapacity)
  • newcapacity是防止在扩容时,capacity为空(零乘任何数为零),申请空间大小错误
  • 最好不要phead直接接收扩容的地址,防止扩容(第二种情况)失败导致找不到之前空间地址
  • 开辟以字符类型来维修开辟的空间,需要为‘\0‘开辟一个空间
顺序表的尾插
void SLPlusBack(SL*phead, SLDataType x)
{
	assert(phead);
    if(phead->size == phead->capacity)
	SLChekckCapacity(phead);
	phead->a[phead->size] = x;
	phead->size++;
}

在实现该接口时:

  • 通过利用下标赋值
顺序表的头插
void SLPlusFront(SL* phead, SLDataType x)
{
	assert(phead);
    if(phead->size == phead->capacity)
	SLChekckCapacity(phead);
	for (int i = phead->size; i >0; i--)
	{
		phead->a[i] = phead->a[i - 1];
	}
	phead->a[0] = x;
	phead->size++;
}

在实现该接口时:

  • 原数据整体向后移动,头会多出个数据将其覆盖,实现头插的效果
  • 循环条件怎么设置,数据向后移动(覆盖并数值不丢失),如果是从前先后覆盖,好比1 2 3 4 5 变成 1 1 2 3 4 5,将i的值赋值给i+1,i从首元素下标开始并且覆盖方式nums[i+1]=nums[i]
顺序表的删除数据
  • 删除分为三类:头删 尾删 任意位置删除(其中任意位置删除,在实现查找功能先放着)
  • 删除数据之前,要判断顺序表是否是为空–>这里有断言去判断
顺序表的尾删
void SLPopBack(SL* phead)
{
	assert(phead);
	assert(phead->a);
	phead->size--;
}

在实现该接口时:

  • 不是将数据设为0就是删除数据。正确的做法,通过size(有效数据个数)个数控制
  • 顺序表不访问size外的无效数据,那么从某种意义上是删除了数据(班里有位同学退学,班里人数少一位,同学还是存在,只是座位没有它)
  • 空间是不浪费的,尾插数据时,可能下次还是用到那个空间
顺序表的头删
void SLPopFront(SL* phead)
{
	assert(phead);
	assert(phead->a);
	for (int i = 0; i < phead->size-1; i++)
	{
		phead->a[i] = phead->a[i + 1];
	}
	phead->size--;
}

在实现该接口时:

  • 数组删除数据的方式就是覆盖数据,那么只需要从后向前覆盖,首元素将被覆盖或者被删除
  • 循环条件怎么设置,如果是从后先前覆盖,好比1 2 3 4 5变成 2 3 4 5 5,将i+1的值赋值给i,i从首元素下标开始并且覆盖方式nums[i]=nums[i+1];
查找指定位置的下标

为了实现对某个位置进行修改,需要利用到顺序表中查找接口

int SLFind(SL* phead, SLDataType x)
{
	assert(phead);
	assert(phead->a);
	for (int i = 0; i < phead->size; i++)
	{
		if (phead->a[i] == x)
            return i;
	}
	return -1;
}

在实现该接口时:

  • 遍历顺序表,如果满足条件返回当前位置的下标,没有找到返回一个负数表示找不到
  • 开始实现任意位置上的修改(任意是相对的,需要对pos进行限制)
  • 顺序表的任意位置插入(pos是下标)
void SLInsert(SL* phead, int pos, SLDataType x)
{
	assert(phead);

	assert(0 <= pos && pos <= phead->size);
		SLChekckCapacity(phead);
		for (int i = phead->size; i>pos;i--)
		{
			phead->a[i] = phead->a[i-1];//pos+1 pos-->注意覆盖的顺序,向后就是后面开始
		}
		phead->a[pos] = x;	
		phead->size++;
}

在实现该接口时:

  • 需要对pos设置范围
  • 以下标pos为界,pos之后的数据向后移动(跟头插类似,主要是在循环条件略显差异)
  • 不要忘记上面的小技巧,任何得到正确的循环条件
顺序表的任意位置插入(pos是下标)
void SLErase(SL* phead, int pos)
{
	assert(phead);
	assert(pos >= 0 && pos < phead->size);
	for (int i = pos;i<phead->size-1;i++)
	{
		phead->a[i] = phead->a[i + 1];
	}
	phead->size--;
}

在实现该接口时:

  • 需要对pos设置范围
  • 以下标pos为界,pos之后的数据向前移动(跟头删是类似的,主要是在循环条件略显差异)

顺序表实现任意位置插入、插入跟头尾插删是类型的。但是上面的操作相当于基础,也是需要学习的(只有学会1+1,才能学会7+8)

顺序表的判空
bool SLEmpty(SL*phead)
{
	assert(phead);
    assert(phead->a);
    return phead->size==0;
}
顺序表的打印
void SLPrintData(SL*phead)
{
	assert(phead);
	for (int i = 0; i < phead->size; i++)
	{
		printf("%d ", phead->a[i]);
	}
	printf("\n");
}
顺序表的销毁
void SLDestory(SL*phead)
{
	assert(phead);
	if (phead->a)
	{
		free(phead->a);//free该前顺序表的动态开辟的空间
		phead->a = NULL;
		phead->size = phead->capacity = 0;
	}	
}

补充:贴出test.c文件

test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "Seqlist.h"

void test4()
{
	SL phead;
	SLInit(&phead);
	SLPlusBack(&phead, 3);
	SLPlusBack(&phead, 4);
	SLPlusBack(&phead, 5);
	SLPrintData(&phead);
	SLInsert(&phead,1, 100);//这个pos是下标,pos之后插入
	SLPrintData(&phead);
	SLErase(&phead,1);
	SLPrintData(&phead);
	int pos = SLFind(&phead, 3);//可以找到当前下标
//实现定位
	SLDestory(&phead);
}
int main()
{
	test4();
	return 0;
}

只学习一种数据结构不能应付在实际中的许多问题,并且顺序表也有自身的优点和缺点->在链表部分,会总结之间的差异

顺序表的优点:

  • 支持下标随机访问(时间复杂度O(1))

顺序表的缺点:

  • 在实现插入和删除操作过程中,通过大量的移动数据,效率较低
  • 空间不足需要扩容并且需要付出一定的代价,可能存在空间浪费
  • 只适合尾插尾删

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

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

相关文章

下载API文档

在线看&#xff1a;Overview (Java SE 17 & JDK 17) 离线下载&#xff1a;Java Development Kit 17 Documentation

【Sql】MVCC有关问题,以及锁,日志和主从复制原理

目录 MVCC 解决什么问题? 实现原理 隐式字段 undo log Read View(读视图) InnoDB 对 MVCC 的实现 锁 分类 锁升级&#xff1f; InnoDB 的行锁&#xff1f; 死锁避免&#xff1f; 乐观锁和悲观锁 日志 主从复制原理 主从复制的作用 MySQL主从复制解决的问题 涉…

模型量化(二)—— 训练后量化PTQ(全代码)

训练后量化&#xff08;Post-training Quantization&#xff0c;PTQ&#xff09;是一种常见的模型量化技术&#xff0c;它在模型训练完成之后应用&#xff0c;旨在减少模型的大小和提高推理速度&#xff0c;同时尽量保持模型的性能。训练后量化对于部署到资源受限的设备上&…

【阿里云系列】-利用yaml文件部署NacosXxl-job到ACK

背景介绍 随着容器化的技术成熟落地&#xff0c;拥抱各种成熟的容器化集群平台是加速我们落地的必然之路&#xff0c;目前国内以阿里云、华为云、腾讯云为平台的供应商为主&#xff0c;国外则以AWS&#xff0c;Azure为主&#xff0c;让我们借助平台已有的优势进行快速落地提高…

指针【理论知识速成】(3)

一.指针的使用和传值调用&#xff1a; 在了解指针的传址调用前&#xff0c;先来额外了解一下 “传值调用” 1.传值调用&#xff1a; 对于来看这个帖子的你相信代码展示胜过千言万语 #include <stdio.h> #include<assert.h> int convert(int a, int b) {int c 0…

log4j2.xml介绍和使用

log4j2.xml是什么 log4j2.xml 是用于配置 Apache Log4j 2 的 XML 格式配置文件。Log4j 2 是一个用于 Java 应用的流行日志框架&#xff0c;提供灵活的日志管理和配置。在 log4j2.xml 文件中&#xff0c;可以配置日志记录的格式、级别、目的地等。 下面是一些主要节点和属性的…

内容管理平台原来对企业这么重要,看完收藏!

“内容为王”&#xff0c;这是当今数字化时代的一个重要真理。不论是创业新贵、还是行业巨头&#xff0c;纷纷开始深入理解和应用内容管理平台&#xff08;Content Management System&#xff0c;简称CMS&#xff09;&#xff0c;以便更好的管理其大量的内容和信息。 那么&…

网络安全从业人员何去何从

从2024年1月1日开始到今天&#xff0c;基本没有真正放下自己休息过一天。可能很多人会说是卷&#xff0c;其实真正的原因是压力。不仅仅是生活压力还有行业压力。 今年这个行业让很多人开始感到了迷茫&#xff0c;不仅是股市的低迷&#xff0c;更多的来自于各大公司不断的因为…

什么是架构?架构设计原则是哪些?什么是设计模式?设计模式有哪些?

什么是架构?架构设计原则是哪些?什么是设计模式?设计模式有哪些? 架构的本质 架构本身是一种抽象的、来自建筑学的体系结构,其在企业及IT系统中被广泛应用。 架构的本质是对事物复杂性的管理,是对一个企业、一个公司、一个系统复杂的内部关系进行结构化、体系化的抽象,…

Stable-Diffusion的WebUI部署实战

1、环境准备及安装 1.1、linux环境 # 首先&#xff0c;已经预先安装好了anaconda&#xff0c;在这里新建一个环境 conda create -n sdwebui python3.10 # 安装完毕后&#xff0c;激活该环境 conda activate sdwebui# 安装 # 下载stable-diffusion-webui代码 apt install wget…

String 底层是如何实现的?

1、典型回答 String 底层是基于数组实现的&#xff0c;并且数组使用了 final 修饰&#xff0c;不同版本中的数组类型也是不同的&#xff1a; JDK9 之前&#xff08;不含JDK9&#xff09; String 类是使用 char[ ]&#xff08;字符数组&#xff09;实现的但 JDK9 之后&#xf…

C#版开源免费的Bouncy Castle密码库

前言 今天大姚给大家分享一款C#版开源、免费的Bouncy Castle密码库&#xff1a;BouncyCastle。 项目介绍 BouncyCastle是一款C#版开源、免费的Bouncy Castle密码库&#xff0c;开发人员可以通过该项目在他们的 C# 应用程序中使用 Bouncy Castle 提供的各种密码学功能&#x…

如何使用 Langchain、Ollama 和 Streamlit 构建 RAG

一、先决条件&#xff1a;您需要了解什么 在深入讨论技术细节之前&#xff0c;我们先概述一下先决条件。Python 的基础知识至关重要&#xff0c;因为它是我们将使用的主要语言。熟悉机器学习和自然语言处理的基本概念将帮助您更轻松地掌握这些概念。此外&#xff0c;对 Langch…

瑞熙贝通实验室物联网管理平台新升级|支持远程开门视频监控与电源控制以及环境监测

瑞熙贝通实验室智能物联网管控平台&#xff1a;利用“互联网与物联网技术”有机融合&#xff0c;对实验室的用电安全监测、实验室环境异常监测&#xff08;颗粒物监测、明火监测、可燃气体、烟雾监测、温湿度传感器、红外人体感应&#xff09;、实验室人员安全准入、万物互联等…

16、技巧之九: 修改参数,如何让表格翻页滚动到底部?【Selenium+Python3网页自动化总结】

1、问题提出 在网页配置参数时&#xff0c;输入参数名称搜索&#xff0c;搜出来的同名参数结果有多个&#xff0c;分布在一个表格的不同行&#xff0c;表格是动态加载的&#xff0c;需要滚动鼠标才能把所出参数找出来。用selenium怎么实现这种参数修改&#xff1f; 2、网页元素…

数字工厂管理系统和ERP管理系统有什么区别

在制造业的数字化转型浪潮中&#xff0c;数字工厂管理系统和ERP管理系统作为两大核心系统&#xff0c;扮演者不可或缺的角色。虽然它们都是为了提高企业的运营效率和降低成本&#xff0c;但在功能与实施效果方面&#xff0c;二者却有着显著的区别。本文将从这两个方面对数字工厂…

Pytorch实战01——CIAR10数据集

目录 1、model.py文件 &#xff08;预训练的模型&#xff09; 2、train.py文件&#xff08;会产生训练好的.th文件&#xff09; 3、predict.py文件&#xff08;预测文件&#xff09; 4、结果展示&#xff1a; 1、model.py文件 &#xff08;预训练的模型&#xff09; impor…

day57 动态规划part17● 647. 回文子串 ● 516.最长回文子序列● 动态规划总结篇

如果大家做了很多这种子序列相关的题目&#xff0c;在定义dp数组的时候 很自然就会想题目求什么&#xff0c;我们就如何定义dp数组。 布尔类型的dp[i][j]&#xff1a;表示区间范围[i,j] &#xff08;注意是左闭右闭&#xff09;的子串是否是回文子串&#xff0c;如果是dp[i][j…

C++学习路线

C学习路线思维导图&#xff0c;肝了一个星期终于搞定&#xff0c;这么硬核求个赞不过分吧&#xff1f; 思维导图的内容&#xff0c;也是本文的内容框架&#xff0c;坐稳扶好&#xff0c; C 高速快车要发车了&#xff01; 内容我会持续更新&#xff0c;点赞收藏&#xff0c;…

Window系统下Vscode配置C/Cpp运行+调试环境

Window系统下Vscode配置C/Cpp运行调试环境 文章目录 Window系统下Vscode配置C/Cpp运行调试环境1.安装Vscode2.安装C/Cpp插件3.配置gcc编译器4.配置Cpp运行环境5.配置Cpp调试环境 1.安装Vscode 安装VScode很简单&#xff0c;直接到官网进行下载&#xff0c;然后傻瓜安装即可。 …