【开卷数据结构 】 顺序表与链表(一)

简介: 【开卷数据结构 】 顺序表与链表

🌺线性表的定义


线性表:线性表是由n ( n≥0 ) 个数据特性相同的元素构成的有限序列。n是线性表的表长,当 n=0时线性表是一个空表。若用 L 来命名线性表,则其一般表达式为

L  =  (a1,a2,...... ,an)


图像:image.png


a1是唯一的【第一个】数据元素,又称表头元素。an是唯一的【最后一个】数据元素,又称表尾元素。除第一个元素外,每个元素有且仅有一个直接前驱。除最后一个元素外,每个元素有且仅有一个直接后续。


以上就是线性表的逻辑特性,这种线性有序的逻辑结构正是线性表名字的由来。


🌺线性表的特点


从线性表的图像和表达式中可以很明显的看出线性表的特点,那就是


存在唯一的“第一元素”,没有前驱;

除第一元素外,其它元素均有唯一的"前驱"。

存在唯一的“最后元素”,没有后继;

除最后元素外,其它元素均有唯一的"后继";


🌺 顺序表


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


       第1个元素存储在线性表的起始位置,第i个元素的存储位置后面紧接着存储的是第i+1个元素。当我们知道顺序表的第一位元素的地址时,就很容易就可以推理出剩余元素的地址,因此顺序表是一种随机存取的存储结构。

顺序表的特点:表中元素的逻辑顺序与其物理顺序相同

假设线性表L存储的起始位置是 LOC(A),sizeof(ElemType)是每个数组元素所占用的存储空间的大小,那么线性表L的顺序存储如下图所示。


线性表的顺序存储结构

数组下标 顺序表 内存地址
0 a1 LOC(A)
1 a2 LOC(A)+sizeof(ElemType)
... ... ...
i-1 ai LOC(A)+(i-1)*sizeof(ElemType)
... ... ...
n-1 an LOC(A)+(n-1)*sizeof(ElemType)
... ... ...
MaxSize-1 ...

LOC(A)+(MaxSize-1)*sizeof(ElemType)


       每个数据元素的存储位置都和线性表的起始位置相差一个和该数据元素的位序成正比的常数。因此,线性表中的任一数据元素都可以随机存取,所以线性表的顺序存储结构是一种随机存取的存储结构。


看到这里不知道大家有没有感觉很熟悉,似曾相识。没错,我们的老朋友——数组也是一种随机存取的存储结构。因此,通常用高级程序设计语言中的数组来描述线性表的顺序存储结构。


注意:线性表中元素的位序是从【1】开始的,而数组中元素的下标是从【0】开始的.


🌷实现原理


首先我们需要定义一下顺序表的长度,也就是最大有多少个元素。我们采用【define】来确定长度,因为使用【define】可以更方便的进行对长度的修改。

#difine        MAXSIZE        ****        //最大长度


下面,我们用结构体,定义一个新的数据类型。


typedef struct
{   ElemType *elem;  //存储空间基地址    
  int length;     //当前长度
}SqList;            //结构类型为SqList


第一数据域:


在结构体中包含了两个数据域,第一个数据域是elem,很明显,elem是一个指针域,它指向了ElemType类型(在真正实现时,是本来的数据类型)

ElemType:它是element type(“元素的类型”)的简化体


【ElemType *elem】代表着连续空间的首地址,也称基地址,elem类似于数组的名字,它也可以当作数组名字使用。


第二数据域:


第二数据域length表示线性表的数据元素的长度


🌷顺序表的初始化


顺序表的初始化就是建立一个新的空的顺序表


🔺实现原理


1️⃣为顺序表L动态分配一个预定义大小的数组空间,使elem指向这段空间的基地址。

2️⃣将表的当前长度设为0。


💬 代码演示


