数据结构之线性表(适合初学者+附原创图附代码超详细+更新中)

一、线性表的定义和特点

提前说明:本文为博主原创文章,未经原作者允许不得转载本文内容,否则将视为侵权;需要转载或者引用本文内容请注明来源及原作者,对于不遵守此声明或者其他违法使用本文内容者,本人依法保留追究权。

前言:线性表是一种逻辑结构,意为数据元素之间存在一对一的关系,例如将学生信息数据依照其入学报到时间的先后顺序进行排列,这就组成了一个线性结构,这只是从逻辑关系(表面)上描述数据,而不牵扯到怎么把这些学生信息数据存储到计算机中。而这些数据元素(学生信息数据)怎样在计算机中的存储表示呢,引出定义:数据对象在计算机中的存储表示称为数据元素的存储结构(也称物理结构),这些数据元素在计算机中有两种基本的存储结构,分别是顺序存储结构和链式存储结构。

定义

线性表是具有相同特性数据元素的一个有限序列(别的教材中也写作:由n(n>=0)个数据特性相同的元素构成的有限序列称为线性表)

  • 相同特性:指的是数据元素的数据类型相同。数据元素要么都是整型的(数组a[4]={1,2,3,4};)、要么都是同一种结构体类型的,如下图,姓名+电话号码就可以构成一个结构体类型(struct phonebook{char name[100];int phonenumber; };),下表(被两个矩形框框中了)是两个数据元素,他们的数据类型均为结构体类型。
    在这里插入图片描述

  • 有限:表中的数据元素个数为n(也叫做线性表的长度,n>=0),是有限个元素。当线性表长度n=0时,此时线性表是一个空表。

  • 序列:数学上,序列是被排成一列的对象(或事件);这样每个元素不是在其他元素之前,就是在其他元素之后。这里,元素之间的顺序非常重要(来自百度百科)
    意为:表中数据元素排成一列,体现了一对一的逻辑特性,即:除首元素和尾元素之外的每个数据元素有则仅有一个前驱元素和一个后继元素,首元素只有一个后继元素,尾元素只有一个前驱元素
    我的理解就是,逻辑(表面)关系上,所有的数据元素都在一条直线上,除第一个数据元素和最后一个数据元素之外的每个数据元素有则仅有一个前驱数据元素和一个后继数据元素,第一个数据元素只有一个后继的数据元素,最后一个数据元素只有一个前驱的数据元素,如下:
    在这里插入图片描述

特点

对于非空的线性表或者线性结构的特点:
(1)存在唯一的一个被称作“第一个”的数据元素;
(2)存在唯一的一个被称作“最后一个”的数据元素;
(3)除第一个外,结构中的每个数据元素均只有一个前驱;
(4)除最后一个外,结构中的每个数据元素均只有一个后继;

二、线性表的存储结构

(一).线性表的顺序表示(顺序表)和实现

1.线性表的顺序存储表示(顺序表)

1). 线性表的顺序表示指的是 用一组地址连续的存储单元 依次存储线性表的数据元素,这种表示也称作线性表的顺序存储结构或顺序映像,同时,顺序存储的线性表被称为顺序表,之前C语言中学过的数组就是一种顺序表,因为数组中相邻的数据元素,在存储次序上也是相邻的。

注意:顺序表与有序表要进行区分:
顺序表指的是顺序存储的线性表,是线性表在存储层面上的表示形式,顺序表中相邻的数据元素在存储地址上是一一对应的,顺序表可以有序,可以无序;
有序表指的是这样的线性表:表中所有数据元素以递增或递减方式有序排列,它没有涉及到存储层面。画个图区分下:
顺序表如下:
线性表中a2与a3是相邻的,a2在a3的左侧,这俩数据元素在存储地址上也是相邻的,a2的存储地址2000H在a3存储地址3000H的左侧

在这里插入图片描述

特点:逻辑上相邻的数据元素,其存储次序也是相邻的
有序表如下:
an={1,3,5,7,9};
an={9,7,5,3,1};
特点:表中所有数据元素以递增或递减方式有序排列,数据元素只涉及到逻辑,而不涉及到存储

2). 顺序表中元素存储位置的计算:(类似高中学的等差数列)
在这里插入图片描述在这里插入图片描述为了帮助理解,我作了如下图(有点粗糙,勿介意),其中:

  1. 存储地址,相当于表中数据元素对应的内存编号,a1的存储地址为Loc(a1),因为是线性表第一个数据元素的地址,Loc(a1)也被称为线性表的起始位置或基地址
  2. 内存状态,黄色的表示存储单元,k个存储单元放一个数据元素,图中所示,a1这个数据元素占6个存储单元(补充知识:一般以8位二进制作为一个存储单元,即一个存储单元是一字节);
  3. 逻辑位序,表示的是第几个数据元素,例如:此表中a2是第一个元素,所以它的逻辑位序为2

