408数据结构知识点——第二章 线性表(一)

文章目录

      • 线性表的定义和基本操作
      • 线性表的顺序表示
        • 顺序表的定义
        • 顺序表的实现——静态分配
        • 顺序表的实现——动态分配
        • 顺序表的基本操作——插入
        • 顺序表的基本操作——删除
        • 顺序表的按位查找
        • 顺序表的按值查找

注:内容参考王道2024考研复习指导以及《数据结构》

线性表的定义和基本操作

线性表是具有相同数据类型的 n ( n > 0 ) n(n>0) n(n>0)数据元素有限序列,其中 n n n表长,当 n = 0 n=0 n=0时线性表是一个空表。线性表一般表示为 L = ( a 1 , a 2 , . . . , a i , . . . , a n ) L=(a_1,a_2,...,a_i,...,a_n) L=(a1,a2,...,ai,...,an)

几个概念:

a i a_i ai是线性表中的“第i个”元素在线性表中的位序。

a 1 a_1 a1是表头元素, a n a_n an是表尾元素。

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

线性表的抽象数据类型定义

ADT{

​ 数据对象: D D D={ a i ∣ a i ∈ E l e m S e t , i = 1 , 2 , 3 , . . . , n , n ≥ 0 a_i|a_i\in ElemSet,i=1,2,3,...,n,n\geq0 aiaiElemSet,i=1,2,3,...,n,n0}

​ 数据关系: R R R={ < a i − 1 , a i > ∣ a i − 1 , a i ∈ D , i = 2 , 3 , . . . n |a_{i-1},a_i \in D,i=2,3,...n <ai1,ai>ai1,aiD,i=2,3,...n}

​ 基本操作:

​ InitList(&L)

​ 操作结果:构造一个空的线性表L;

​ Destory(&L)

​ 初始条件:线性表L已经存在

​ 操作结果:销毁线性表L

​ ClearList(&L)

​ 初始条件:线性表L已经存在

​ 操作结果:将L重置为空表

​ ListEmpty(L)

​ 初始条件:线性表L已存在

​ 操作结果:若L为空表,则返回TRUE,否则返回FALSE

​ ListLength(L)

​ 初始条件:线性表L已存在;

​ 操作结果:返回线性表L中的数据元素个数;

​ GetElem(L,i,&e)

​ 初始条件:线性表L已存在,1<=i<=ListLengh(L)

​ 操作结果:用e返回L中第i个数据元素的值;

​ LocateElem(L,e)

​ 初始条件:线性表L已存在

​ 操作结果:返回L中第1个值与e相同的元素在L中的位置。若这样的数据元素不存在,则返回值为0。

​ PriorElem(L,cur_e,&pre_e)

​ 初始条件:线性表L已存在

​ 操作结果:若cur_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,L长度加1;

​ ListDelete(&l,i)

​ 初始条件:线性表L已存在且非空,1≦i≦ListLength(L)

​ 操作结果:删除L的第i个数据元素,L长度减1

​ TraverseList(L)

​ 初始条件:线性表L已存在

​ 操作结果:对线性表L进行遍历,在遍历过程中对L的每个 结点访问一次

}ADT List

线性表的顺序表示

顺序表的定义

顺序表——用顺序结构的方式实现线性表

特点:

随机访问,即可以在 O(1) 时间内找到第 i 个元素。

②存储密度高,每个节点只存储数据元素。

③拓展容量不方便(即便采用动态分配的方式实现,拓展长度的时间复杂度也比较高)。

④插入、删除操作不方便,需要移动大量元素。

顺序表的实现——静态分配

给各个数据元素分配连续的存储空间,大小为MaxSize*sizeof(ElemType)

“数组”存满后无法更改

