【数据结构与算法】顺序表的实现

本文系在学习数据结构过程中做的笔记记录,主要参考书籍为《大话数据结构》《算法导论》,文中如有纰漏欢迎指正。

文章目录

      • 1-线性表的定义
      • 2-线性表的抽象数据类型
      • 3- 线性表的顺序存储结构
      • 4-顺序存储结构的插入与删除
      • 5-优缺点

1-线性表的定义

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

用数学语言可以表述如下:
若线性表记为 ( a 1 , ⋅ ⋅ ⋅ , a i − 1 , a i , a i + 1 , ⋅ ⋅ ⋅ , a n ) (a_1, ···, a_{i-1}, a_i, a_{i+1}, ··· , a_n) (a1,,ai1,ai,ai+1,,an),则表中 a i − 1 a_{i-1} ai1领先于 a i a_i ai a i a_i ai领先于 a i + 1 a_{i+1} ai+1,称 a i − 1 a_{i-1} ai1 a i a_i ai的直接前驱元素, a i + 1 a_{i+1} ai+1 a i a_i ai的直接后继元素。当 i = 1 , 2 , ⋅ ⋅ ⋅ , n − 1 i = 1 , 2 ,··· ,n-1 i=12,n1时, a i a_i ai有且仅有一个直接后继,当 i = 2 , 3 , ⋅ ⋅ ⋅ , n i = 2 , 3 ,··· ,n i=23,n时, a i a_i ai有且仅有一个直接前驱。 如下图所示:

【数据结构与算法】顺序表的实现_第1张图片
图1 线性表图示

所以线性表元素的个数 n ( n ≥ 0 ) n(n≥0) n(n0)定义为线性表的长度,当 n = 0 n=0 n=0时,称为空表。

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

线性表的抽象数据类型可以定义如下:

ADT 线性表(List)
Data
operation:
    InitList(*L) ://初始化操作,建立一个空的线性表L
    ListEmpty(L) ://若线性表为空,返回true,否则返回false
    ClearList(*L) ://将线性表清空
    GetElem(L, i, *e) : //将线性表L中的第i个元素返回给e
    LocateElem(L, e) : //在线性表中查找与指定元素e相等的元素,如果查找成功,返回元素在表中的序号;否则返回0表示失败
    ListInsert(*L, i, e) : //在线性表L中的第i个位置插入新元素e
    ListDelete(*L, i, e) : //删除线性表中第i个位置的元素,并用e返回其值
    ListLeng(L) : //返回线性表L的元素个数
endADT

对于不同的应用,线性表的基本操作是不同的,上述操作是最基本的,对于实际问题中涉及的关于线性表的更复杂的操作,可以利用这些基本操作的组合来实现。

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

1-顺序存储的定义

  • 线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表的数据元素。

线性表 ( a 1 , ⋅ ⋅ ⋅ , a i − 1 , a i , a i + 1 , ⋅ ⋅ ⋅ , a n ) (a_1, ···, a_{i-1}, a_i, a_{i+1}, ··· , a_n) (a1,,ai1,ai,ai+1,,an)的顺序存储示意图如下:

【数据结构与算法】顺序表的实现_第2张图片
图1 线性表顺序存储示意

2-顺序存储方式
因为线性表的每个数据元素的类型都相同,所以可以用一维数组来实现顺序存储结构,即把第一个数据元素存储到数组下标为0的位置中,接着把线性表相邻的元素存储在数组中的相邻的位置。
下面是线性表顺序存储结构代码:

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

这里需要注意顺序存储结构的3个属性:

  • 存储空间的起始位置:数组data,它的存储位置就是存储空间的存储位置
  • 线性表的最大存储容量:数组长度MAXSIZE
  • 线性表的当前长度:length

线性表的长度时线性表中数据元素的个数,随着线性表插入和删除操作的进行,这个量是可以变化的,在任何时刻,线性表的长度应该小于等于数组的长度

