顺序表(超详解哦)

news2024/10/1 15:29:03

全文目录

  • 引言
  • 顺序表定义
    • 静态顺序表
    • 动态顺序表
  • 动态顺序表的接口实现
    • 顺序表的初始化与销毁
    • 顺序表尾插/尾删
    • 顺序表头插/头删
    • 顺序表在pos位置插入/删除
    • 顺序表的打印
    • 顺序表中的查找
  • 总结

引言

在生产中,为了方便管理数据,我们经常会需要将一些数据连续的存储起来。例如手机的通讯录中需要存储联系人的信息;图书管理系统中需要存储图书的信息等。

想到存储一系列相同类型的数据,我们就不免想到数组。数组可以实现将一些相同类型的数据存储到一块连续的空间中。其实,我们在这篇文章中要介绍的顺序表中的数据就是以数组的形式存储的。

顺序表定义

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

为了方便管理数据,我们通常会将存储数据的数组与目前数据的状态(顺序表中已经存储元素的个数等)放在一个结构体变量中。

静态顺序表

静态顺序表就是使用定长的数组存储数据的顺序表。

我们需要将存储数据的数组与当前已存储的数据的个数放在一个结构体变量中,以方便对数据进行管理:

typedef int SLDateType;

typedef struct SeqList
{
	SLDateType arr[10];
	size_t size;
}SeqList;

但是,这样存储数据是有很明显的缺陷的:就是空间的大小一旦确定下来就不能改变了,当数据存储满之后也不能实现扩容。

所以,我们可以使用动态顺序表来实现:

动态顺序表

动态顺序表就是使用动态开辟的数组存储数据的顺序表:

我们需要将存储数据的动态空间的地址、当前已经存储的数据的个数与顺序表的容量大小放在一个结构体变量中,方便对数据进行管理:

typedef int SLDateType;

typedef struct SeqList
{
	SLDateType* arr;
	size_t size;
	size_t capacity;
}SeqList;

在这里插入图片描述

SLDateType* arr指向的空间是动态开辟的,当需要扩容时,只需要使用realloc函数进行扩容即可。

动态顺序表的接口实现

在有了顺序表的相关概念后,我们就可以尝试实现一下顺序表
静态顺序表的实现其实是较为简单的,这里就只介绍动态顺序表的实现:

首先,我们需要将上述的SeqList类型的结构体定义出来。但此时它的成员为一个SLDateType*型的指针、任意值的size变量与capacity变量。并没有任何意义,所以,我们需要对这个结构体中的成员进行初始化:

顺序表的初始化与销毁

初始化函数:void SeqListInit(SeqList* ps);

对于初始化函数,只有一个参数就是我们创建的结构体的结构体指针。在这个函数中,我们需要实现动态开辟一块空间用来存放数据,并且将size与capacity的值初始化为0:

void SeqListInit(SeqList* ps)
{
	assert(ps);
	ps->arr = (SLDateType*)calloc(INIT, sizeof(SLDateType));
	if (ps->arr == NULL)
	{
		perror(calloc);
		return;
	}
	ps->capacity = INIT;
	ps->size = 0;
}

我们的空间是动态开辟的,在使用结束后自然需要free释放

内存释放函数:void SeqListDestroy(SeqList* ps)

void SeqListDestroy(SeqList* ps)
{
	assert(ps);
	free(ps->arr);
	ps->arr = NULL;
	ps->capacity = 0;
	ps->size = 0;
}

有了存储数据的空间,我们就需要实现对这些数据的操作:无非增、删、查、改。
我们将逐一实现这些操作:

顺序表尾插/尾删

顺序表的尾插就是在顺序表的末尾插入一个值。
我们直接在顺序表中下标为size(结构体中的成员)的位置插入一个数据即可。

但是,这样的想法是有漏洞的,当size等于capacity时,即顺序表已经存满的时候。我们如果还将数据存在下标为size的位置,就会出现数组越界的问题。所以插入数据前,我们需要判断是否需要扩容,如果需要,则使用realloc扩容后再插入数据:
(别忘了插入后size++)

