数据结构-顺序表

顺序表

顺序表的定义

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

顺序表的特点是表中元素的逻辑顺序与其物理顺序相同。所以插入和删除操作需要移动大量元素。

线性表的顺序存储结构是一种随机存取的存储结构。

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

#define MaxSize 50		//定义线性表的最大长度
typedef struct{
    ElemType data[MaxSize];		//用静态的“数组”存放数据元素
    int length;		//顺序表的当前长度
}SqList;		//顺序表的类型定义(静态分配方式)

//基本操作-初始化一个顺序表
void InitList(SqList &L){
    for(int i=0; i<MaxSize; i++)
        L.data[i]=0;		//将所有数据元素设置为默认初始值
    L.length=0;		//顺序表初始长度为0
}

int main(){
    SqList L;		//声明一个顺序表
    InitList(L);		//初始化顺序表
    //....未完待续,后续操作
    return 0;
}

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

而在动态分配时,存储数组的空间大小是在程序执行过程中通过动态分配语句分配的。

#define InitSize 100		//表长度的初始定义
typedef struct{
    ElemType *data;		//指示动态分配数组的指针,指向顺序表中第一个数据元素
    int MaxSize;		//顺序表的最大容量
    int length;			//顺序表的当前长度
}SeqList;		//顺序表的类型定义(动态分配方式)

void InitList(SeqList &L){
    //用malloc函数深情一片连续的存储空间
    L.data=(int *)malloc(InitSize*sizeof(int));
    L.length=0;
    L.MaxSize=InitSize;
}

//增加动态数组的长度
void IncreaseSize(SeqList &L, int len){
    int *p=L.data;
    L.data=(int *)malloc(InitSize*sizeof(int));
    for(int i=0; i<L.length; i++){
        L.data[i]=p[i];		//将数据复制到新区域(时间开销大)
    }
    L.MaxSize=L.MaxSize+len;		//顺序表最大长度增加 len
    free(p);		//malloc和free函数需要使用头文件 #include <stdlib.h>
}

int main(){
    SeqList L;		//声明一个顺序表
    InitList(L);		//初始化顺序表
    //...往顺序表中随便插入几个元素...
    IncreaseSize(L, 5);
    return 0;
}

c的初始动态分配语句为

L.data=(ElemType *)malloc(sizeof(ElemType)*InitSize);
//(ElemType*):malloc函数返回一个指针,需要强制转型为你定义的数据元素类型指针
//sizeof(ElemType):一个数据元素所占存储空间的大小,如int占4个字节
//malloc函数的参数,指明要分配多大的连续内存空间

c++的初始动态分配语句为

L.data=new ElemType[InitSize];

Key:动态申请和释放内存空间

c—malloc、free函数

c++—new、delete关键字

顺序表的特点

  1. 随机访问,即可在o(1)时间内找到第i个元素
  2. 存储密度高,每个节点只存储数据元素
  3. 拓展容量不方便(即便采用动态分配的方式实现,拓展长度的时间复杂度也比较高)
  4. 插入删除操作不方便,需要移动大量元素

顺序表的基本操作-插入

ListInsert(&L,i,e):插入操作。在表L中的第i个位置(位序)上插入指定元素e。

#define MaxSize 10		//定义线性表的最大长度
typedef struct{
    ElemType data[MaxSize];		//用静态的“数组”存放数据元素
    int length;		//顺序表的当前长度
}SqList;		//顺序表的类型定义(静态分配方式)

void ListInsert(SqList &L,int i,int e){		//在L的位序i处插入元素e
    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
}

//插入的元素要合法,于是ListInsert函数改版为
bool ListInsert(SqList &L,int i,int e){
    if(i<1||i>L.length+1)		//判断i的范围是否有效
        return false;
    if(L.length>=MaxSize)		//当前存储空间已满,不能插入
    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;
    //好的算法,应该具有“健壮性”。能处理异常情况,并给使用者反馈
}

int main(){
    SqList L;		//声明一个顺序表
    InitList(L);		//初始化顺序表
    //...此处省略一些代码,插入几个元素
    ListInsert(L,3,3);
    return 0;
}

插入操作的时间复杂度:关注最深层循环语句的执行次数与问题规模n的关系。问题规模n=L.length(表长)

在这里插入图片描述

顺序表的基本操作-删除

ListDelete(&L,i,&e):删除操作。删除表L中第i个位置的元素。并用e返回删除元素的值。

bool Delete(SqList &L,int i,int &e){
    //为什么是int &e,而不是int e:e是引用型变量,加了引用符号
    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.leng--;		//线性表的长度减1
    return true;
}

int main(){
    SqList L;		//声明一个顺序表
    InitList(L);		//初始化顺序表
    //...此处省略一些代码,插入几个元素
    int e = -1;		//用变量e把删除的元素“带回来”
    if(ListDelete(L,3,e))
        printf("已删除第3个元素,删除元素值为=%d\n",e);
    else
        print("位序i不合法,删除失败\n");
    return 0;                       
}

删除操作的时间复杂度:关注最深层循环语句的执行次数与问题规模n的关系。问题规模n=L.length(表长)

在这里插入图片描述

顺序表的基本操作-查找

查找分为按位查找与按值查找。

顺序表的按位查找

GetElem(L,i):按位查找操作。获取表L中第i个位置的元素的值。

#define MaxSize 10		//定义线性表的最大长度
typedef struct{
    ElemType data[MaxSize];		//用静态的“数组”存放数据元素
    int length;		//顺序表的当前长度
}SqList;		//顺序表的类型定义(静态分配方式)

ElemType GetElem(SqList L,inti){
    return L.data[i-1];		//时间复杂度o(1)
}
#define InitSize 10		//表长度的初始定义
typedef struct{
    ElemType *data;		//指示动态分配数组的指针,指向顺序表中第一个数据元素
    int MaxSize;		//顺序表的最大容量
    int length;			//顺序表的当前长度
}SeqList;		//顺序表的类型定义(动态分配方式)

ElemType GetElem(SqList L,inti){
    return L.data[i-1];		//时间复杂度o(1)
}

顺序表的按值查找

LocateElem(L,e):按值查找操作。在表L中查找具有给定关键字值的元素。

#define InitSize 10		//表长度的初始定义
typedef struct{
    ElemType *data;		//指示动态分配数组的指针,指向顺序表中第一个数据元素
    int MaxSize;		//顺序表的最大容量
    int length;			//顺序表的当前长度
}SeqList;		//顺序表的类型定义(动态分配方式)

//在顺序表L中查找第一个元素值等于e的元素,并返回其位序
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;		//退出循环,说明查找失败
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值