3-地址计算方法
用数组存储顺序表意味着要分配固定的长度的数组空间,由于线性表中可以进行插入和删除操作,因此分配的数组空间要大于当前线性表的长度。
假设一个元素占用 c c c个存储单元,那么线性表中第 i + 1 i+1 i+1个数据元素的存储位置和第 i i i个元素的存储位置满足如下关系( L O C LOC LOC表示获得存储位置的函数): L O C ( a i + 1 ) = L O C ( a i ) + c LOC(a_{i+1}) = LOC(a_i) + c LOC(ai+1)=LOC(ai)+c,所以对第 i i i个数据元素的存储位置可以用 a 1 a_1 a1推算出来: L O C ( a i + 1 ) = L O C ( a 1 ) + ( i − 1 ) ∗ c LOC(a_{i+1}) = LOC(a_1) + (i-1) * c LOC(ai+1)=LOC(a1)+(i1)c

【数据结构与算法】顺序表的实现_第3张图片
图3 线性表顺序存储示意

4-顺序存储结构的插入与删除

1-获得元素操作
对于线性存储结构来说,如果我们要实现GetElem操作,即将线性表中第i个位置的元素值返回,下面是实现代码:

#define OK 1
#define ERROE 0
typedef int Status;
//Status是函数的类型,其值是函数结果状态代码,如OK等
//初始条件:顺序表 L 已经存在,1 ≤ i ≤ListLength(L)
//操作结果: 用 e 返回L中的第 i 个元素的值
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;
}

2-插入操作
插入算法的思路:

  • 如果插入位置不合理,抛出异常
  • 如果线性表长度大于或等于数组长度,则抛出异常或动态增加容量
  • 从最后一个元素开始向前遍历到第 i 个位置,分别将它们都向后移动一个位置
  • 将要插入元素填入位置 i 处
  • 表长加 1

实现代码如下:

//初始条件:顺序表 L 已经存在,1 ≤ i ≤ListLength(L)
//操作结果: 在L中第 i 个位置之前插入新的数据元素e, L的长度加 1
Status ListInsert(Sqlist *L, int i, ElemType e)
{
    if(L->length == MAXSIZE)    return ERROR;//顺序表已填满
    if(i < 1 || i > L->length + 1)     return ERROR;//i 不在范围内
    if(i <= L->length){//插入数据不在表尾
        for(int k = L->length - 1; k >= i-1; k--){//将要插入位置后的元素向后移动一位
            L->data[k+1] = L->data[k];
        }
    }
    L->data[i] = e;//新元素插入
    L->length ++;
    return OK;
}

3-删除操作
删除算法的思路:

  • 如果位置不合理,抛出异常
  • 取出删除元素
  • 从删除元素位置开始遍历到最后一个元素位置,分别将它们都向前移动一个位置
  • 表长加 1

实现代码如下:

//初始条件:顺序表 L 已经存在,1 ≤ i ≤ListLength(L)
//操作结果: 删除L中的第 i 个元素, 并用e返回其值,L的长度减 1
Status ListDelete(Sqlist *L, int i, ElemType *e)
{
    if(L->length == 0)    return ERROR;//顺序表为空
    if(i < 1 || i > L->length)     return ERROR;//删除位置不正确
    *e = L->data[i - 1];
    if(i < L->length){//如果删除不是最后位置
        for(int k = i; k < L->length; k++){//将删除位置后继元素前移
            L->data[k-1] = L->data[k];
        }
    }
    L->length --;
    return OK;
}

5-优缺点

优点:

  • 无须为表示表中的元素之间的逻辑关系增加额外的存储空间
  • 可以快速地存取表中任一位置的元素

缺点:

  • 插入和删除操作需要移动大量元素
  • 当线性表长度变化较大时,难以确定存储空间的容量
  • 造成存储空间的“碎片”

PS:公众号上线啦,技术干货分享,欢迎关注。

【数据结构与算法】顺序表的实现_第4张图片

你可能感兴趣的:(数据结构与算法)