数据结构与算法——线性表

线性表

定义和基本操作

定义

线性表是具有相同

数据类型的n(n大于0)个数据元素的有限序列

,其中n为表长,当n=0时线性表是一个空表。若用L命名线性表,则其一般表示为
$$
L = (a1, a2, ..., ai, ai+1, ..., an)
$$
ai时线性表中第i个元素线性表中的位序

a1表头元素

an表尾元素

除第一个元素外,每个元素有且仅有一个直接前驱;除最后一个元素外,每个元素有且仅有一个直接后驱。

基本操作

一个数据结构的基本操作是指最核心、最基本的操作。其它较复杂的操作可通过调用其基本操作来实现。线性表的主要操作如下:

// 1. 初始化表。构造一个空的线性表
InitList(&L)
    
// 2. 求表长,返回线性表L的长度,即L中数据元素的个数
Length(L)
    
// 3. 按值查找操作。在表L中查找具有给定关键字值得元素
LocateElem(L, e)
// 4. 按位查找操作。获取表L中第i个位置的元素的值

Tips:

  1. 对数据的操作——创建销毁、增删改查
  2. c语言函数的定义需要指定参数类型
  3. 实际开发中,可根据实际需求定义其它的基本操作
  4. 函数名和参数的形式、命名都可以改变(Reference:严蔚敏版)
  5. 当需要对参数的修改结果“带回来”的时候传入引用 &

为什么要实现对数据结构的基本操作?

  1. 团队合作编程,你定义的数据结构要让别人可以很方便的使用。
  2. 将常用的操作或运算封装成函数,避免重复工作,降低出错风险。

总结

线性表的物理结构

线性表的顺序表示

线性表的定义

线性表的顺序存储又叫做顺序表。用顺序存储的方式实现线性表顺序存储。把逻辑上相邻的元素存储在物理位置上也相邻的存储单元中,元素之间的关系由存储单元的邻接关系来体现。

假定线性表的元素类型为ElemType,则线性表的顺序存储类型描述为:

#define MAXSIZE 50
typedef struct {
    ElemType data[MAXSIZE];
    int length;
}

此种表示方式是由缺陷的。如果当第51个元素到来时,它是没有地方可以插入的。也就是说,一旦空间占满,在加入新的数据就会产生溢出,进而导致程序崩溃。

所以引出动态分配。

动态分配时,存储空间是在程序执行过程中通过动态存储分配语句分配的,一旦数据空间占满,就需要开辟一块更大的存储空间,用以替代原来的存储空间,从而达到扩充数据空间的目的,而不需要为线性表一次性的划分所有空间。

#define INITSIZE 50
typedef struct {
    // 动态分配数组的指针
    ElemType *data;
    // 数组的最大容量
    int maxsize;
    // 数组的当前个数
    int length;
}

C的初始动态分配语句为

L.data = (ElemType *)malloc(sizeof(ElemType) * INITSIZE)

C++的初始化分配语句为

L.data = new ElemType[INITSIZE]

顺序表的最主要特点是随机访问,即通过首地址和元素需要可在时间O(1)内找到指定的元素。

顺序表的存储密度高,每个节点只存储数据元素。

顺序表逻辑相邻的元素物理上也相邻,所以插入和删除操作需要移动大量的元素。

顺序表上基本操作的实现

插入操作
boll ListInsert(SqList &L, int i, ElemType e) {
    if (i < 1 || i > L.length)
        return false;
    if (L.length > MAXSIZE) 
        return false;
    for(int j = L.length; j >= i; j--) {
        L.data[j] = L.data[j-1]
    }
    L.data[i-1] = e;
    L.length++;
    return true;
}
删除操作
bool ListDelete(SqList &L, int i, int &e) {
    if (i < 1 || i > L.length)
        return false;
    e = data[i-1];
    for(int j = i; j < L.length; j++) {
        L.data[j-1] = L.data[j];
    }
    L.length--;
    return true;
}

最好情况:删除表尾元素,时间复杂度为O(1)

最坏情况:删除表头元素,时间复杂度为O(n)

平均情况:i=1循环n-1次;i=2循环n-2次

故为 0 + 1 + 2 + ... + n-1 平均为(n-1) / 2

按值查找
int LocateElem(SqList L, ElemType e) {
    for(int i=0;i<L.length;i++) {
        if(L.data[i] == e)
            return i+1;
    }
    return 0;
}

最好情况:目标元素在表头,循环一次 O(1)

最坏情况:目标元素在表尾,循环n次 O(n)

平均情况:(1 + 2 + ... + n)/n = (n+1)/n

按位查找

静态分配

ElemType GetElem(SqList L, int i) {
    if (i < 1 || i > L.length) {
        return null;
    }
    return L.data[i-1];
}

《数据结构》考研初试中,手写代码可以直接使用“==”,无论是结构体类型还是基本结构类型。

基本操作小结
posted @ 2022-06-12 11:10  Gazikel  阅读(123)  评论(0编辑  收藏  举报