[数据结构]线性表-----顺序存储结构


写在前面,本篇文章,你将了解到
1.线性表的定义
2.线性表的抽象数据类型及一些基本操作
3.线性表的两大结构介绍:顺序存储结构和链式存储结构
4.顺序存储结构的插入与删除,及优缺点

[数据结构]线性表-----顺序存储结构_第1张图片

1.线性表的定义

字面意思上看,是具有像线一样的性质的表。
例如:

  • ①在某中心广场上,分散着很多人,有大人,也有小孩子,也许还有一些小宠物,这些在广场的人和动物的数据,对于整个广场来说,不能算是线性结构
  • ②我们小时候,放学的时候,老师总是让我们排好队,手拉手走出学校,而且老师会让我们记住自己的前面和后面,以及拉手的小伙伴的人,每次都在固定的位置和固定牵手的人,我们各自都知道自己的前面和后面是谁,如果一根线把放学的队伍串起来,这就可以称为线性表

题外话:按照次序排队做事,遵守秩序从娃娃抓起,每个小朋友都知道自己的前后是谁,当有人不见了,小朋友就是监督员,老师能及时知道谁不见了,出门春游时,老师也能很快的统计人数,有人丢失也能最快时间知道

(思绪满千,不得不回忆一波,那大概是寡人最巅峰的时候,随便牵妹子的手,拉远了拉远了,哈哈)

官方定义:
线性表(List):零个或多个数据元素的有限序列

关键地方:

  • ①一个序列,元素之间是有顺序的,当存在多个元素时,第一个元素无前驱,最后一个元素无后继,其他每个元素都有且只有一个前驱和后继
  • ②线性表强调是有限的,元素个数也是有限的

[数据结构]线性表-----顺序存储结构_第2张图片

如图所示,1 作为第一个元素只有一个后继,2有一个前驱 1和一个后继 3 ,n没有后继
线性表元素个数n(n大于等于0)定义为线性表的长度,当n = 0时,称为空表

另外,在较复杂的线性表中,一个数据元素可以由若干个数据项组成。
例如:
班级名字的信息记录,如下图,每个数据元素代表一条数据,每条数据里面,有学号,姓名,性别,住址,邮箱等数据项
[数据结构]线性表-----顺序存储结构_第3张图片


2.线性表的抽象数据类型

我们先来看一个例子:
还是拿我们之前小时候小朋友排队的例子,

  • ①老师让散乱到处跑的小朋友排好队,并且长期使用这个顺序,这就是一个线性表的创建和初始化过程
  • ②排好队后发现,有的小朋友个子高在前面,有的个子矮在后面,参差不齐,老师就让小朋友解散重新排,这就是一个将线性表置空的操作
  • ③排好队以后,有家长发现有的孩子好可爱,衣服很时尚,可能会问老师,第十个小朋友穿那么可爱,叫什么名字啊,老师就可以告诉家长叫什么名字,这种根据位序得到数据元素也是一种线性表的操作
  • ④老师要知道班级有多少个小朋友,于是排队一个个数,这种就是获得线性表的长度
  • ⑤有些糊涂的家长,可能第一次来接孩子,不知道自己孩子在哪个班,于是一个个班级去问老师,XXX小朋友是不是在这里啊,这种查找某个元素是否在线性表中也是线性表的基本操作
  • ⑥当然,小朋友肯定有时候会加入新的成员或者有的小朋友长大了,需要到高年级的班里学习,就会有人加入有人退出,对于线性表来说就是,插入数据和删除数据
    等等操作。。。。。。
    由此可见,假如我们把小朋友以及对小朋友的一些安排,信息获取,等操作就是线性表的抽象数据类型
ADT 线性表(List)
Data 
     线性表的数据对象
Operation
   InitList(*L) 初始化操作
   ListEmpty(L)线性表为空则返回true
   ClearList(*L)线性表清空
   GetElem(L,i,*e)将线性表中的第i个元素返回给e
   LocateElem(L,e)在线性表L中查找与e相等的元素,如果查找成功,返回该元素在表中的序号,若不成功,返回0
    ListInsert(*L,i,e)在线性表的第i个位置插入e
    ListDelete(*L,i,e)删除线性表中第i个位置的元素,并用e返回其值
    ListLength(L)返回线性表L的元素个数
endADT

在应用时,应用这些基本的线性表操作,可以完成一些更复杂的操作


3.线性表的顺序存储结构

定义: 线性表的顺序存储结构,指的是一段地址连续的存储单元依次存储线性表的数据元素
例如:
跟我们网吧开黑5连坐一样,占了空的位置,五个人按顺序坐,哈哈哈哈哈,我们可以用一维数组来实现顺序存储结构,当我们在网吧找位子的时候,肯定是找风水宝地,比如在哪可以看到漂亮的妹子,然后放下东西占好地,所以我们的第一个位置就非常关键,在线性表中,第一个位置是存储空间的起始位置。
然后,我们有5个人,需要占5个位置,我们估算这个线性表的最大容量,建立一个数组,长度就是这个数组的最大容量
可往往总有人因为恋爱,女朋友的呼唤(来自单身狗的鄙视,哼哼)有人缺席,我们在用来打游戏的座位实际上被使用的只有4个,有1个位置是空的,我们就可以叫其他同学、朋友一起来,往线性表中增加数据,当然最多只能容纳5个人,总不能一个人坐另一个人身上(写到这,脸上露出了邪恶的笑容)