#define MaxSize 10//定义最大长度
typedef struct {
    ElemType data[MaxSize];
    int length;
}SqList;
//初始化线性表
void Initlist(SqList &L){
	L.length=0;
}
顺序表的实现——动态分配
#define InitSize 10//定义最大长度
typedef struct {
    ElemType *data;
    int MaxSize;
    int length;
}SqList;
//初始化线性表
void Initlist(SqList &L){
    L.data=(ElemType *)malloc(InitSize*sizeof(ElemType));
	L.length=0;
    L.MaxSize=InitSize;
}
void IncreaseSize(SqList &L,int len){
    int *p=L.data;
    L.data=(ElemType *)malloc((L.MaxSize+len)*sizeof(ElemType));
    forint i=0;i<L.length;i++{
        L.data[i]=p[i];//将数据复制到新区域
        L.MaxSize=L.MaxSize+len;//顺序表最大长度增加1en
        free(p);
}
顺序表的基本操作——插入
bool ListInsert(SqList &L,int i,ElemType e){
    if(i<1 || i>L.length+1){
        return false;
    }
    if(L.length >= MaxSize){
        return false;
    }
    for(int j=L.lengthlj>=i;j--){
        L.data[j]=L.data[j-1];
    }
	L.data[i-1]=e;
    L.length++;
}

时间复杂度分析

最好情况:新元素插入到表尾,不需要移动元素i = n+1,循环0次;最好时间复杂度 = O(1);

最坏情况:新元素插入到表头,需要将原有的 n 个元素全都向后移动i = 1,循环 n 次;最坏时间复杂度 = O(n);

平均情况:假设新元素插入到任何一个位置的概率相同,即 i = 1,2,3, … , length+1 的概率都是 p = 1 n + 1 p=\frac{1}{n+1} p=n+11,循环 n 次;i=2 时,循环 n-1 次;i=3,循环 n-2 次 …… i =n+1时,循环0次。平均循环次数 = n p + ( n − 1 ) p + ( n − 2 ) p + … … + 1 ⋅ p = n ( n + 1 ) 2 1 n + 1 = n 2 np + (n-1)p + (n-2)p + …… + 1⋅p =\frac{n(n+1)}{2}\frac{1}{n+1}=\frac{n}{2} np+(n1)p+(n2)p+……+1p=2n(n+1)n+11=2n平均时间复杂度 = O(n)

顺序表的基本操作——删除
bool ListDelete(SqList &L,int i,ElemType &e){
    if(i<1||i>L.length)//判断i的范围是否有效
        return false;
    e=L.data[i-1];//将被删除的元素赋值给e
    for(int j=i;j<L.length;j++){
        L.data[j-1]=L.data[j];
    }
    L.length--;
    return true;

时间复杂度分析

最好情况:新元素插入到表尾,不需要移动元素i = n+1,循环0次;最好时间复杂度 = O(1);

最坏情况:新元素插入到表头,需要将原有的 n 个元素全都向后移动i = 1,循环 n 次;最坏时间复杂度 = O(n);

平均情况:假设新元素插入到任何一个位置的概率相同,即 i = 1,2,3, … , length+1 的概率都是 p = 1 n p=\frac{1}{n} p=n1,循环 n 次;i=2 时,循环 n-1 次;i=3,循环 n-2 次 …… i =n+1时,循环0次。平均循环次数 = n p + ( n − 1 ) p + ( n − 2 ) p + … … + 1 ⋅ p = n ( n − 1 ) 2 1 n = n − 1 2 np + (n-1)p + (n-2)p + …… + 1⋅p =\frac{n(n-1)}{2}\frac{1}{n}=\frac{n-1}{2} np+(n1)p+(n2)p+……+1p=2n(n1)n1=2n1平均时间复杂度 = O(n)

顺序表的按位查找
ElemType GetElem(SqList L, int i){
    return L.data[i-1];
}
顺序表的按值查找
int LocateElem(SeqList L,ElemType e){
    for(int i=0;i<L.length;i++){
        if(L.data[i]==e){
            return i+1; //数组下标为i的元素值等于e,返回其位序i+1
        }
    }
	return 0; //退出循环,说明查找失败
}

时间复杂度分析

最好情况:新元素插入到表尾,不需要移动元素i = n+1,循环0次;最好时间复杂度 = O(1);

最坏情况:新元素插入到表头,需要将原有的 n 个元素全都向后移动i = 1,循环 n 次;最坏时间复杂度 = O(n);

平均情况:假设新元素插入到任何一个位置的概率相同,即 i = 1,2,3, … , length+1 的概率都是 p = 1 n p=\frac{1}{n} p=n1,循环 n 次;i=2 时,循环 n-1 次;i=3,循环 n-2 次 …… i =n+1时,循环0次。平均循环次数 = n p + ( n − 1 ) p + ( n − 2 ) p + … … + 1 ⋅ p = n ( n + 1 ) 2 1 n = n 2 np + (n-1)p + (n-2)p + …… + 1⋅p =\frac{n(n+1)}{2}\frac{1}{n}=\frac{n}{2} np+(n1)p+(n2)p+……+1p=2n(n+1)n1=2n平均时间复杂度 = O(n)

你可能感兴趣的:(数据结构,考研)