【数据结构】第二章——线性表(2)

这篇具有很好参考价值的文章主要介绍了【数据结构】第二章——线性表(2)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【数据结构】第二章——线性表(2),数据结构,数据结构,算法,c语言,改行学it,开发语言

导言

大家好,很高兴又和各位见面啦!!!在上一个篇章中,我们简单了解了一下线性表的基础知识以及一下重要的术语。在今天的篇章中我们将来开始正式介绍线性表的顺序存储——又称顺序表。我们将会在本章介绍什么是顺序表,对于顺序表的操作我们又应该如何实现。接下来,我们就来开始今天的内容吧!!!

1、顺序表的定义

线性表的顺序存储又称顺序表。它是用一组地址连续的存储单元依次存储线性表中的数据元素,从而使得逻辑上相邻的两个元素在物理位置上也相邻

在上一个篇章中我们有提到数组是一种线性表,我们在数组篇章中有介绍过,数组元素在内存上是由低地址到高地址进行连续存放的,所以数组元素不仅满足逻辑上相邻,也满足在物理位置上相邻,因此数组就是一种顺序表

通常在高级程序语言中,我们会使用数组来描述线性表的顺序存储结构。假设线性表L存储的起始位置为LOC(A),每个元素占用内存空间大小为sizeof(ElemType),则表L所对应的顺序存储如下图所示:

【数据结构】第二章——线性表(2),数据结构,数据结构,算法,c语言,改行学it,开发语言
顺序表的元素在物理位置上相邻体现在以下两点:

  1. 两个相邻元素的地址之间相差的大小刚好就是一个元素所占内存空间的大小
  2. 从第二个元素开始,其它的每个元素和首元素的地址之间相差的大小刚好是元素的位序减1与元素所占内存空间大小的乘积,也就是对应的数组下标×元素所占看内存空间大小

因此,顺序表中的任意一个数据元素都是可以进行随机存取的,所以线性表的顺序存储结构是一种随机存取的存储结构

下面我们通过C语言来实现一个顺序表;

2. 顺序表的实现

我们想要实现一个顺序表是可以通过两种方式来实现:

  • 确定了顺序表的最大长度时,可以采取静态分配的方式实现顺序表;
  • 顺序表的最大长度会发生变化时,可以采取动态分配的方式实现顺序表;

接下来我们来详细介绍这两种实现方式;

2.1 静态分配

在已知最大长度时,我们可以通过定义一个静态数组来实现一个顺序表。具体的实现格式如下所示:

//顺序表的静态实现方式
#define MaxSize//通过#define定义一个标识符常量作为顺序表的最大表长
//通过定义一个结构体作为顺序表
typedef struct Sqlist
{
	Elemtype date[MaxSize];
	//Elemtype——数组元素的数据类型
	//date[MaxSize]——静态数组存放数据元素
	int length;//顺序表的当前表长
}Sqlist;//Sq:sequence——顺序,序列
//Sqlist——顺序表,顺序表的名字,这里根据实际情况进行自定义

从这个格式中我们可以看到,要实现一个静态顺序表,我们需要先确定顺序表的最大表长、顺序表的当前表长以及顺序表数据元素的数据类型。这些内容缺一不可,下面我们就来尝试着创建一个整型的顺序表;

2.1.1 整型顺序表的创建

//整型顺序表的静态实现
#define MaxSize 10//最大表长为10
typedef struct
{
	int date[MaxSize];//通过整型数组存取整型数据元素
	int length;//当前表长
}int_Sqlist;//顺序表命名为整型顺序表
int main()
{
	int_Sqlist L;//创建一个顺序表
	return 0;
}

这里我们创建了一个整型数据类型的顺序表,顺序表的最大长度为10,也就是,顺序表中最多只能存放10个元素。

2.1.2 顺序表的初始化

在创建好顺序表后,我们还需要对顺序表进行初始化,如下所示:

//初始化顺序表
void InitList(int_Sqlist* L)
{
	for (int i = 0; i < MaxSize; i++)
		//通过元素下表访问表中的各个元素
		L->date[i] = 0;//当前表中各元素初始化为0
	L->length = 0;//当前表长为0
}
int main()
{
	int_Sqlist L;//创建一个顺序表
	InitList(&L);//通过传址传参实现对顺序表中各个元素的修改
	return 0;
}