void SeqListPushBack(SeqList* ps, SLDateType x)
{
	assert(ps);
	if (ps->capacity == ps->size)
	{
		SLDateType* ptr = (SLDateType*)realloc(ps->arr, 2 * ps->capacity * sizeof(SLDateType));
		if (ptr == NULL)
		{
			perror("realloc");
			return;
		}
		ps->arr = ptr;
		ps->capacity *= 2;
	}
	*(ps->arr + ps->size++) = x; 
}

顺序表的尾删就是删除顺序表中的最后一个数据:

当然,当顺序表中的数据数(size)为0时,就不执行此函数。这里我们可以直接使用assert来判断:
(别忘了删除后size–)

void SeqListPopBack(SeqList* ps)
{
	assert(ps);
	assert(ps->size > 0);
	*(ps->arr + --(ps->size)) = 0;
}

顺序表头插/头删

顺序表的头插就是在顺序表的前面插入一个数据。

此时,我们显然是不能直接用数据覆盖第一个数据的。而是需要将顺序表中的数据整体向后移动一个元素的位置,然后再将第一个元素的位置覆盖。
当然,头插也需要判断顺序表是否已满:
(别忘了插入后size++)

void SeqListPushFront(SeqList* ps, SLDateType x)
{
	assert(ps);
	if (ps->capacity == ps->size)
	{
		SLDateType* ptr = (SLDateType*)realloc(ps->arr, 2 * ps->capacity * sizeof(SLDateType));
		if (ptr == NULL)
		{
			perror("realloc");
			return;
		}
		ps->arr = ptr;
		ps->capacity *= 2;
	}
	for(size_t i = ps->size; i > 0; i--)
	{
		*(ps->arr + i) = *(ps->arr + i - 1);
	}
	*ps->arr = x;
	ps->size++;
}

顺序表的头删就是将顺序表中最前面的元素删除。
首先判断size是否为0。然后我们可以直接用后面的元素覆盖前面一个的元素,这样可以直接实现删除第一个元素:
(别忘了删除后size–)

void SeqListPopFront(SeqList* ps)
{
	assert(ps);
	assert(ps->size > 0);
	for (size_t i = 1; i < ps->size; i++)
	{
		*(ps->arr + i - 1) = *(ps->arr + i);
	}
	ps->size--;
}

顺序表在pos位置插入/删除

实现了头插头删、尾插尾删后,我们再进一步思考,能不能实现在顺序表的任意位置插入或删除任意位置的元素:

在pos位置插入数据时:
同样需要判断是否已满。我们需要将从pos开始的元素向后移动,然后再将元素插入到pos位置即可:
(别忘了插入后size++)

void SeqListInsert(SeqList* ps, int pos, SLDateType x)
{
	assert(ps);
	if (ps->capacity == ps->size)
	{
		SLDateType* ptr = (SLDateType*)realloc(ps->arr, 2 * ps->capacity * sizeof(SLDateType));
		if (ptr == NULL)
		{
			perror("realloc");
			return;
		}
		ps->arr = ptr;
		ps->capacity *= 2;
	}
	for (int i = ps->size; i > pos; i--)
	{
		*(ps->arr + i) = *(ps->arr + i - 1);
	}
	ps->size++;
	*(ps->arr + pos) = x;
}

删除pos位置的元素时,首先判断size是否为0。然后只需要将从pos后的元素统一向前覆盖即可实现pos位置数据的删除:
(别忘了删除后size–)

void SeqListErase(SeqList* ps, int pos)
{
	assert(ps);
	assert(ps->size > 0);
	for (size_t i = pos; i < ps->size - 1; i++)
	{
		*(ps->arr + i) = *(ps->arr + i + 1);
	}
	*(ps->arr + --(ps->size)) = 0;
}

顺序表的打印

打印顺序表中元素时,直接便利顺序表打印即可:

void SeqListPrint(SeqList* ps)
{
	assert(ps);
	for (size_t i = 0; i < ps->size; i++)
	{
		printf("%d ", *(ps->arr + i));
	}
}

顺序表中的查找

查找顺序表中数据时,只需要将顺序表中度元素遍历,逐个与输入元素比较即可。查找到后,返回下标,否则返回0:

int SeqListFind(SeqList* ps, SLDateType x)
{
	assert(ps);
	for (size_t i = 0; i < ps->size; i++)
	{
		if (*(ps->arr + i) == x)
		{
			return i + 1;
		}
	}
	return -1;
}

总结

