线性表的顺序表示及实现

简介: 线性表的顺序表示及实现

线性表的定义和特点

1. 定义

线性表(Linear List):由n(n>=0)个具有相同特性的数据元素(结点)a1,a2, ... , 组成的有限序列。

  • 其中数据元素的个数n定义为表的长度;
  • 当n = 0 时称为空表;
  • 将非空的线性表(n>0)记作:(a1 , a2 , ... , an)
  • 这里的数据元素ai(1 <= i <= n)只是一个抽象的符号,其具体含义在不同的情况下可以不同。

2.线性表的逻辑特征

  1. 在非空的线性表中,有且仅有一个开始结点a1,它没有直接前趋,而仅有一个直接后继;
  2. 有且仅有一个终端结点a1,它没有直接后继,而仅有一个直接前趋a ~n-1~ ;
  3. 其余的内部结点a~i~(2 <= i <= n-1)都有且仅有一个直接前趋a ~n-1~和一个直接后继a ~n+1~;
  4. ==线性表是一种典型的线性结构==。

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

ADT List{
    数据对象 : D = {a[i] | a[i]属于Element,(i=1,2,...,n)}
    数据关系 : R = {<a[i-1],a[i]> | a[i-1],a[i]属于D,(i=1,2,...,n)}
    基本操作 :
     InitList(&L);       DestroyList(&L);
     ListInsert(&L,i,e);   ListDelete(&L,i,&e);
     ......等等
}ADT List

线性表的顺序表示

把逻辑相邻的数据元素存储在物理上相邻的存储单元中的存储结构。知道某个元素的存储位置就可以计算出其他元素的存储位置。
假设线性表的每个元素需占 l 个存储单元,则第i+1个数据元素的存储位置和第i个数据元素的存储位置之间满足关系:
==Loc(a~i+1~) = Loc(a~i~) + l==
由此,所有数据元素的存储位置均可由第一个数据元素的存储位置得到
==Loc(a~i~) = Loc(a~1~) + (i +1) x l==

顺序表的元素地址连续、依次存放、随机存取、类型相同,所以可用数组来表示顺序表; 线性表的长度可变,因此用一变量表示顺序表的长度属性。

#define LIST_INIT_SIZE 100    //线性表存储空间的初始分配量
typedef struct {
    ElemType elem[LIST_INIT_SIZE ];
    int length;    //当前长度
}

例如,多项式的顺序存储结构类型定义为:
p~n~(x) = p~1~(x)x^e1^ + p~2~(x)x^e2^ + ... + p~m~(x)x^em^,
线性表 P = ( (p1,e1) , (p2,e2) , ... , (pm,em) );

#define MAXSIZE 1000    //多项式可能达到的最大长度

typedef struct {    //多项式非零项的定义
    float p;        //系数
    int e;          //指数
}Polynomial;

typedef struct {
    Polynomial *elem;        //存储空间的基地址
    int length;              //多项式中当前项的个数
}SqList;                     //多项式的顺序存储结构类型为SqList

顺序表的基本实现

1. 线性表L的初始化

Status initList_Sq(SqlList &L){          //构造一个空的顺序表L
    L.elem = new ElemType[MAXSIZE];      //为顺序表分配空间
    if(!L.elem)                          //存储空间分配失败
        return;
    L.length = 0;                        //空表长度为0
    return;
}

2. 销毁顺序表L

void DestroyList(SqList &L){
    if(L.elem)
        delete L.elem;         //释放存储空间
}

3. 清空顺序表L

void ClearList(SqList &L){
    L.length = 0;              //将线性表的长度置为0
}

4. 求线性表L的长度

