【数据结构初阶】第二篇——顺序表

news2024/10/6 12:33:53

顺序表的概念及其结构

初始化顺序表

销毁顺序表

打印顺序表

增加数据

头插

尾插

指定下标位置插入

删除数据

头删

尾删

删除指定位置

查找数据

修改数据


顺序表的概念及其结构

基本概念

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

  • 存储空间连续,既允许元素的顺序访问,又可以随机访问
  •  要访问指定元素,可以使用索引(下标)来访问,时间复杂度为O(1)
  • 要在其中增加或者删除一个元素,都要涉及后面所有元素的向前或向后移动,时间复杂度为O(n);
  • 可以方便的存储表中的任一结点,存储速度快
  • 长度固定,分配内存之前必须知道数组的长度;
  • 无需为表示结点间的逻辑关系而增加额外的存储空间,存储利用率提高

存储结构:

顺序表一般可以分为:

1.静态顺序表:使用定长数组存储;

2.动态顺序表:使用动态开辟的数组存储;

静态分配和动态分配有什么不同?其实就是数组的不同。在静态分配时,我们在编写的时候,就已经确定了数组的大小。而动态分配时,没有确定它的大小,是根据动态分配语句在运行时才将它的大小进行分配。这样有一点好处就是,在静态分配时,当我想要存放顺序表的数据元素超过100时候则会产生错误溢出,而动态分配时,如果一旦超过了分配的空间大小,可以再重新分配一块内存空间,把旧的空间和所增加的数据元素转移到新申请的空间上,这样就不会产生溢出的问题了。这是动态分配的一个优点。

 代码如下:

//顺序表的静态存储
#define N 8
typedef int SLDataType;
typedef struct SeqList
{
  SLDataType array[N];//定长数组
  size_t size;//有效数组的个数
}SeqList;


//顺序表的动态存储
typedef int SLDataType;
typedef struct SeqList
{ 
   SLDataType* array;//指向动态开辟的数组
   size_t size;//有效数据的个数
   size_t capacity;//空间容量的大小
}SeqList;
/*注解:我们发现这里用的是指针,指针是存放一个存储单元地址的.顺序表根据第一个数据元素的地址和数据元素的大小,就可以算出任意数据元素的位置.即只定义第一个元素的指针即可,描述整个顺序表。但它仅仅是个地址,没有确切的空间,因此我们使用是要开辟空间;
SLDataType* tmp = (SLDataType*)realloc(ps->a, newcapacity*sizeof(SLDataType));
详细代码下面讲解;*/

静态顺序表的定长数组导致N定长,空间开少了不够用,开多了浪费,所以现实中都是使用动态顺序表,使用倍增-复制的办法来支持动态扩容,将顺序表变成了"可变长度"的,下面我将实现动态顺序表;

初始化顺序表

对顺序表进行初始化

void SeqListInit(SeqList* ps)
{
	assert(ps);
	ps->array = NULL;//顺序表指针NULL
	ps->size = 0;//起始元素个数为0
	ps->capacity = 0;//容量为0
}

销毁顺序表

因为顺序表所用的内存空间是动态开辟在堆区的,所以我们在使用完后需要及时对其进行释放,避免造成内存泄漏

//销毁顺序表
void SeqListDestory(SeqList* ps)
{
	assert(ps);
	free(ps->a);//释放顺序表指针指向的空间
	ps->a = NULL;//及时置空
	ps->size = 0;//元素个数置0
	ps->capacity = 0;//容量置0
}

若需要对数据进行保存,可以使用文件操作函数将数据保存到一个文件中,下次使用顺序表的时候先读取文件数据即可 

打印顺序表

void SeqListPrint(SeqList* ps)
{
	assert(ps);
	for (int i = 0; i < ps->size; i++)
	{
		printf("%d", ps->array[i]);
	}
	printf("\n");
}

增加数据

头插

每一次在顺序表最前方插入,其他数据后移

