数据结构与算法——线性表

1.概念

线性表可以看做一种抽象的概念,也可以作为一种抽象数据类型,一个线性表是某类元素的集合,还记录着元素之间的一种顺序关系。相当于一个抽象类,只做定义。

2.具体实现

1.顺序表

顺序表的基本实现方式非常简单:表中元素顺序存放在一片足够大的连续储存区间里,首元素存入储存区的开始位置,其余元素依次顺序存放,元素之间的逻辑关系通过元素在储存区里的物理位置表示(隐式表示元素之间的关系)

顺序表在内存中的布局方式:

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

  1. 创建和访问操作

创建空表时,需要分配一块元素储存,记录表的容量,并将元素计数设置为0,复杂度为O(1)

  1. 简单判断操作

判断表空或表满的操作很容易实现,复杂度都为O(1)

  1. 访问给定下标i的元素

不依赖表中元素个数,因此也是O(1)操作

  1. 遍历操作

要顺序访问表中元素,在遍历过程中记录遍历到达位置,再算出元素位置,即可获取到元素。获取每一个元素的复杂度为O(1),所以遍历整个表的复杂度为O(n)。

  1. 查找给定元素d的位置

这种操作称为检索或查找,采用遍历的操作,顺序比较,时间复杂度O(n)。

  1. 查找给定元素d在位置k之后第一次出现的位置

同5相同,只不过从位置k以后遍历。

  1. 加入元素

在表的尾端加入和删除都很简单,时间复杂度为O(1)。在其他位置添加和删除就要麻烦些,需要移动操作位置后面的数据,向前移动或向后移动,时间复杂度为O(len-i),i为操作位置。

  1. 删除元素

尾端删除元素操作简单,时间复杂度为O(1),一般位置删除O(n),基于条件的删除O(n)。

总结:

优点:O(1)时间的按位置访问,元素在表里储存紧凑,除表元素外,只需要O(1)空间存放少量的辅助信息。

缺点:需要连续的储存区存放表中元素,如果表很大,就需要大片的连续内存空间,一旦确定了储存块的大小,不会随着数据的插入和删除操作进行变动,会有大量空闲单元存在,造成浪费。

2.顺序表的结构

两种基本实现方式

    1. 一体式结构
    2. 分离式结构

  1. 一体式分析

实现比较紧凑,有关信息集中在一起,整体性强,易于管理。

创建后储存区大小固定

  1. 分离式分析

表中只保存于整个表有关的信息,实际元素放在另一个独立的元素储存区对象里,通过链接于基本表对相关连,这样的表对象大小统一,但一个表需要两个独立的对象实现,创建和管理工作复杂。分离式实现的最大优点是带来了一种新的可能,可以在标识不变的情况下,为其对象换一块元素储存区,也就是说可以改变表的容量。

      • 另外申请一块更大的存储区
      • 把表中已有元素复制到新存储区
      • 用新的元素存储区替换原来的元素存储区
      • 实际加入新元素

在扩容的时候如果每次只扩大10个元素储存位置,那么在大量数据插入的时候,需要不停的更换存储位置,元素频繁复制迁移。如果每次扩大当前储存量的一倍,当数据较大的时候,会造成大量的存储空间浪费。所以扩容的时候采用的策略也需要权衡利弊。

3.python的list

基本实现

    1. 基于下标高效访问和更新
    2. 允许任意加入元素,而且在加入过程中表的id不变

解决方案

    1. 由于需要O(1)时间的元素访问,并能维持元素的顺序,这种表只能采用连续表技术
    2. 要求容纳任意多的元素,就必须能更换元素存储区,所以只能采用分离式技术实现。

实际策略

    1. 在建立空表或很小的表时,系统分配一块能容纳8个元素的存储区,如果满了就换一块4倍大的存储区
    2. 如果表的容量达到50000时,换储存区时容量加倍

4.顺序表的简单总结

  1. 最重要的特点是O(1)时间的定位元素访问,更新。很多简单操作的效率也比较高。
  2. 最麻烦的是加入,删除等操作的效率问题
  3. 需要连续的存储空间
  4. 结构不够灵活

2.链接表

    1. 单链表

在这样的结构中,为了掌握一个表,只需要用一个变量保存着这个表的首节点的引用

    • 一个单链表由一些具体的表节点构成
    • 每个节点是一个对象,有自己的标识,也称为该节点的链接
    • 节点之间通过链接建立起单向的顺序联系
    • 链表的结束只需在最后的节点的链接域设置一个None。
2.1.1. 基本操作
    • 创建空链表:只需要把相应的表头变量设置为空链接。
    • 删除链表:丢弃这个链表里的所有节点,python里只需要将表指正赋值为None,python解释器会自动回收不用的存储。
    • 判断是否为空:将表头变量的值与空链接值比较
    • 判断是否满:一般而言链表不会满,除非程序用完了所有的存储空间
    • 首端插入:
      • 创建一个新节点并存入数据
      • 把原链表首节点的链接存入新节点的链接域next
      • 修改表头变量,使之指向新节点
    • 一般情况下的插入
      • 找到插入位置
      • 执行首端操作的三步
    • 删除表首元素:只需修改表头指针,令其指向第二个节点
    • 一般情况下的删除:找到元素前一节点所在位置,next域改为元素后一节点的链接
    • 扫描、定位和遍历:由于单链表只有一个方向的链接,开始时只有表头的链接在掌握中,所以对表内内容的一切检查都只能从表头开始,沿表中链接逐步进行,过程称为扫描。
      • 按下标定位
      • 按元素定位
    • 操作复杂度

      • 创建空表:O(1)
      • 删除表:在python里是O(1)
      • 判断空:O(1)
      • 加入元素或删除:
      • 首端加入:O(1)
      • 尾端加入:O(n)
      • 随意加入:O(n),平均和最坏情况都是
      • 求表的长度:需要扫描整个,得出长度,也可以把长度记录为表的数据成分,O(1)

