【数据结构与算法】线性表、顺序表、静态顺序表、动态顺序表

【数据结构与算法】(二)线性表、顺序表、静态顺序表、动态顺序表

前言

本篇文章大部分内容摘自严蔚敏、李冬梅、吴伟民编著的由人民邮电出版社出版发行的《数据结构:C语言版》。

本文中的所有代码使用C23标准的C语言实现,因此在编译时请加上-std=c2x,代码中若存在错误,欢迎大家在评论区指出。

如果觉得本篇文章对你有帮助的话,不妨点赞、收藏加关注吧!😘❤️❤️❤️

2.1 线性表的定义和特点

线性表是最基本且最常用的一种线性结构,同时也是其他数据结构的基础,尤其是单链表,是贯穿整个数据结构课程的基本技术。

在日常生活中,线性表的例子比比皆是。例如,26个英文字母(A,B,C, …, Z)、学生成绩表等。

从上面的示例中可以看出,它们的数据元素虽然不同,但同一线性表中的元素必定具有相同的特性,即属于同一数据对象,相邻数据元素之间存在着序偶关系。

诸如此类的由n(n >= 0)个数据特性相同的元素构成的有限序列称为线性表。

线性表中的元素个数n(n >= 0)定义为线性表的长度,n = 0时称为空表。

对于非空的线性表或线性结构,其特点是:

  1. 存在唯一的一个被称作“第一个”的数据元素;
  2. 存在唯一的一个被称作“最后一个”的数据元素;
  3. 除第一个之外,结构中的每个数据元素均只有一个前驱;
  4. 除最后一个之外,结构中的每个数据元素均只有一个后继。

2.2 线性表的类型定义

线性表是一个相当灵活的数据结构,其长度可以根据需要增长或缩短,即对线性表的数据元素不仅可以进行访问,而且可以进行插入和删除等操作。

下面给出线性表的抽象数据类型定义(只包含一些基本操作):

ADT List{
    数据对象:D = {a1, a2, ..., an},对象中每个数据元素的类型相同
    数据关系:R = {<a[i], a[i+1]> | 1 <= i < n, a[i], a[i+1] ∈ D}。

    基本操作:
        InitList(&L)
            初始条件:线性表 L 不存在。
            操作结果:构造一个空的线性表 L。
        
        DestoryList(&L)
            初始条件:线性表 L 已存在
            操作结果:销毁线性表 L。
        
        ClearList(&L)
            初始条件:线性表 L 已存在。
            操作结果:将线性表 L 清空。
        
        ListEmpty(L)
            初始条件:线性表 L 已存在。
            操作结果:若 L 为空表,则返回 true,否则返回 false。
        
        ListLength(L)
            初始条件:线性表 L 已存在。
            操作结果:返回线性表 L 的长度。
        
        GetElem(L, i, &e)
            初始条件:线性表 L 已存在,1 <= i <= ListLength(L)。
            操作结果:将线性表 L 中第 i 个位置的元素值返回给 e。
        
        LocateElem(L, e)
            初始条件:线性表 L 已存在。
            操作结果:在线性表 L 中查找与给定值 e 相等的元素,若找到返回其在表中的位置,否则返回 0。

        PriorElem(L,cur_e,&pre_e)
            初始条件:线性表L已存在
            操作结果:若cure_e是L的数据元素,且不是第一个,则用pre_e返回其前驱,否则操作失败,pre_e无定义。
        
        NextElem(L,cur_e,&next_e)
            初始条件:线性表L已存在。
            操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回其后继,否则操作失败,next_e无定义
                
        ListInsert(&L, i, e)
            初始条件:线性表 L 已存在,1 <= i <= ListLength(L) + 1。
            操作结果:在线性表 L 的第 i 个位置插入元素 e。
        
        ListDelete(&L, i, &e)
            初始条件:线性表 L 已存在,1 <= i <= ListLength(L)。
            操作结果:删除线性表 L 中第 i 个位置的元素,并用 e 返回删除的元素值。
        
        TraverseList(L)
            初始条件:线性表L已存在。
            操作结果:对线性表 L 进行遍历,在遍历过程中对 L 的每个结点访问一次。
}