Status InitList(SqList &L)
{//构造一个空的顺序表L 
  L.elem=new ElemType[MAXSIZE];//为顺序表分配一个大小为MAXSIZE的数组空间  
  if(!L. elem) exit(OVERFLOW);//存储分配失败退出 
  L.length=0;                        //空表长度为0 
  return OK; 
}


🌷顺序表的取值


🔺实现原理

1️⃣判断指定位置是否合理,若不合理,则返回 ERROR。

2️⃣若i值合理,则将第i个元素L.elem[i-1]赋值给参数e,通过e返回第i个数据元素的传值。


💬 代码演示


Status GetElem(SqListL, int i,ElemType &e)
{
  if(i<1||i>L. length) //判断是否合理 
  return ERROR;e=L. elem[i-1];    //elem[i-1]存储第i个数据元素 
  return OK;
}


🌷顺序表的查找


🔺实现原理

1️⃣从第一个元素开始,一个一个与e相比较,若查找成功,返回该元素在表中的位置序号。

2️⃣若查找失败,则返回0。


💬 代码演示


int LocateElem(SqList L,ElemType e)
{//在顺序表1中查找值为e的数据元素,返回其序号
  for(i=0;i<L. length;i++)
  {
  if(L. elem[i]==e) 
    return i+1;
  }
  return 0; 
}


🌷顺序表的插入


线性表的插入操作是指在表的第i个位置插入一个新的数据元素e,使得长度为n的线性表变成长度为n+1的线性表。


❓那么问题来了,应该怎么实现呢?


在线性表的顺序存储结构中,由于逻辑上相邻的数据元素在物理位置上也是相邻的,为了在线性表的第i个位置上插入一个数据元素,则需将第i个至最后一个数据元素依次向后移动一个位置。


🔺实现原理


1️⃣判断插入位置i是否合法(i值的合法范围是1≤i≤n+1),若不合法则返回ERROR。


2️⃣判断顺序表的存储空间是否已满,若满则返回ERROR。


3️⃣将第n个至第i个位置的元素依次向后移动一个位置,空出第i个位置(i=n+1时无需移动)


4️⃣将要插入的新元素e放入第i个位置。


5️⃣表长加一。


🔑空间状态

d411fb3b4b438cdcc709c85d4c1e8f14_watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQ2V5bGFuXw==,size_19,color_FFFFFF,t_70,g_se,x_16.png

41261038b72a583476b25d72f1f105c9_watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQ2V5bGFuXw==,size_19,color_FFFFFF,t_70,g_se,x_16.png




💬 代码演示


Status ListInsert(SqList &L, int i,ElemType e)
{//在顺序表L中第i个位置插入新的元素e,i值的合法范围是1≤i≤L. length+1
  if((i<1)||(i>L. length+1)) 
  return ERROR;//i值不合法
  if(L. length==MAXSIZE) 
  return ERROR;//当前存储空间已满
  for(j=L. length-1;j>=i-1;j--)
  L.elem[j+1]=L.elem[j];
  L.elem[i-1]=e;
  ++L. length;
  return OK;
}


🌷顺序表的删除


和插入同理,在线性表的顺序存储结构中,由于逻辑上相邻的数据元素在物理位置上也是相邻的,为了在线性表的第i个位置上删除一个数据元素,则需将第i个至最后一个数据元素依次向前移动一个位置。


🔺实现原理


1️⃣判断插入位置i是否合法(i值的合法范围是1≤i≤n+1),若不合法则返回ERROR。


2️⃣将第i+1个至第n个元素依次向前移动一个位置。


3️⃣表长减一。


🔑空间状态

5bfc79ea4144f20df6efe206e8a9d4e0_watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQ2V5bGFuXw==,size_19,color_FFFFFF,t_70,g_se,x_16.png

e9a10100fc8c4917dfef14ffb9583df8_watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQ2V5bGFuXw==,size_19,color_FFFFFF,t_70,g_se,x_16.png




💬 代码演示