通过定义一个初始化函数,我们就能完成对表中的各个元素进行初始化,以及表长的初始化。此时我是因为今天不对其他操作进行演示,所以当前表长我是将其初始化为0。此时我们是可以不用对表中的元素进行初始化的,因为当前表长为0时,表示的是此时表中不存在任何元素。

2.1.3 顺序表的打印

在完成初始化之后,我们还可以将顺序表中的全部元素打印出来,如下所示:

//打印顺序表中的各个元素
void PrintList(int_Sqlist L)
{
	for (int i = 0; i < MaxSize; i++)
		printf("L.date[%d] = %d\n", i, L.date[i]);
}
int main()
{
	int_Sqlist L;//创建一个顺序表
	InitList(&L);//通过传址传参实现对顺序表中各个元素的修改
	PrintList(L);//通过传值传参实现对顺序表中的各个元素进行打印
	return 0;
}

这里我们需要注意一个问题,此时顺序表的当前表长为0,我们通过现在的打印方式是属于违规打印的,正常复合要求的打印方式应该是:

//打印顺序表中的各个元素
void PrintList(int_Sqlist L)
{
	//for (int i = 0; i < L.length; i++)//通过当前表长来打印表中的各个元素
	for (int i = 0; i < MaxSize; i++)//通过最大表长打印表中的元素属于违规打印
		printf("L.date[%d] = %d\n", i, L.date[i]);
}
int main()
{
	int_Sqlist L;//创建一个顺序表
	InitList(&L);//通过传址传参实现对顺序表中各个元素的修改
	PrintList(L);//通过传值传参实现对顺序表中的各个元素进行打印
	return 0;
}

当前表长为0,就表示此时的顺序表中未存放任何元素,所以没有元素打印,但是我们可以先尝试着违规打印一次,看看初始化的效果:

【数据结构】第二章——线性表(2),数据结构,数据结构,算法,c语言,改行学it,开发语言
可以看到,此时我们很好的进行了表中各元素的初始化与打印。当然因为我们正常打印是通过当前表长进行打印的,所以对表中各元素的初始化可以省略,只对当前表长进行初始化就行。不过为了避免不必要的麻烦,建议大家还是在初始化时对表中各个元素也完成初始化。

2.2 动态分配

当我们在创建顺序表时,顺序表的最大表长在后续的操作中可能会出现修改的情况,如果此时我们继续通过静态分配来创建顺序表时,当表中的元素个数超过最大表长时,就会导致数组越界,从而导致程序崩溃。
为了更好的处理这种表长会变化的情况,我们可以通过malloc/calloc/realloc/free这些来创建一个动态顺序表。具体的实现格式如下:

//顺序表的动态实现方式
#define InitSize//通过#define定义一个标识符作为动态顺序表的初始表长
typedef struct Sqlist
{
	ElemType* date;
	//ElemType——数据元素的数据类型
	//ElemType*——指针类型
	//date——指针变量,通过指针来指向顺序表
	int MaxSize, length;
	//MaxSize——动态顺序表的最大表长
	//length——动态顺序表的当前表长
}Sqlist;//动态顺序表的名字

在通过动态分配的方式实现顺序表时,我们需要确定的元素与静态实现的方式稍有不同。在动态分配的实现中,我们需要确定:初始的表长,指向数据元素的指针,顺序表的最大表长,顺序表的当前表长以及数据元素的数据类型

当然,这里的最大表长是会在后续的操作中不断变化的,所以这里我们是以整型变量的方式来确定最大表长,如果通过#define来定义的话,此时定义的是一个不可被修改的常量,这时就无法完成对最大表长的修改了。

2.2.1 整型顺序表的创建

下面我们通过动态分配的方式来创建一个整型顺序表,如下所示:

#define InitSize 5//初始表长为5
typedef struct
{
	int* date;//通过指针指向顺序表
	int MaxSize, length;//定义顺序表的最大表长和当前表长
}Int_Sqlist;//顺序表命名为整型顺序表
int main()
{
	Int_Sqlist L;//创建一个整型顺序表L
	return 0;
}