void SeqListPushFront(SL* ps, SLDataType x)
{
	//如果没有空间,或者空间不足,我们可以增容
	if (ps->size == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;//对数组进行二倍增容,使用三目运算符是为了防止0这种情况
		SLDataType* tmp = (SLDataType*)realloc(ps->a, sizeof(SLDataType) * newcapacity);
		//判断是否增容成功
		if(tmp == NULL)
		{
			printf("realloc fail\n");
			exit(-1);
		}
		ps->a = tmp;
		ps->capacity = newcapacity;
	}
    //从最后一个元素开始向前遍历到第一个元素,分别将它们向后移动一个位置
	for (int i = ps->size - 1; i >= 0; i--)
	{
		ps->a[i + 1] = ps->a[i];
	}
	ps->a[0] = x;//将要插入的数据插入到头部
	ps->size++;//表长加1
}

尾插

顺序表的末尾增加数据,其他元素不用改变

void SeqListPushBack(SL* ps, SLDataType x)
{
	if (ps->size == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		SLDataType* tmp = (SLDataType*)realloc(ps->a, newcapacity * sizeof(SLDataType));
		if (tmp == NULL)
		{
			printf("realloc fail");
			exit(-1);
		}
		ps->a = tmp;
		ps->capacity = newcapacity;
	}
	ps->a[ps->size] = x;
	ps->size++;
}

指定下标位置插入

从最后一个元素开始向前遍历到第指定位置,分别将它们向后移动一个位置

void SeqListInsert(SL* ps, int pos, SLDataType x)
{
	//因为顺序表连续存储,所以首先要判断插入位置是否合法;
	assert(pos >= 0 && pos <= ps->size);
	//增容
	if (ps->size == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		SLDataType* tmp = (SLDataType*)realloc(ps->a, sizeof(SLDataType) * newcapacity);
		if (tmp == NULL)
		{
			printf("realloc fail\n");
			exit(-1);
		}
		ps->a = tmp;
		ps->capacity = newcapacity;
	}
	//从最后一个元素开始向前遍历到第指定位置,分别将它们向后移动一个位置
	for (int i = ps->size - 1; i >= pos; i--)
	{
		ps->a[i + 1] = ps->a[i];
	}
    //将x插入到指定位置
	ps->a[pos] = x;
    //表长加1
	ps->size++;
}

删除数据

头删

从删除位置遍历到最后一个元素的位置,将他们依次向前移一个位置;

void SeqListPopFront(SeqList* ps)
{
	assert(ps->size > 0);
	for (int i = 1; i < ps->size; i++)
	{
		ps->array[i-1] = ps->array[i];
	}
	ps->size--;
}

尾删

将表长减去1即可;

void SeqListPopBack(SL* ps)
{
	assert(ps->size > 0);
	ps->size--;
}

删除指定位置

首先判断指定位置是否合法然后从指定位置的下一个元素依次向前移动一步

void SeqListErase(SL* ps, int pos)
{
	assert(pos >= 0 && pos < ps->size);
	for (int i = pos + 1; i < ps->size; i++)
	{
		ps->a[i - 1] = ps->a[i];
	}
	ps->size--;
}

查找数据

顺序表的一端开始,依次将每个元素的关键字同给定值 K 进行比较,直到相等或比较完毕还未找到.

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

修改数据

//修改指定下标位置元素
void SeqListModify(SeqList* ps, int pos, SLDataType x)
{
	assert(ps);
	assert(pos >= 0 && pos < ps->size);//检查输入下标的合法性
	ps->a[pos] = x;//修改数据
}

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

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

相关文章

Word控件Spire.Doc 【Table】教程(6): 在 Word 中合并或拆分表格单元格

Spire.Doc for .NET是一款专门对 Word 文档进行操作的 .NET 类库。在于帮助开发人员无需安装 Microsoft Word情况下&#xff0c;轻松快捷高效地创建、编辑、转换和打印 Microsoft Word 文档。拥有近10年专业开发经验Spire系列办公文档开发工具&#xff0c;专注于创建、编辑、转…

