数据结构之顺序表

  • 线性表的概念以及性质
    • 线性表是最基本的数据结构之一,它是一组元素(序列)的抽象,抽象的来看线性表,可以类比成一个集合里面的有穷序列,这个序列中的元素都有一个确定的位置,即元素的下标,通常下标都是从0开始编号,这个线性表代表了某类元素的一个集合,同时也记录了元素之间的关系,不包含任何元素的表称为空表。
    • 表中的元素个数称为表的长度;在一个非空的线性表中,存在着唯一一个首元素和唯一一个尾元素,除首元素外,其他每个元素都有一个前驱元素;除末尾元素外,其他每个元素都有一个后继元素。
    • 线性表中是一种线性结构,其中的元素也是一种顺序关系。
  • 表抽象数据类型
    • 线性表既然作为一种数据结构,就需要有它实际的工程意义。即①如何组织其内部的元素,②如何操作表的内部元素。
      • 线性表的存储模式,即线性表如何组织内部元素。
        • 基于各方面的考虑,主要有两种线性表的实现模式。
          • 一、将表中的元素顺序的存放在一大块连续的存储区内,即顺序表。

          • 二、将表元素存放在通过链接构造起来的一系列存储块里,即链接表。

      • 线性表的操作,即如何操作表的内部元素。对于表这种数据结构来说,都应该有增,删,盖,查这四个基本的功能,同时还需要比较等运算,例如python的list就有如下的 基本操作。

    • 线性表的实现不得不考虑的两个条件,①计算机的内存机制(空间复杂度),②操作效率(时间复杂度)。如果对空间复杂度和时间复杂度不熟悉,可参考https://www.cnblogs.com/zknublx/p/5885840.html
  • 顺序表的实现
    • 基本实现方式
      • 表中的元素顺序存放在一片足够的连续的存储区间里,首元素放在存储区的开始位置,其余元素依次顺序存放。元素之间的逻辑关系(可以用下标来表示)可以通过物理存储区的物理位置表示。
      • 通常表中的元素大小可以静态确定(例如,元素是整数或者实数,或者包含一组大小确定的元素的复杂结构),在这种情况下,假设元素大小一致且为c,记第一个元素的地址为Loc (e0),那么第i个元素的地址为:Loc(ei)=Loc(e0)+c*i。
      • 顺序表的两种布局
        • (a) 基本顺序表,这种表的下标是其逻辑地址,可以更具上述公式计算出实际地址,对元素的操作可根据下标来查找,如list[5]= e5,元素的访问是O(1)复杂度的操作。

        • (b)元素置外的顺序表,对于元素外置的顺序表,更好的解决了表数据元素大小不一的情况,因为通过上述公式,可以得到存放元素的链接地址,而存放链接所需的存储量通常很小,这样公式中的c就是一个固定值,通过取链接接着再做一间接访问就能得到数据元素的值了,其操作的复杂度仍是O(1)。

  • 顺序表的操作
    • 创建空表
      • 创建空表时,系统给表分配一块存储区,可将这个存储区分为2块:①信息记录区,②元素存储区。其中信息记录区包括表的容量和元素个数,元素存储区主要用来存储元素。

    • 判断操作
      • 一般判断即判断表是否为空或者表是否满了,通常只要取出num和max进行比对即可,所有判空和判满操作的复杂度都为O(1)。
      • 深入点的判断操作
        • 判断已知下标为i的元素是否满足给定条件,其复杂度也是O(1)。
        • 判断某个元素是否在n个元素的表中,最好的情况下,复杂度为O(1),最坏的情况下查需要查找到第n个,也就是所谓的遍历操作,因此这种情况下的复杂度为O(n),即遍历操作的复杂度也为O(n)。
    • 变动操作
      • 加入元素
        • 尾端加入新元素,假设表未满的状态下,则操作复杂度为O(1)。
        • 在数据表的第i个单元中加入新元素,通常情况下,对于n(其中,n>i)个元素的数据表,第i个单元中已经存入了数据,如果将新元素插入到第i个单元中,并且后面的元素需要保序,就需要把其中n-i个元素向后移动,这样的操作为n-i次,那么时间复杂度就是O(n-i)了,当n很大时,操作的复杂度即为O(n),但n非常小甚至只有几或者i=n时,操作的复杂度就会变为O(1)了。
      • 删除元素
        • 删除尾端元素,操作复杂度为O(1)。
        • 删除其中第i个元素,根据加入元素的逆方式操作,同样知道其操作的复杂度为O(n-i),当n(即,n》i)很大时为O(n),否则为O(1)。
        • 删除符合给定条件的数据项,在这种情况下,首先得遍历找到满足的数据项删除,此时复杂度为O(n),接着还需要处理删除项后面的元素,为了使删除项后面的元素保序,假设n很大,且满足删除条件的项不在尾端,此时保序操作的复杂度也是O(n),由此可知这是两种步骤组合起来的操作,即有操作复杂度为O(2n),去掉n前面的系数2,即总的时间复杂度为O(n)。
  • 顺序表的结构
    • 根据上述描述,可以将顺序表分为两种结构,即①一体式结构和②分离式结构。

    • 对于一体式结构,当存储区满了以后,要想扩大内存就会遇到问题,假设这块存储区两端都有数据,那么就会扩容失败,而分离式结构就比较容易解决这样的问题了,它可以在不改变对象的情况下换一块更大的元素存储区,其操作过程可以按如下操作:
      • 另外申请一块更大的元素存储区
      • 把表中已有的元素复制到新存储区
      • 用新存储区的链接替换旧存储区的链接
      • 插入新元素到新存储区
  • Python的list和tuple
    • list的实现
      • 基于元素下标的高效访问和更新,时间复杂度为O(1)
      • 允许任意加入元素(不会出现由于表满而无法加入新元素的情况),而且在不断加入元素的过程中,表对象的标识(即表示表对象的id)是不变的,因此可以判定python的list采用了分离式实现技术。
      • list的实现策略:在建立空表时,系统分配一块能容纳8个元素的存储区,在执行插入操作(insert 或append等)时,如果元素区满就换一块4倍大的存储区。但如果当时的表已经很大,系统换存储区时容量就只会增倍。这里的很大,在目前已知的值为50000,引入增倍策略主要是为了避免出现过多空闲的存储位置。
    • list的一些主要操作
      • len(),检查表的长度,O(1)操作
      • 元素访问和赋值,索引(index)、尾端加入(append)和尾端删除(pop),O(1)操作。
      • 一般位置的元素加入,替换(replace)、删除(remove)、表连接(extend)等都是O(n)操作。
    • tuple的实现与操作
      • 由于tuple是不变的表,因此不支持改变其内部状态的任何操作,可以判断,索引操作,也可以将tuple编程器list,然后对其进行想要的操作。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值