2.3 线性表的顺序存储结构

2.3.1 线性表的顺序存储表示(顺序表)

线性表的顺序表示指的是用一组地址连续的存储单元一次存储线性表的数据元素,这种表示也称作线性表的顺序存储结构或顺序映像。通常,称这种存储结构的线性表为
顺序表(Sequential List),由于顺序表和程序设计语言中定义的数组类似,因此也有人将顺序表称为数组表(Array List)。

顺序表的特点有:

  1. 连续存储:逻辑上相邻的数据元素,其物理次序也是相邻的
  2. 读取速度快(随机访问):由于顺序表是连续存储的,因此,只要确定了存储顺序表的起始位置,顺序表中的任意一个数据元素都可以随机存取(因为可以通过下标直接访问任意位置的元素)。
  3. 插入和删除操作慢:由于顺序表是连续存储的,因此每次删除和插入操作时,为了保证连续存储,需要将插入位置之后的元素向前或向后移动,这就导致顺序表的插入和删除操作较慢。

根据顺序表的最大容量是否固定,我们将顺序表分为静态顺序表和动态顺序表。

其中,静态顺序表的最大容量固定,其元素个数达到最大容量时,无法再向其中插入元素。

动态顺序表在元素个数达到最大容量时,会自动扩容,一般来说都是创建一个容量比原来大的新元素域,然后将旧顺序表中的元素copy过来。

在无特殊说明的情况下,我们的顺序表指的都是静态顺序表。

2.3.2 静态顺序表的实现

2.3.2.1 静态顺序表的头文件申明

建议自己copy一下头文件,然后自己去实现一遍

在此不得不吐槽一句,虽然C23支持了bool true 和 false作为关键字,但是大多数编辑器/插件并没有完全支持,例如vscode上的c/c++插件,只能识别bool是关键字,true和false不是关键字。

#define MAX_SIZE 100

typedef int ElemType;

typedef struct StaticSequenceList{
   
    ElemType *elems;
    unsigned length;

    /* 使用指针封装的方法,在初始化的时候让指针指向对应函数即可 */
    void (*destroy)(struct StaticSequenceList *list);
    void (*clear)(struct StaticSequenceList *list);
    bool (*isEmpty)(struct StaticSequenceList list);
    void (*get)(struct StaticSequenceList list, unsigned i, ElemType *e);
    unsigned (*locate)(struct StaticSequenceList list, ElemType e);
    bool (*getPrior)(struct StaticSequenceList list, ElemType cur_e, ElemType *pre_e);
    bool (*getNext)(struct StaticSequenceList list, ElemType cur_e, ElemType *next_e);
    void (*insert)(struct StaticSequenceList *list, unsigned i, ElemType e);
    void (*delete)(struct StaticSequenceList *list, unsigned i, ElemType *e);
    void (*toString)(struct StaticSequenceList *list);

} StaticSequenceList;

void StaticSequenceList_Init(StaticSequenceList *list);

void StaticSequenceList_Destroy(StaticSequenceList *list);

void StaticSequenceList_Clear(StaticSequenceList *list);

bool StaticSequenceList_isEmpty(StaticSequenceList list);

void StaticSequenceList_Get(StaticSequenceList list, unsigned i, ElemType *e);

unsigned StaticSequenceList_Locate(StaticSequenceList list, ElemType e);

bool StaticSequenceList_LocatePrior(StaticSequenceList list, ElemType cur_e, ElemType *pre_e);

bool StaticSequenceList_LocateNext(StaticSequenceList list, ElemType cur_e, ElemType *next_e);

void StaticSequenceList_Insert(StaticSequenceList *list, unsigned i, ElemType e);

void StaticSequenceList_Delete(StaticSequenceList *list, unsigned i, ElemType *e);

void StaticSequenceList_toString(StaticSequenceList *list);

2.3.2.2 静态顺序表初始化
void StaticSequenceList_Init(StaticSequenceList *list)
{
   
    assert(list);
    l
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值