在这里插入图片描述

3).顺序表具有随机存取的特性在C语言中可用动态分配的一维数组表示,定义如下:

#define MAXSIZE 100	
/* define是宏定义,意为将MAXSIZE定义为100,
   下面出现的MAXSIZE均可替换为100  */
typedef struct{
    
    
/* typedef将struct{ElemType *elem;int length;}
   这种数据类型起了个别名,注意!是数据类型的别名,名为SqList
   举个栗子:typedef int zhengshu,
   意为给int这个数据类型起了个别名叫zhengshu
   int i=3等价于zhengshu i=3  */
ElemType *elem; 
/* ElemType可以替换成int,float,char,struct等数据类型,
   此句是定义数组名elem,数组名是个指针常量,而指针就是地址,
   故而,数组名是数组第一个元素的地址,elem=&elem[0]  */
int length;	//数组elem的长度
}SqList;
SqList L;
/* SqList是struct{ElemType *elem;int length;}结构体类型的别名,
   SqList L,是指定义了SqList类型的变量L,也就是说
   L这个结构体变量里面有两个成员,一个是L.emem,一个是L.length
   举个栗子:zhengshu i就等价于int i  */
L.elem=(ElemType *)malloc(sizeof(ElemType)*MAXSIZE);
// 动态分配内存,malloc(m)开辟m字节长度的地址空间并返回这段空间的首地址

2.顺序表基本操作的实现

1)顺序表的初始化

顺序表(数组)最重要的两个属性为:数组名(数组首元素的地址)、数组长度。只有确定了他俩,才能确定一个数组。
顺序表的初始化,两步走:

  1. 为顺序表L动态分配一个内存空间,使数组名elem(存储的是数组首元素的地址)指向(存储)这段空间的基地址。
  2. 顺序表的长度初始化为0。
Status SqList(Sqlist &L)
{
    
    
  L.elem = new ElemType[MAXSIZE];
  /*C++动态分配内存,确定数组名(数组首元素地址),
    也可以用C语言去写:
    L.elem = (ElemType *)malloc(sizeof(Elemtype)*MAXSIZE);*/
  if (!L.elem) exit(OVERFLOW);//分配内存的时候必须要加的一句话
  L.length = 0;//数组长度
  return OK;
}

2)顺序表的取值

用自己的话表达:取值就是让你取出顺序表(数组)中的第 i 个数据元素,然后用 e 这个变量把这个数据元素装起来。注意!这个 i 是逻辑次序
取值:
要先判断 i 在不在数组的逻辑位序[1,L.length] ( 数学表示:i 属于[1,L.length],i 是整数) 中,如果不在直接返回ERROR,下面的程序不再执行。要是在,那就直接把L.elem[i-1]赋值给e

Status GetElem(SqList L,int i,ElemType &e){
    
    
  if(i<1||i>L.length) return ERROR;//如果i不在[1,L.length],ERROR
  e = L.elem[i-1];
  return OK;
}

3)顺序表的查找

用自己的话表达:查找就是查一查数组中有无一个值为 e 的数据元素。
查找:
根据数组下标,查找数组中有无一个值为 e 的数据元素,如果有,返回它的逻辑位序。
数据元素的逻辑位序 = 数组元素的下标+1
举个栗子:
C语言或者C++语言中,a={1,2,3,4,5};其中,a[3]=4,a[3]的下标是中括号里面的数字为3,而它的逻辑位序为4(a[3]是数组中的第四个元素)

int LocateElem(SqList L,ElemType e){
    
    
  for(i=0;i<length;i++)
    if(e==L.elem[i]) return i+1;//查找成功,返回i+1(逻辑位序)
  return 0;//查找失败,返回0(ERROR)
}

4)顺序表的插入

用自己的话表达:插入就是在逻辑次序为 i 的位置插入一个新的数据元素e
顺序表的插入算法在逻辑关系上的表示过程如下:
(下面是我用软件画的图,比较粗糙,凑活看吧)

在这里插入图片描述
据上图,逻辑关系上,显而易见,要插入一个新数据元素:
Step 1:将逻辑位序 i~n 的元素(蓝色部分)右移,把逻辑位序为 i 的位置空出位置来
Step 2:将新的数据元素 e 放在逻辑位序为 i 的那个位置