原文地址:https://www.cnblogs.com/jiaojianglong/p/11260919.html

时间: 2024-10-10 04:46:54

数据结构与算法——线性表的相关文章

数据结构与算法—线性表详解

前言 通过前面数据结构与算法前导我么知道了数据结构的一些概念和重要性,那么我们今天总结下线性表相关的内容.当然,我用自己的理解解分享给大家. 其实说实话,可能很多人依然分不清线性表,顺序表,和链表之间的区别和联系! 线性表:逻辑结构, 就是对外暴露数据之间的关系,不关心底层如何实现. 顺序表.链表:物理结构,他是实现一个结构实际物理地址上的结构.比如顺序表就是用数组实现.而链表用指针完成主要工作.不同的结构在不同的场景有不同的区别. 对于java来说,大家都知道List接口类型,这就是逻辑结构,

数据结构与算法-线性表

近期在学习数据结构,反反复复已经看过几遍了,也做了一些练习题,但总感觉不记录一下,思路就不是很清晰,所以,从今天开始总结这段时间对数据结构的学习. 无论学习什么,基础知识都是最总要的,数据结构也不例外.线性表就是数据结构的基础,很多常见的数据结构都是基于线性表来实现的. 那么,什么是线性表呢?官方的定义是: 零个或多个数据元素的有限序列 可以从两个方面来理解线性表,首先它是一个序列,也就是其中的元素有先后顺序,其次是有限的,对于无线数列,也只能存在于理论数学中. 说了这么多,小结一下: 1)线性

数据结构与算法——线性表顺序存储结构

今天总结一下数据结构中的线性表中的顺序存储结构,这是一种比较简单的结构. 首先,看一下什么是线性表. 什么是线性表? 线性表是一种简单的数据结构,数据元素之间是一对一的关系,即除了第一个和最后一个元素外其余元素都是首尾相接的.元素的个数称为线性表的长度,长度为零则表示线性表为空. 什么是线性表的循序存储结构? 线性表中的顺序存储结构就是把线性表中的元素按逻辑次序依次存放在一组地址连续的存储空间中,也把这种线性表称为顺序表.根据顺序表的特点,通常是用数组来存储元素的. 下面就看具体的实现(C++)

数据结构与算法-线性表的实现(1)

今天来说说线性表的实现 这里以List作为例子 package com.ray.testobject; public class List { private int length; private Man[] array; public int getLength() { return length; } public void setLength(int length) { this.length = length; } public Man[] getArray() { return ar

数据结构与算法-线性表顺序存储结构删除操作的实现

这一章节我们来看一下线性表顺序存储结构删除操作的简单实现 package com.ray.testobject; public class Test { private Object[] list; public Object[] getList() { return list; } /** * 初始化list * * @param num * 元素个数 */ private void iniList(int num) { list = new Object[num]; for (int i =

数据结构与算法--线性表系列(循环链表、双向链表)

hello,everybody,今天我们来学习线性表的最后两种形式,循环链表.双向链表.这两种链表,是链式存储结构的不同形式.书归正传,我们先来看看循环链表吧. 大家思考一个问题,我们把线性表各个元素比作下图的路线图上的城市: 我们的线性表各个结点的指针,都是指向唯一的后继结点,线性表的终端结点的指针为空.这样的话,如果我们在南京,我们需要先访问南京右j边的城市,再访问南京左边的城市.根据线性表的结构,我们只能返回上海,从上海依次访问到北京.因为我们的终端结点的指针为空,如果直接访问南京右边的城

数据结构与算法-线性表的定义与特点

1.线性表概念 线性表是由零个或者多个数据元素组成的有序的序列. 图示: 2.特点 2.1 有序 我们可以从上图看见,线性表里面的元素是一个挨着一个顺序排下去的,就像平常小朋友排队等放学的样子 2.2 允许零元素,也就是空表 2.3 第一个元素有且仅有一个后继,最后一个元素有且仅有一个前驱,其他元素有且仅有一个前驱以及有且仅有一个后继 我们可以从上图看见,线性表里面第一个元素a1,他没有前驱,只有一个a2的后继,最后一个元素an,只有一个前驱a(n-1),没有对应的后继,其他某个元素ai,它有且

数据结构与算法-线性表之双向链表

参考博客: http://www.cnblogs.com/skywang12345/p/3561803.html https://blog.csdn.net/howlaa/article/details/38513235 1.概述 线性表是一种线性结构,由数组.单项链表和双向链表组成,这里讲讨论双向链表的理论知识和实现代码. 双向链表和单项链表类似,双向链表由两个指针作为指针域,分别指向前驱节点和后驱节点.可以从任何节点开始向前或者向后删除.增加.查找节点. 双链表的示意图如下: 在插入节点的时

java数据结构和算法------线性表(顺序表结构)

1 package iYou.neugle.list; 2 3 public class MySeqList<T> { 4 private int initMaxSize = 10; 5 private T[] list; 6 private int listLen = 0; 7 8 public MySeqList() { 9 this.Init(); 10 } 11 12 public MySeqList(int size) { 13 this.initMaxSize = size; 14