顺序表的基本操作实现

目录

1. 顺序表的定义

2. 顺序表的基本操作的实现 

(1) 插入操作 

(2) 删除操作

(3) 按值查找(顺序查找)


1. 顺序表的定义

  线性表的顺序存储又称顺序表。它是一组地址连续的存储单元依次存储线性表中的数据元素,从而使得逻辑上相邻的两个元素在物理位置上也相邻。

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

#define MaxSize 50                //定义线性表的最大长度
typedef struct{
    ElemType data[MaxSize];       //顺序表的元素
    int length;                   //顺序表的当前长度
}SqList;                          //顺序表的类型定义

  一维数组可以是静态分配的,也可以是动态分配的。 在静态分配时,由于数组的大小和空间事先已经固定,一旦空间占满,再加入新的数据将会产生溢出,进而导致程序崩溃。

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

#define MaxSize 100                //表长度的初始定义
typedef struct{
    ElemType *data;                //指示动态分配数组的指针
    int MaxSize,length;            //数组的最大容量和当前个数
}SeqList;                          //动态分配数组顺序表的类型定义

C的初始动态分配语句为:

L.data = (ElemType*)malloc(sizeof(ElemType)*InitSize);

C++ 的初始动态分配语句为:

L.data = new ElemType[InitSize];

2. 顺序表的基本操作的实现 

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

(1) 初始化 

  为顺序表L动态分配一个预定义大小的数组空间,使 data 指向这段空间的基地址。将表的当前长度设为0。 

bool InitList(SqList &L){
//本算法用于实现初始化顺序表L
    L.data = new ElemType[MaxSize];    //为顺序表分配一个大小为MaxSize的数组空间
    if(!L.data)
        exit(OVERFLOW);                //存储分配失败退出
    l.length = 0;                      //表长度为0
    return true;
}

(2) 取值 

  取顺序表L的第1 <= i <= L.length 个位置元素值,并用e返回。若i的输入不合法,则返回 false ,表示取值失败。

bool GetElem(SqList L, int i, ElemType e){
//本算法用于实现获取顺序表L中第i个元素的值
    if(i <= 1||i >= L.length)                //判断i值是否合理
        return false;
    e = L.data[i-1];
    return true;
}

(3) 插入操作 

  在顺序表L的第 1 <= i <= L.length+1 个位置插入新元素e。若i的输入不合法,则返回 false ,表示插入失败;否则,将顺序表的第i个元素及其后的所有元素右移一个位置,腾出一个空位置插入新的元素e,顺序表长度加1,插入成功,返回 true 。

bool ListInsert(SqList &L, int i, ElemType e){
//本算法实现将元素e插入到顺序表L中第i个位置
    if(i < 1||i > L.length+1)            //判断i的范围是否有效
        return false;
    if(L.length >= MaxSize)                      //判断是否超出数组的最大范围
        return false;
    for(int j = L.length; j >= i; j--)           //将i个元素及之后的元素后移
        L.data[j] = L.data[j-1];
    L.data[i-1] = e;                             //在i位置处插入e
    L.length++;                                  //线性表长度加1
    return true;
}

最好情况:在表位插入,时间复杂度为O(1).

最坏情况:在表头插入,时间复杂度为O(n).

平均情况:假设是在第i个位置上插入一个结点的概率,则在长度为 n 的线性表中插入一个结点时,所需移动结点的平均次数为O((1+n)/2)

因此,线性表插入算法的时间复杂度为 O(n).

(4) 删除操作

  顺序表L的第 1 <= i <= L.length 个位置元素,若成功则返回 true,并将被删除的元素用引用变量e返回,否则返回 false 。 

bool ListDlelete(SqList &L, int i, ElemType &e){
//本算法实现删除顺序表L中第i个位置的元素
    if(i < 1||i > L.length)              //判断i的范围是否有效
        return false;
    e = L.data[i-1];                             //将被删除的元素赋值给e
    for(int j = i; j < L.length; j++)            //将第i个位置后的元素前移
        L.data[j-1] = L.data[j];
    L.length--;                                  //线性表的长度减1
    return true;
}

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

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

平均情况:假设是删除第i个位置上结点的概率,则在长度为 n 的线性表中删除一个结点时,所需的时间复杂度为 O(n).

(5) 按值查找(顺序查找)

  在顺序表L中查找第一个元素值等于e的元素,并返回其次序。

int LocateElem(SqList L, ElemType e){
//本算法实现查找顺序表中值为e的元素,如果查找成功,返回元素位序,否则返回0
    int i;
    for(i = 0; i<L.length; i++)
        if(e == L.data[i])
            return i+1;                 //下标为i的元素值等于e,返回其位序i+1
    return 0;
}

最好情况:查找的元素在表头,时间复杂度为O(1).

最坏情况:查找的元素在表尾,时间复杂度为O(n).

平均情况:假设是查找的元素在第 1 <= i <= L.length 个位置上的概率,则在长度为 n 的线性表中查找值为e的元素所需比较的平均次数为(n+1)/2

因此,线性表查找算法的时间复杂度为 O(n).

猜你喜欢

转载自blog.csdn.net/Gefangen/article/details/102537847
今日推荐