AcWing 1072. 树的最长路径(DFS与树形DP)

AcWing 1072. 树的最长路径&#xff08;树形DP&#xff09;一、题目&#xff1a;二、思路&#xff1a;三、代码&#xff1a;四、树形DP1、状态表示2、状态转移3、循环设计4、初末状态5、代码实现一、题目&#xff1a; 二、思路&#xff1a; 为了方便&#xff0c;我们利用下面这…

Vue3现状—必然趋势?

文章目录&#x1f31f; 专栏介绍&#x1f31f; Vue默认版本&#x1f31f; 拥抱Vue3的UI&#x1f31f; Vue3显著优势&#x1f31f; 专栏介绍 凉哥作为 Vue 的忠诚粉丝输出过大量的 Vue 文章&#xff0c;应粉丝要求开始更新 Vue3 的相关技术文章&#xff0c;Vue 框架目前的地位大…

Python爬虫之Scrapy框架系列(8)——XXTop250电影所有信息同时存储到MySql数据库

现在又不满足于只保存在本地txt文本了&#xff0c;所以来试试存储到数据库mysql里怎么搞呢&#xff1f;&#xff08;首先&#xff0c;要准备好mysql数据库以及navicat数据库可视化管理工具&#xff09; 目录&#xff1a;分析&#xff1a;如何同时存储到本地txt文本以及mysql数据…

回溯详解 LeetCode 46. 全排列 51. N 皇后 52. N皇后 II

&#x1f308;&#x1f308;&#x1f604;&#x1f604; 欢迎来到茶色岛独家岛屿&#xff0c;本期将为大家揭晓LeetCode 46. 全排列 51. N 皇后 52. N皇后 II&#xff0c;做好准备了么&#xff0c;那么开始吧。 &#x1f332;&#x1f332;&#x1f434;&#x1f434; 46. 全…

Word处理控件Aspose.Words功能演示:如何在 C# 和Java中将 DOC 转换为 JSON

Aspose.Words 是一种高级Word文档处理API&#xff0c;用于执行各种文档管理和操作任务。API支持生成&#xff0c;修改&#xff0c;转换&#xff0c;呈现和打印文档&#xff0c;而无需在跨平台应用程序中直接使用Microsoft Word。此外&#xff0c; Aspose API支持流行文件格式处…

kvm磁盘管理

kvm磁盘管理虚拟磁盘类型rawqcow2qemu-img常用参数主要参数&#xff1a;查看磁盘信息--info创建磁盘文件--create磁盘容量调整--resize磁盘增加容量磁盘缩小容量(生产环境下禁止操作)磁盘调整容量到指定大小转换磁盘格式--convert检查磁盘镜像在线热添加磁盘附加磁盘到vm实例--…

UI自动化测试面试题总结

文章目录一、请描述实现用户登陆模拟自动化测试的思路。二、基于Web端呈现的产品如何做自动化测试&#xff0c;谈谈你的思路和方向。三、什么是web自动化测试&#xff1f;四、什么是selenium&#xff1f;五、写出selenium中你最熟悉的接口或类(*)六、findElement()和findElemen…

java总结(数组)

1.数组概述数组&#xff08;Array&#xff09;是多个相同数据类型按照一定顺序排列的集合&#xff0c;并使用一个名字命名&#xff0c;通过编号的方式对这些数据进行统一的管理。数组相关概念数组名&#xff1a;下标&#xff08;索引&#xff09;元素数组长度数组特点有序排列数…

sqlserver将mdf文件拆分成多个ndf文件

sqlserver版本&#xff1a;2008R2 1、为什么要拆分 数据库在运行一段时间后mdf文件会迅速增大&#xff0c;这会导致查询速度变慢。或者mdf文件的大小达到了操作系统允许的最大大小&#xff0c;这个时间就必须要进行拆分了。 2、拆分的好处 在没有拆分的时候只有一个mdf主数…

KVM虚拟化技术学习笔记10

