数据结构理论基础——线性表

      版权声明:本文为博主原创文章,未经博主允许不得转载。          https://blog.csdn.net/u011815404/article/details/88353792        </div>
        <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-f57960eb32.css">
                          <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-f57960eb32.css">
      <div class="htmledit_views" id="content_views">
        <h1><a name="t0"></a>【逻辑结构】</h1>

线性表是零或多个数据元素组成的有限序列,其中,数据元素的个数定义为线性表的长度,当长度为 0 时称为空表,反之称为非空表

一个非空表常记为:(a_1,a_2,...,a_{i-1},a_i,a_{i+1},...,a_n),其中 ai 是表中的第 i 个数据元素,表中的 a_{i-1} 领先于 a_{i}a_{i} 领先于 a_{i+1},称 a_{i-1} 是 a_{i} 的直接前驱元素,a_{i+1} 是 a_{i} 的直接后继元素。当 i=1,2,...,n-1 时,a_{i} 有且只有一个直接后继;当 i=2,3,...,n 时,a_{i} 有且只有一个直接前驱。

【顺序存储结构】

1.概述

线性表的顺序存储结构称为顺序表,常用一维数组来实现,其通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系。 

线性表支持对数据元素的随机访问,因此属于随机存取结构。设顺序表的每个元素占用 c 个存储单元,则第 i 个元素的存储地址为:LOC ( a_ i ) = LOC ( a_1 )+ ( i - 1 ) *c

2.特点

  • 无需为表示结点间的逻辑关系而增加额外的存储空间
  • 可方便地随机读取表中的任一元素
  • 插入或删除运算需要移动大量元素
  • 表长变化较大时,难以确定合适的存储规模

【链式存储结构】

1.单链表

1)概述

单链表是用一组任意的存储单元存放线性表的元素,这组存储单元可以连续,也可以不连续,即逻辑顺序与物理顺序可以不一致,表可以进行扩充。

为了能正确的表示元素间的逻辑关系,每个存储单元在存储数据元素的同时,还必须存储其后继元素所在的地址信息,这两部分构成了数据元素的存储映像,称为结点(Node)。每个结点分为两部分,一部分是存储数据元素的数据域,一部分是存放该结点后继结点地址信息的指针域,通过每个结点的指针域,线性表的数据元素按其逻辑顺序链接在一起,由于每个结点只有一个指针域,因此被称为单链表

2)头指针与头结点

由于单链表中每个结点的存储地址存放在其前驱结点的指针域中,第一个结点没有前驱,因此通常在单链表的开始结点之前设置一个头指针,指向第一个元素所在的结点,因而头指针具有标识单链表的作用;同时,由于最后一个结点没有后继,故通常将终端结点的指针域设为空(NULL)

为便于处理,常在开始节点之前设置一个类型相同的头结点,其数据域不存储任何信息(也可存储链表长度等附加信息),指针域指向开始结点,并使头指针始终指向头结点,这样空表与非空表的处理就统一了。

两者异同:

头指针头结点
指向链表开始结点,若链表有头结点,则指向头结点是为了操作统一与方便而设置的,放在开始节点之前,其数据域一般无意义
具有标识作用,常用头指针冠以链表的名字使对开始结点前插入结点、删除开始结点的操作与其他结点的操作统一,便于操作
无论链表是否为空难,头指针均不为空,其是链表的必要元素头结点不一定是链表的必要元素

3)顺序表与单链表的比较

顺序表由向量实现,是一种随机存取结构,对表中任一结点都可以在 O(1) 时间内直接地存取,而链表中的结点,需从头指针起,顺着链找才能取得。

在链表中的任何位置上进行插入和删除,都只需要修改指针,而在顺序表中进行插入和删除,平均要移动表中近一半的结点,尤其是当每个结点的信息量较大时,移动结点的时间开销就十分大。

因此,若线性表的操作主要是进行查找,宜采用顺序表存储结构;若线性表的操作主要是插入、删除, 宜采用链表做存储结构。

2.循环链表

在单链表中,将尾结点的指针域由空结点改为指向头结点,就使得整个单链表形成了一个环,不增加额外的空间,但却对不少操作带来了方便。其最大特点是,从循环表中任一结点出发,都能访问到表中的其他结点。

但其也存在一定的危险性,即循环链表中没有明显的尾端,可能会使循环链表的处理操作进入死循环,因此需要格外注意循环条件,判断用作循环变量的工作指针是否等于某一定指针(头指针或尾指针),即原来是判断 p->next!=NULL,现在是变为 p->next!=first

为使空链表和非空链表处理一致,通常设置一个头结点。

3.双向链表

对于单链表来说,next 字段仅指向后继结点,不能有效的找到前驱,很多操作及其不便,因此可在单链表的基础上增加一个前驱指针。

由于在双向链表中既有前向链又有后向链,寻找任一个结点的直接前驱结点与直接后继结点变得非常方便。设指针 p 指向双链表中某一结点,则有: p->llink->rlink = p = p->rlink->llink 

4.静态链表

静态链表是用数组来表示单链表,用数组元素的下标来模拟单链表的指针,其每个数组元素都由两个域构成:数据域 data 存放数据元素、游标 cur 存放该元素的后继元素所在的数组下标。

在某些程序设计语言中,没有指针,因此,静态链表的存在具有必要性。其优点在于,删除和插入元素时不需要移动元素,直接修改 next 指针即可,效率较高,其缺点在于,不能动态的修改数组的大小,跟静态数组一样不能按需分配存储空间。

存储结构:


 
 
  1. #define maxSize=n
  2. template<class T>
  3. struct Node{
  4. T data; //数据域
  5. int next; //指针域
  6. }staticLink[maxSize];

【实现】

  1. 顺序表:点击这里
  2. 单链表:点击这里
  3. 循环链表:点击这里
  4. 双向链表:点击这里
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值