存储关系上,怎么去实现呢?首先说哈,插入位置 i 指的是逻辑位序,在 i 属于 [1,L.length+1] 成立的情况并且 L.length<MAXSIZE 成立的情况下才能插入,这个是前提条件!(为啥L.length+1也可以呢,是因为可以在表中最后一个元素的后面插入新元素,所以L.length+1是阔以的) 在这个前提条件下,逻辑位序为 i~n 的元素右移,怎么移动呢,两种移动方法:
一种是从蓝色部分的最左端元素 ai-1 开始,每个元素右移;一种是蓝色部分的最右端元素 an-1 开始,每个元素右移
如果是前一种, ai-1 赋值给 ai ,那等到 ai 赋值给 ai+1 的时候,原先 ai 的值早就被 ai-1 给覆盖住了,所以此办法并不可行;如果是第二种,不存在前一个数据元素的值被覆盖的情况,可以实现。

所以,总结一下,插入:

  1. 要判断插入位置 i 是否属于 [1,L.length+1] 和 L.length<MAXSIZE是否同时成立,有一个不成立,ERROR!
  2. 将逻辑次序为 n~i 的数据元素依次向后移动一个位置,空出第 i 个位置;(i=n+1时,不需要移动数据元素)
  3. 将新数据元素 e 放入第 i 个位置
  4. 表长+1
Status ListInsert(SqList &L,int i,ElemType e)
{
    
    
  int j;
  if(i<1||i>L.length+1||L.length==MAXSIZE)  return ERROR;//前提条件
  for(j=L.length-1;j>=i-1;j--)
  /*注意,j表示的是数组元素的下标,而同一个数据元素的下标比逻辑位序小1,
  逻辑位序n对应的是元素下标是n-1,逻辑位序i对应的元素下标是i-1,逻辑位序n就是表长L.length */
    L.elem[j+1]=L.elem[j];//将当前下标(j)的元素放到后面那个位置(j+1)上
  L.elem[i-1]=e;//将新元素放到第i个位置上(第i个位置就是逻辑次序为i的位置,也是下标为i-1的位置)
  ++L.length;//数组元素的个数多了一个,表长+1,数组的表长就是数组中元素的个数
  return OK;
}

5)顺序表的删除

用自己的话表达:删除就是在逻辑次序为 i 的位置删去对应的数据元素
顺序表的删除算法在逻辑关系上的表示过程如下:
在这里插入图片描述
删除算法相对于插入算法,比较简单,逻辑上,只需要将逻辑次序为i+1 ~ n的数据元素左移即可。存储上,在删除位置 i 属于 [1,L.length] 成立的基础上,将 ai 赋值给 ai-1 ,移完了 ai 之后,开始移 ai+1 ,将 ai+1 赋值给 ai
所以,总结一下,删除:

  1. 要判断删除位置 i 是否属于 [1,L.length] ,不成立,ERROR!
  2. 将逻辑次序为 i~n 的数据元素依次向前移动一个位置(i=n时,不需要移动数据元素)
  3. 表长-1
Status ListDelete(SqList &L,int i){
    
    
  int j;
  if(i<1||i>L.length)  return ERROR;//前提条件
  for(j=i;j<=L.length-1;j++)
  /*删掉的是第i个元素,所以需要移动的是逻辑位序为i+1~n的元素,
  逻辑位序i+1对应的元素下标为i,逻辑位序n对应的元素下标为n-1,其中n=L.length*/
    L.elem[j-1]=L.elem[j];
  --L.length;
  return OK;
}

(二).线性表的链式表示(链表)和实现

1.线性表的链式存储表示

  1. 线性表的链式存储结构的特点是:用一组任意的存储单元存储线性表的数据元素,这组存储单元可以连续也可以不连续,也就是说链式存储结构用离散的存储单元去存储线性表的数据元素

结点(对应的英语单词为node)指的是线性表中数据元素 ai(1<=i<=n)的存储映像,它包括两个部分,一个是数据域部分,一个是指针域部分,因为包括两个部分,所以联想到把一个结点看成一个结构体(随手写一下: one node = struct{数据域部分;指针域部分;})。数据域部分存储的是数据元素的信息(可能是一个数值,可能是一条姓名+电话号码的信息)。指针域部分存储的是直接后继的存储地址。
在这里插入图片描述
n 个结点链接成一个链表,即为线性表(a1, a2, a3 ,……, an)的链式存储结构,被称作链表。链表是一系列的存储数据元素的单元通过指针串接起来形成的。
2) 单链表可由头指针唯一确定

2.单链表基本操作的实现

3.循环链表

4.双向链表

(三).两种存储结构(顺序表和链表)的比较

猜你喜欢

转载自blog.csdn.net/weixin_45418543/article/details/109518934
今日推荐