虚拟机镜像管理 学习目标&#xff1a; 能够了解KVM虚拟机支持的镜像格式 能够使用qemu-img实现镜像创建 能够使用qemu-img实现镜像查看 能够使用qemu-img实现镜像格式转换 能够了解后备镜像的作用 能够了解差量镜像的作用 能够基于后备镜像制作差量镜像 能够使用差量镜…

SAP ADM100-2.3 系统启动:AS ABAP和AS ABAP+JAVA

一、打开并停止一个SAP Netweaver AS ABAP+JAVA 使用例如SAP MC(SAP Management Console)工具开启并关闭实例。在一个双栈实例中(ABAP+JAVA),JAVA是通过ABAP dispatcher使用Startup and Control Framework开启的,然后它再开启JAVA dispatcher和SP(server Processes)。 …

Qt OpenGL(三十)——Qt OpenGL 核心模式-纹理二(给正方体贴上图片)

提示:本系列文章的索引目录在下面文章的链接里(点击下面可以跳转查看): Qt OpenGL 核心模式版本文章目录 Qt OpenGL(三十)——Qt OpenGL 核心模式-纹理二(给正方体贴上图片) 通过前两篇文章,我们知道了如何绘制一个正六面体和使用纹理贴图,本篇继续介绍在正方体(正…

面试中如何才能有底气的回答,软件测试题库你有必要一用

面试&#xff0c;是决定求职者是否能进入到自己心仪岗位的敲门砖&#xff0c;而对于很多第一次参加软件测试面试的求职来说&#xff0c;想要通过面试就得经过hr的初面以及技术官技术面&#xff0c;前者还好说&#xff0c;可以根据情况临场发挥&#xff0c;而后者&#xff0c;就…

Linux 之十七 Ubuntu 22.04 配置内核版本、GRUB 引导、远程桌面

前段时间重新安装了 Ubuntu 22.04 LTS&#xff0c;安装后没有显示 GRUB 引导页面&#xff08;默认自动跳过&#xff09;&#xff0c;直接使用默认内核启动&#xff0c;而我需要变更一下默认的内核版本&#xff0c;特此记录一下修改过程。 安装其他版本内核 Ubuntu 中安装其他版…

MAC m1 安装 allure

一、下载安装包&#xff0c;并进行解压 1.1 下载安装包 官网下载包地址 1.2 双击 进行 解压 二、配置环境变量 2.1 打开配置文件 在终端输入以下命令 vi ~/.bash_profile【注意】 该命令地址 注意 中间不要出现多余的空格&#xff0c;否则打开会有问题&#xff0c;这个…

学生护眼台灯怎么选?推荐教育部认可护眼灯品牌

现在许多家庭都会购买学生护眼台灯给孩子用&#xff0c;那么学生护眼台灯怎么选&#xff1f;1. 光线的舒适度&#xff0c;才是最关键的&#xff1a;一般会在护眼技术上体现出&#xff0c;有全光谱灯珠、色温舒适、显色指数高、无蓝光危害、无可视频闪等&#xff0c;让光线照射眼…

高效、优雅的对象copy之MapStruct入门到精通,实战踩坑版

一、前言 大家在开发中&#xff0c;最让人头疼的就是&#xff1a;对象之间的拷贝&#xff0c;前端的VO和数据库的Entity不一致&#xff01; 性能最好的就是手动set&#xff0c;主要是枯燥且无技术含量&#xff0c;不仅耗费大量时间而且很容易出错&#xff1b; 所以我们要成为…

jsp 新房销售竞买管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 jsp 新房销售竞买管理系统 是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统采用web模式开发&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&…

OJ万题详解––赦免战俘(C++详解)

题目 题目背景 借助反作弊系统&#xff0c;一些在月赛有抄袭作弊行为的选手被抓出来了&#xff01; 题目描述 现有 名作弊者站成一个正方形方阵等候 kkksc03 的发落。kkksc03 决定赦免一些作弊者。他将正方形矩阵均分为 4 个更小的正方形矩阵&#xff0c;每个更小的矩阵的边长…