Status ListDelete(SqList &L, int i)
{//在顺序表L中删除第i个元素,i值的合法范围是1≤i≤L.1ength 
  if(i<1)||(i>L. length)) 
  return ERROR;//i值不合法
  for(j=i;j<=L. length-1;j++)
  L,elem[j-1]=L,elem[j];//被删除元素之后的元素前移
  --L. length;//表长减1
  return OK;
}


🌷顺序表的优缺点


顺序表的内存连续,支持随机访问,可以高效的按下标进行操作,可以很方便的查找表中任一元素。

然而,通过上文不难发现,在做插入或删除操作时,需移动大量元素。当表中数据元素个数较多且变化较大时,操作过程相对复杂。这些问题,以通过线性表的另一种表示方法——链式存储结构来解决。



相关文章
|
2月前
|
存储 算法 Perl
数据结构实验之链表
本实验旨在掌握线性表中元素的前驱、后续概念及链表的建立、插入、删除等算法,并分析时间复杂度,理解链表特点。实验内容包括循环链表应用(约瑟夫回环问题)、删除单链表中重复节点及双向循环链表的设计与实现。通过编程实践,加深对链表数据结构的理解和应用能力。
67 4
|
5天前
|
机器学习/深度学习 存储 C++
【C++数据结构——线性表】单链表的基本运算(头歌实践教学平台习题)【合集】
本内容介绍了单链表的基本运算任务,涵盖线性表的基本概念、初始化、销毁、判定是否为空表、求长度、输出、求元素值、按元素值查找、插入和删除数据元素等操作。通过C++代码示例详细解释了顺序表和链表的实现方法,并提供了测试说明、通 - **任务描述**:实现单链表的基本运算。 - **相关知识**:包括线性表的概念、初始化、销毁、判断空表、求长度、输出、求元素值、查找、插入和删除等操作。 - **测试说明**:平台会对你编写的代码进行测试,提供测试输入和预期输出。 - **通关代码**:给出了完整的C++代码实现。 - **测试结果**:展示了测试通过后的预期输出结果。 开始你的任务吧,祝你成功!
24 5
|
5天前
|
机器学习/深度学习 存储 C++
【C++数据结构——线性表】顺序表的基本运算(头歌实践教学平台习题)【合集】
本文档介绍了线性表的基本运算任务,涵盖顺序表和链表的初始化、销毁、判定是否为空、求长度、输出、查找元素、插入和删除元素等内容。通过C++代码示例详细展示了每一步骤的具体实现方法,并提供了测试说明和通关代码。 主要内容包括: - **任务描述**:实现顺序表的基本运算。 - **相关知识**:介绍线性表的基本概念及操作,如初始化、销毁、判定是否为空表等。 - **具体操作**:详述顺序表和链表的初始化、求长度、输出、查找、插入和删除元素的方法,并附有代码示例。 - **测试说明**:提供测试输入和预期输出,确保代码正确性。 - **通关代码**:给出完整的C++代码实现,帮助完成任务。 文档
22 5
|
19天前
|
数据库
数据结构中二叉树,哈希表,顺序表,链表的比较补充
二叉搜索树,哈希表,顺序表,链表的特点的比较
数据结构中二叉树,哈希表,顺序表,链表的比较补充
|
2月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
80 5
|
2月前
|
存储
顺序表和链表(2)
【10月更文挑战第23天】
顺序表和链表(2)
|
2月前
|
算法
数据结构之购物车系统(链表和栈)
本文介绍了基于链表和栈的购物车系统的设计与实现。该系统通过命令行界面提供商品管理、购物车查看、结算等功能,支持用户便捷地管理购物清单。核心代码定义了商品、购物车商品节点和购物车的数据结构,并实现了添加、删除商品、查看购物车内容及结算等操作。算法分析显示,系统在处理小规模购物车时表现良好,但在大规模购物车操作下可能存在性能瓶颈。
58 0
|
2月前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
265 9
|
2月前
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
42 1
|
5天前
|
存储 C语言 C++
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
116 75