int DestroyList(SqList L){
    return L.length;

5. 判断线性表是否为空

int IsEmpty(SqList L){
    if(L.length == 0) return 1;
    else return 0;
}

6. 顺序表的求值(根据位置i获取相应位置数据元素的内容)

int GetElem(SqList L,int i,ElemType &e){
    if(i<1||i>L.length)
        return ERROR;       //判断i值是否合理,若不合理,返回ERROR
    e = L.elem[i-1];        //第i-1的单元存储着第i个数据
    return OK;
}

7. 顺序表的查找

算法思想:

  • 在线性表L中查找与指定e相同的数据元素的位置
  • 从表的一段开始,逐个进行记录的关键字和给定值的比较。找到,返回该元素的位置序号,未找到,返回0。
int LocateElem(SqList L,Element e){
//在线性表L中查找值为e的数据元素。返回其序号(是第几个元素)
    for(i=0li<L.length;i++)
        if(L.elem[i] == e) return i+1;   //查找成功,返回序号
    return 0;                  //查找失败,返回0
}

顺序表的查找算法分析:

平均查找长度ASL(Average Search Length):
为确定记录在表中的位置,需要与给定值进行比较的关键字的个数的期望值(平均值)叫做查找算法 的平均查找长度。

对含有n个记录的表,查找成功时:
在这里插入图片描述
其中,Pi为找到第i个记录需要比较的次数。Ci为第i个记录被查找的概率。
顺序查找的平均查找长度:
==ASL=P~1~ + 2P~2~ + ... + (n-1)P~n-1~ + nP~n~==,
假设每个记录的查找概率相等:
则:在这里插入图片描述由此,得顺序表查找的时间复杂度为==O(n) ~ n==

8. 顺序表的插入
线性表的插入运算是指在表的第i个位置上,插入一个新结点e,使长度为n的线性表(a1,... ,ai-1,ai,...,an)变成长度为n+1的线性表(a1,... ,ai-1, e ,ai,...,an)。

算法思想:

  • 判断插入位置i是否合法,
  • 判断顺序表的存储空间是否已满,
  • 将第n至第i位的元素依次向后移动一个位置,空出第i个位置,
  • 将要插入的新元素e放入第i个位置,
  • 表长加1。
Status ListInsert_Sq(SqList &L,int i,ElemType e){
    if(i<1||i>L.length) return;   //i值不合法
    if(L.length == MAXSIZE) return;   //当前存储空间已满
    for(j=L.length-1;j>=i-1;j++){
        L.emel[j+1] = L.elem[j];      //插入位置及之后的元素后移
    }
    L.elem[i-1]=e;                   //将新元素e放入第i个位置
    L.length++;                      //表长加1
    return;
}

在这里插入图片描述
9. 顺序表的删除
线性表的删除操作运算是指将表的第i个结点删除,使长度为n的线性表(a1,... ,ai-1,ai,ai+1...,an)变成长度为n-1的线性表(a1,... ,ai-1, ai+1,...,an)。

算法思想:

  • 判断删除位置i是否合法,
  • 将欲删除的元素保留在e中,
  • 将第i+1至第n位的元素依次向前移动一个位置,
  • 表长减1,删除成功。
Status ListDelete_Sq(SqList &L,int i){
    if(i<1||i>L.length) return;   //i值不合法
    for(j=i;j<=L.length-1;j++){
        L.emel[j-1] = L.elem[j];      //被删除元素之后的元素前移
    }
    L.length--;                      //表长加1
    return;
}

总结

顺序表的优缺点:
优点:

  • 存储密度大(结点本身所占存储量/结点结构所占存储量)
  • 可以随机存取表中任一元素

缺点

  • 在插入、删除某一元素时,需要大量移动元素
  • 浪费存储空间
  • 属于静态存储形式,数据元素的个数不能自由扩充
目录
相关文章
|
Linux
yum镜像源汇总
yum镜像源汇总
5441 0
|
SQL 存储 弹性计算
阿里云EMR 2.0:重新定义新一代开源大数据平台
本次分享主要介绍了阿里云E-MapReduce的开发历程,EMR 2.0的新特性、产品架构,以及EMR 2.0在平台体验、数据开发、资源形态及分析场景等方面的全面突破与创新,重新定义新一代开源大数据平台。
3750 0
阿里云EMR 2.0:重新定义新一代开源大数据平台
|
2月前
|
BI API 语音技术
阿里云百炼平台新人免费额度完整实操指南:领取规则、额度查看、用完即停与API代码调用全解
对于初次接触大模型开发、原型验证、智能应用搭建的个人开发者与企业技术团队来说,平台新人免费额度是降低试错成本的重要资源。开发者可以借助免费额度完成模型能力验证、应用原型调试、业务场景POC测试,不用一开始就投入按量付费成本。百炼大模型服务平台提供面向新开通用户的新人免费推理额度,但这套权益附带地域限制、有效期、额度隔离、账号共享、扣费防护等一系列复杂规则,如果对规则理解不到位,容易出现额度看不到、提前过期、子账号消耗完主账号额度、免费阶段产生意料之外账单等问题。本文完整梳理新人免费额度全部规则,讲解额度获取、多途径查看剩余额度、用完即停防护功能,附带可直接运行curl、Python调用代码,梳
529 1
|
4月前
|
人工智能 API 芯片
重磅!阿里云真武 M890 超节点 Day0 适配 Kimi K3,国产算力支撑近 3 万亿参数大模型
阿里云真武M890超节点实例Day0适配Kimi K3(近3万亿参数),国内首个跑通该规模模型的超节点。依托64卡全互联、9TB显存与ICN Switch高速网络,突破算力瓶颈;软硬协同优化后,首Token时延降35%,单卡吞吐提升1.8倍。在阿里云百炼官网:https://t.aliyun.com/U/fPVHqY 免费领取千万Tokens
561 1
|
5月前
|
存储 人工智能 运维
企业呼叫中心深度选型:SaaS、混合云、私有化部署架构技术对比(2026)
随着企业客服数字化、外呼业务合规化、政企数据安全管控升级,呼叫中心已从传统电话接待工具,演变为全渠道客户联络中台。企业在建设呼叫中心体系时,常会遇到部署架构选择、功能适配、合规落地、系统集成等共性问题。 本文从技术架构、部署模式、业务场景、合规体系、集成能力五个维度,系统性解析企业呼叫中心选型逻辑,客观梳理主流技术方案特征,帮助企业技术负责人、运维、架构师建立标准化选型依据。全文为纯技术调研分析,无商业导向。
1010 0
|
7月前
|
自然语言处理 安全
Stop Fixating on Prompts: Reasoning Hijacking and Constraint Tightening for Red-Teaming LLM Agents(论文解读)
本文提出的JailAgent框架,通过不修改用户提示词的隐式攻击方式,实现了对LLM智能体推理轨迹与记忆检索的高效劫持,兼具高攻击成功率、强泛化性、高隐蔽性与低计算开销,为LLM智能体的红队测试与安全评估提供了全新范式。
346 2
|
数据采集 Java PHP
使用Python+requests简单实现模拟登录以及抓取接口数据
本文通过Python的requests库演示了如何实现模拟登录和抓取接口数据的过程,包括设置请求头、发送POST请求进行登录以及使用登录后的会话进行GET请求获取数据。
1420 1
|
机器学习/深度学习 计算机视觉
sklearn 中 learning_curve 函数 的详细使用方法 (机器学习)
sklearn 中 learning_curve 函数 的详细使用方法 (机器学习)
906 0
sklearn 中 learning_curve 函数 的详细使用方法 (机器学习)
|
NoSQL Linux 网络安全
|
JavaScript
【Vue】npm run serve 和 npm run dev 有什么区别
【Vue】npm run serve 和 npm run dev 有什么区别