现在我们已经创建好了一个整型顺序表L,接下来我们就要对顺序表进行初始化了;

2.2.2 顺序表的初始化

与静态分配不同的是,动态分配在初始化时,我们要对顺序表进行动态内存的空间申请,格式如下:

//动态内存申请格式
L->date = (ElemType*)malloc(InitSize * sizeof(ElemType));
//L——创建的顺序表
//date——指向顺序表的指针
//ElemType*——指向顺序表的指针的数据类型
//malloc——分配内存块的函数
//InitSize——初始表长
//sizeof(ElemType)——每个元素所占内存空间大小

因此我们在动态分配时的初始化如下所示:

//初始化顺序表
void InitList(Int_Sqlist* L)
{
	//进行动态内存空间申请
	L->date = (int*)malloc(InitSize * sizeof(int));
	L->length = 0;//当前表长初始化为0
	L->MaxSize = InitSize;//最大表长初始化为初始表长
}
int main()
{
	Int_Sqlist L;//创建一个整型顺序表L
	InitList(&L);//初始化顺序表
	return 0;
}

此时我们就在内存空间中申请了5个连续的整型空间给顺序表进行使用;

2.2.3 修改顺序表的长度

当我们在完成初始化后,如果我们想要修改此时的表长,我们可以通过malloc/calloc进行空间的重新申请,也可以直接通过realloc直接对表长进行修改,如下所示:

//修改表长
void IncreaseSize(Int_Sqlist* L, int len)
{
	//通过realloc修改表长
	L->date = (int*)realloc(L->date, (L->MaxSize + len) * sizeof(int));
	---------------------------------------------------
	//通过malloc/calloc修改表长
	//创建整型指针p指向顺序表原先的空间
	int* p = L->date;
	//通过malloc向内存申请新的空间
	L->date = (int*)malloc((L->MaxSize + len) * sizeof(int));
	//将原先空间中的元素复制到新的空间中
	for (int i = 0; i < L->length; i++)
		L->date[i] = p[i];
	//释放原先申请的空间
	free(p);
}
int main()
{
	Int_Sqlist L;//创建一个整型顺序表L
	InitList(&L);//初始化顺序表
	IncreaseSize(&L, 5);//修改表长
	//正数代表增加表长
	//负数代表减少表长
	return 0;
}
  • 当我们直接通过realloc对表长进行修改时,我们是不需要创建临时的指针变量的;
  • 当我们通过malloc或者calloc来修改表长时,我们需要按照以下的步骤完成修改:
    • 我们需要通过临时的指针变量来指向原先的空间,并通过malloc或者calloc申请新的空间;
    • 在申请完新的空间后,我们再通过临时指针将原先空间的内容复制到新的空间中;
    • 最后将原先的空间通过free给释放掉。

结语

现在咱们对顺序表的静态分配和动态分配与表长的修改就介绍完了,希望这篇内容能帮助大家更加容易理解顺序表的创建与表长的修改过程。

对于动态内存管理相关的内容,后面我会给大家进行详细的介绍,现在还不了解动态内存管理的朋友不要着急,我们先阶段只需要了解顺序表的两种创建方式就可以了。

在下一篇中,我会详细介绍顺序表的其它操作,大家记得关注哦!!!最后感谢各位的翻阅,咱们下一篇再见!!!文章来源地址https://www.toymoban.com/news/detail-778208.html