到此,关于顺序表的所有内容就介绍完了。不难发现,这些数据存储的形式可以抽象化为线性,顺序表其实就是线性表的一种。

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

线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,
线性表在物理上存储时,通常以数组和链式结构的形式存储。在下一篇文章我们将要介绍的链表也是线性表的一种。

如果大家认为我对某一部分没有介绍清楚或者某一部分出了问题,欢迎大家在评论区提出

如果本文对你有帮助,希望一键三连哦

希望与大家共同进步哦

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

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

相关文章

MyBatis——创建与使用

概念 当我们使用传统的jdbc进行数据库与程序的连接时&#xff0c;每一个操作都需要写一条sql语句&#xff0c;并且没法调试和修改 jdbc连接数据库流程&#xff1a; 创建数据库连接池DataSource获取数据库连接Connection执行带占位符的sql语句通过Connection创建操作对象Stat…

【LeetCode】剑指 Offer(8)

目录 题目&#xff1a;剑指 Offer 21. 调整数组顺序使奇数位于偶数前面 - 力扣&#xff08;Leetcode&#xff09; 题目的接口&#xff1a; 解题思路&#xff1a; 代码&#xff1a; 过啦&#xff01;&#xff01;&#xff01; 题目&#xff1a;剑指 Offer 24. 反转链表 - …

HTTP 返回码

HTTP 返回码1XX 指示信息2XX 成功3XX 重定向301 Moved Permanently302 Found304 Not Modified4XX 客户端错误400 Bad Request401 Unauthorized403 Forbidden404 Not Found405 Method Not Allowed411 Length Requied413 Request Entity Too Large414 Request Uri Too Long5XX 服…

学习 Python 之 Pygame 开发魂斗罗(一)

学习 Python 之 Pygame 开发魂斗罗&#xff08;一&#xff09;Pygame回忆Pygame1. 使用pygame创建窗口2. 设置窗口背景颜色3. 获取窗口中的事件4. 在窗口中展示图片(1). pygame中的直角坐标系(2). 展示图片(3). 给部分区域设置颜色5. 在窗口中显示文字6. 播放音乐7. 图片翻转与…

php使用wangeditor实现富文本

官网参考连接&#xff1a;https://www.wangeditor.com/v5/getting-started.html样式&#xff1a;前端代码&#xff1a;搭建前端部分样式&#xff1a;<tr><td><span style"color:red">*</span>内容</td><td colspan"20"&g…

锁屏面试题百日百刷-Hive篇(二)

锁屏面试题百日百刷&#xff0c;每个工作日坚持更新面试题。锁屏面试题app、小程序现已上线&#xff0c;官网地址&#xff1a;https://www.demosoftware.cn/#/introductionPage。已收录了每日更新的面试题的所有内容&#xff0c;还包含特色的解锁屏幕复习面试题、每日编程题目邮…

【华为OD机试模拟题】用 C++ 实现 - 机器人活动区域(2023.Q1)

最近更新的博客 华为OD机试 - 入栈出栈(C++) | 附带编码思路 【2023】 华为OD机试 - 箱子之形摆放(C++) | 附带编码思路 【2023】 华为OD机试 - 简易内存池 2(C++) | 附带编码思路 【2023】 华为OD机试 - 第 N 个排列(C++) | 附带编码思路 【2023】 华为OD机试 - 考古…

django项目实战十四(django+bootstrap实现增删改查)进阶混合数据使用modelform上传

目录 一、启用media 1、URL设置 2、settings.py配置 二、url 三、upload.py 新增upload_modelform方法 四、form.py新增UpModelForm 五、创建city表 六、创建city_list.html 接上一篇《django项目实战十三&#xff08;djangobootstrap实现增删改查&#xff09;进阶混合数据f…

【信管12.5】项目集与项目组合管理

项目集与项目组合管理之前学习的 PMP 相关的项目管理知识&#xff0c;其实都是针对一个项目的管理过程。但是&#xff0c;在一个组织企业中&#xff0c;往往不止一个项目&#xff0c;可能会有多个相关联的项目&#xff0c;这种情况就叫做项目集。另外&#xff0c;多个项目一起完…

值得推荐!安利5款良心又好用的小众软件