接下来,我们来看线性表的顺序存储结构代码:

#define MAXSIZE 20   //存储空间初试分配量
typedef int ElemType   //ElemType类型根据实际情况而定,我们在这假定是int
typedef struct
{
       ElemType data[MAXSIZE];  //数组存储数据元素,最大值为MAXSIZE
       int length;      //线性表当前长度
}SqList;

顺序存储结构的三个属性:

  • ①存储空间的其实位置:数组data
  • ②线性表的最大存储容量:数组长度MaxSize
  • ③线性表的当前长度:length

敲黑板!!!!!!!!注意!!!!!!
注意区分数组的长度和线性表的长度

  • 数组长度:是存放线性表的存储空间的长度,存储分配后这个量一般是不变的,当然动态分配数组除外
  • 线性表的长度:是指线性表中有多少个元素,随着线性表的插入和删除,这个数量在不断变化
    线性表的长度应该小于等于数组的长度

4.地址计算方法

当我们在数数的时候,通常第一反应都是从1开始,所以我们的线性表也不能免俗,起始也是1,但是C语言中的数组却是从0开始第一个下标,于是就有了数组元素的序号和存放它的数组下标之间存在的对应关系,第i个元素是要存储在数组下标为 i -1 的位置。
[数据结构]线性表-----顺序存储结构_第4张图片
用数组存储顺序表,数组空间要大于当前线性表的长度,因为线性表中可以进行插入删除操作

内存的地址,都是有编号的,就跟电影院的座位一样,存储器中的每个存储单元都有自己的编号,这个编号称为地址。

假设每个数据占用的是c个存储单元,那么线性表中第 i + 1个元素和第 i 个元素的存储位置满足关系:
在这里插入图片描述
所以,对于第 i 个元素来说,可以由A1推算得出,
在这里插入图片描述


5.顺序存储结构的插入与删除

  • ①对于线性表的顺序存储结构来说,我们要返回线性表中的第 i 个位置元素值返回,只要 i 在数组下标范围内,我们返回数组中 i - 1 位置上的值就行,我们来看一组返回值的定义

    #define OK 1
    #define ERROR 0
    #define TRUE 1
    #define FALSE 0
    typedef int Status

    Status GetElem(SqList L,int i, ElemType *e)
    {
    if (L.length == 0 || i < 1 || i > L.length)
    return ERROR;
    *e = L.data[ i - 1];
    return OK;
    }

  • ②插入操作
    当我们要在线性表L中的第 i 个位置插入新元素 e, ListInsert(*L , i , e),就像你在排队进地铁站,或者排队买票的时候,还有2个人就要轮到自己了,有个小姐姐有紧急的事情想排在你前面,那你就必须后退一步,不然小姐姐就没办法进队伍,此时当你后退了以后,后面的所有人都得往后退

思路:

  • 如果插入位置不合理,抛出异常
  • 如果线性表长度大于数组长度,抛出异常或者动态增加容量
  • 从最后一个元素开始向前遍历到第 i 个位置,分别将它们都向后移动一个位置
  • 将要插入的元素填入位置 i 处
  • 表长 + 1
Status ListInsert(SqList *L, int i, ElemType e)
{
       	int k;
		if (L ->length == MAXSIZE)
			return ERROR;
		if (i < 1 || i > L->length)
			return ERROR;
		if  (i <= L-> length)
		{
			for ( k = L->length - 1, k > =i - 1, k--)
			{
				L -> data[k+1] = L->data[k];
			}
		}
		L->data[i - 1] = e;
		L->length++;
		return OK;
}
  • ③删除操作

接着上面的例子,刚刚排到了你前面的小姐姐,突然被一个人抓住,说她骗钱,这个小姐姐,灵活的闪过了众人的追堵,跑出了队伍,此时队伍后面的人又慢慢悠悠的往前移动了一步。。
思路:

  • 如果删除位置不合理,抛出异常
  • 取出删除元素
  • 从删除元素位置开始遍历到最后一个元素位置,分别将它们都向前移动一个位置
  • 表长 减1
Status ListDelete(SqList   *L,int i,ElemType  *e)
{
		int k;
		if (L->length == 0)
			return ERROE;
		if (i < 1 || i>L->length)
			return ERROR;
		*e = L->data[i-1];
		if (i < L->length)
		{
			for (k = i; klength; k++)
			{
				L->data[k-1] = L->data[k];
			}
		}
		L->length--;
		return OK;
}

总结:

线性表顺序存储结构的优缺点:
优点:

  • 1.不需要为表示表中元素之间的逻辑关系增加额外空间
  • 2.可以快速存取表中任一位置的元素

缺点:

  • 1.插入和删除操作需要移动大量元素
  • 2.当线性表的长度变化时,不好确定存储空间容量
  • 3.容易造成存储空间的碎片

你可能感兴趣的:([数据结构])