到了这里,关于【数据结构】第二章——线性表(2)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构基础内容-----第二章算法

    算法 是指,解决问题或执行任务的一系列步骤、规则或指令的有序集合。它可以用来解决各种不同的问题,例如搜索、排序、优化、图像和语音识别等。在计算机科学中,算法通常用于编写程序以实现特定任务。算法可以被用于各种不同的领域,如人工智能、机器学习、数据

    2024年02月06日
    浏览(49)
  • C++算法之旅、05 基础篇 | 第二章 数据结构

    常用代码模板2——数据结构 - AcWing 使用结构体指针,new Node() 非常慢,创建10万个节点就超时了,做笔试题不会用这种方式(优化是提前初始化好数组,但这样跟数组模拟没区别了,而且代码量很长) 使用两个数组,e存储val,ne存储next。空节点next用-1表示 826. 单链表 - AcWi

    2024年02月10日
    浏览(57)
  • 【AcWing算法基础课】第二章 数据结构(部分待更)

    本专栏文章为本人AcWing算法基础课的学习笔记,课程地址在这。如有侵权,立即删除。 邻接表 :存储图和树 e数组存储每个结点的值,ne数组存储每个结点的指向的下一个结点。 数组模拟链表比较快,指针模拟会涉及到new操作,比较慢。 题目链接 :826. 单链表 1.1题目描述

    2024年02月13日
    浏览(50)
  • 数据结构英文习题解析-第二章 链表List

    前言:最近快到FDS考试了,po重刷了一下学校的题目,自己整理了一些解析orz 因为po在自己找解析和学习的过程中非常痛苦,所以在此共享一下我的题目和自己写的解题思路,欢迎各位指出错误~全章节预计会陆续更新,可在专栏查看~ HW2 1. For a sequentially stored linear list of leng

    2024年04月11日
    浏览(53)
  • 从零开始学数据分析之——《线性代数》第二章 矩阵

    元素全为实数的矩阵称为实矩阵  元素全为负数的矩阵称为复矩阵 只有一行(列)的矩阵称为行(列)矩阵 元素全为零的矩阵称为零矩阵 行数和列数都等于n的矩阵称为n阶矩阵或n阶方阵 主对角线元素全为1,其余元素全为0的矩阵称为单位矩阵,记作E或I 两个矩阵行数和列数

    2023年04月23日
    浏览(49)
  • 线性代数 第二章 矩阵

    一、概念 个数排成的m行n列的表格 二、运算法则 三、初等变换 (1)用非零常数k乘矩阵的某一行(列); (2)互换矩阵某两行(列)的位置; (3)把某行(列)的k倍加至另一行(列)。 称为矩阵的 初等行(列)变换 ,统称 初等变换 。矩阵经初等行变换后秩不变。 初等

    2024年02月08日
    浏览(47)
  • 高等数学:线性代数-第二章

    n bm{n} n 元线性方程组 设有 n 个未知数 m 个方程的线性方程组 { a 11 x 1 + a 12 x 2 + ⋯ + a 1 n x n = b 1 a 21 x 1 + a 22 x 2 + ⋯ + a 2 n x n = b 2 ⋯ ⋯ ⋯ ⋯ a m 1 x 1 + a m 2 x 2 + ⋯ + a m n x n = b m begin{cases} a_{11}x_{1} + a_{12}x_{2} + cdots + a_{1n}x_{n} = b_{1} \\\\ a_{21}x_{1} + a_{22}x_{2} + cdots + a_{2n}x_{n} = b

    2024年02月11日
    浏览(42)
  • 线性代数第二章矩阵及其运算详解

    一.线性方程组和矩阵 1.概念 如图所示,该矩阵称为 m行n列矩阵 若行数和列数都等于n,则该矩阵称为 n阶方阵 两个矩阵的行数相等,列数也相等,就称它们为 同型矩阵 若A=(aij)和B=(bij)是同型矩阵,且aij=bij(i=1,2,...,m;j=1,2,...,n),则称 矩阵A与矩阵B相等 ,记作 A=B 2.特殊

    2024年01月25日
    浏览(52)
  • 线性代数(魏福义)——第二章:矩阵及其向量特征

    矩阵 是一个 矩形数表 ,它是研究线性方程组、向量及其变换的重要工具 在数学中,矩阵是一个按照长方形排列的复数或实数集合,它是将一组 有序的数据 视为“ 整体量 ”进行 表述 和 运算 ,从而使问题的表述更加简洁。 2.1.1 矩阵 由 m × n 个数aij排成的 m行n列 的 数表

    2024年02月04日
    浏览(49)
  • <<数值分析>>第二章线性方程组的直接解法

              解线性方程组是工程数学中最常见的模型之一。所说的“最常见”有两方面的含义: 1)一部分工程问题的本身建立的就是线性方程组模型; 2)较多工程问题建立的非线性方程组模型需要转化为线性方程组的求解。           线性方程组为Ax=b,以下介绍

    2024年02月08日
    浏览(56)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包