电脑上的各类软件有很多&#xff0c;除了那些常见的大众化软件&#xff0c;还有很多不为人知的小众软件&#xff0c;专注于实用功能&#xff0c;简洁干净、功能强悍。今天分享5个实用的软件&#xff0c;简单实用&#xff0c;效果拉满&#xff0c;堪称工作生活必备&#xff01; …

MXNet中使用双向循环神经网络BiRNN对文本进行情感分类

文本分类类似于图片分类&#xff0c;也是很常见的一种分类任务&#xff0c;将一段不定长的文本序列变换为文本的类别。这节主要就是关注文本的情感分析(sentiment analysis)&#xff0c;对电影的评论进行一个正面情绪与负面情绪的分类。整理数据集第一步都是将数据集整理好&…

对restful的支持 rust-grpc-proxy

目录前言快速体验说明1. 启动目标服务2. 启动代理3. 测试4. example.sh尾语前言 继上一篇博文的展望&#xff0c;这个月rust-grpc-proxy提供了对restful的简单支持。 并且提供了完成的用例&#xff0c;见地址如下&#xff0c; https://github.com/woshihaoren4/grpc-proxy/tre…

函数指针、函数指针的数组、QT中的函数指针

一、函数指针三种定义方法 函数名本质就是函数指针&#xff0c;函数实际上就是返回的是函数指针 //函数指针#include <iostream> using namespace std;void func(int a){cout << "hello world" << endl; }int main(){//函数指针 三种定义方法//一…

WindownsPowershell中的单引号和双引号

WindownsPowershell中的单引号和双引号 目录标题WindownsPowershell中的单引号和双引号单引号对中,可以直接写双引号双引号对中,可以直接写单引号反引号 可以在 双引号对中表示转义双引号对中, 可以用 反引号双引号 表示一个双引号双引号对中, 可以用 反引号单引号 表示一个单引…

【华为OD机试模拟题】用 C++ 实现 - 构成的正方形数量(2023.Q1)

最近更新的博客 华为OD机试 - 入栈出栈(C++) | 附带编码思路 【2023】 华为OD机试 - 箱子之形摆放(C++) | 附带编码思路 【2023】 华为OD机试 - 简易内存池 2(C++) | 附带编码思路 【2023】 华为OD机试 - 第 N 个排列(C++) | 附带编码思路 【2023】 华为OD机试 - 考古…

极品笔记,阿里P7爆款《K8s+Jenkins》技术笔记,职场必备

前些日子从阿里的朋友那里取得这两份K8sJenkins的爆款技术笔记&#xff1a;《K8S(kubernetes)学习指南》《Jenkins持续集成从入门到精通》&#xff0c;非常高质量的干货&#xff0c;我立马收藏&#xff01; 而今天咱们文章的主角就是这非常之干货的技术笔记&#xff1a;K8SJenk…

第八届蓝桥杯省赛 C++ B组 - K 倍区间

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?spm1011.2415.3001.5343 &#x1f4da;专栏地址&#xff1a;蓝桥杯题解集合 &#x1f4dd;原题地址&#xff1a;K 倍区间 &#x1f4e3;专栏定位&#xff1a;为想参加蓝桥杯的小伙伴整理常考算法题解&#xff0c;祝大家…

【华为OD机试模拟题】用 C++ 实现 - 求解连续数列(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 分积木(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 吃火锅(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - RSA 加密算法(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 构成的正方形数量(2023.Q1) 【华为OD机试模拟…

MATLAB绘制雷达图/蜘蛛图

雷达图/蜘蛛图 1 方法一 函数来源为MATLAB | 如何使用MATLAB绘制雷达图(蜘蛛图) 1.1 调用函数 1.2 案例 2 方法二 函数来源为MATLAB帮助-spider_plot 2.1 调用函数 语法&#xff08;Syntax&#xff09;&#xff1a; spider_plot(P)spider_plot(P, Name, Value, ...)h …

JavaWeb中FilterListener的神奇作用

文章目录1&#xff0c;Filter1.1 Filter概述1.2 Filter快速入门1.2.1 开发步骤1.3 Filter执行流程1.4 Filter拦截路径配置1.5 过滤器链1.5.1 概述1.5.2 代码演示1.5.3 问题2&#xff0c;Listener2.1 概述2.2 分类2.3 代码演示最后说一句1&#xff0c;Filter 1.1 Filter概述 F…