数据结构复习笔记1——绪论

绪论

什么是数据结构

数据结构是相互之间存在一种或多种特定关系的数据元素集合,这种数据元素之间的关系称为结构。数据结构包括:逻辑结构、存储结构、数据运算。

逻辑结构

逻辑结构指的是数据元素之间的逻辑关系,即从逻辑关系上描述数据。它与数据的存储方式没有关系,独立于计算机。(例如,线性表既可以用顺序存储方式的数组实现,也可以用链式存储方式的单链表实现,没有必然关系)

数据的逻辑结构主要有:

  • 线性结构数据元素一对一):
    • 一般线性表
      • 顺序表(数组实现)
      • 单链表(链式实现,利用指针
    • 受限线性表
      • 栈(后进先出
      • 队列(先进先出
      • 串(字符串匹配,BF算法和KMP算法
    • 线性表推广
      • 数组
      • 广义表
  • 非线性结构:
    • 集合(数据元素除了同属一个集合外,没有任何联系)
    • 树形结构:(数据元素一对多,所有节点入度为0
      • 二叉树(一个节点只有两个孩子节点)
      • 一般树(一个节点有任意多个孩子节点)
    • 图状结构:(数据元素多对多
      • 邻接表(链式表示图)
      • 邻接矩阵(数组表示图)

存储结构

  • 顺序存储
    • 逻辑上相邻的元素存放在物理上相邻的存储单元中,最典型的例子是数组。数据元素之间的关系通过存储单元的邻接关系体现(比如要求当前元素的下一个元素,只需要访问当前存储单元的下一个存储单元即可)
    • 优点:
      • 可以随机存取(例如,OS的逻辑文件中的直接文件,一旦知道存储开始位置,直接通过所求元素的脚标即可访问对应的元素),数据读取和修改较快,时间复杂度为O(1)。
      • 每个元素只占用最少的存储空间(不需要存放指针,只用占用一个存储单元即可)
    • 缺点:
      • 所需的存储单元必须是连续的(类似于OS中的连续内存分配机制),因此会产生大量的外部碎片(比如,一个数组 int[] arr = new int[100],需要100个连续的int型,即4个字节的空间,虽然目前的内存中有400字节的空闲空间,但是它们被分割开来了,所以无法使用,这些被割裂开来的小孔即为外部碎片,如果是链式存储的话,可以非连续地存放在这些小孔中)
      • 数据的插入和删除需要挪动之后所有的元素,较慢,时间复杂度为O(n)。
    • 实例:数组
  • 链式存储
    • 不要求逻辑上相邻的数据元素在物理位置上也相邻。数据元素之间的逻辑关系采用指示元素物理位置的指针来表示。
    • 优点:
      • 非连续存储,因此可以充分利用碎片空间,不会产生碎片现象,空间利用率高
      • 不考虑定位问题,数据的插入和删除直接修改指针即可,较快,时间复杂度为O(1)。
    • 缺点:
      • 需要在每个元素中额外占用空间存放指针。
      • 只能顺序存取访问和修改数据较慢,时间复杂度为O(n)。
    • 实例:单链表
  • 索引存储
    • 在存储元素信息时,建立附加的索引表,索引表中的每一项都是索引项,格式为(关键字,地址)。既可以让数据元素以非连续的方式存储,也可以直接存取数据元素。
    • 优点:
      • 检索速度快(直接链式存储,一个100GB的文件要读完100GB才能获取到最后的元素,而100GB的文件,其索引表可能只有100MB,大大减少了需要遍历的数据量)
      • 不会出现碎片现象(非连续存储)
    • 缺点:
      • 附加的索引表需要占用额外的空间(其实就相当于把链式存储每一个元素的指针提出来到一张大表中了)
      • 插入删除数据也要修改索引表,花费时间较长
    • 实例:Mysql数据库索引
  • 散列存储
    • 使用哈希(hash)函数,根据元素的关键字直接计算出该元素的存储地址。
    • 优点:
      • 检索、增加、删除结点的操作都很快。因为可以在O(1)的时间复杂度内通过函数计算的方式直接定位到对应元素的物理位置。
    • 缺点:
      • 如果散列函数(哈希函数)不好,可能出现存储元素的冲突(哈希碰撞现象),需要花费时间和空间解决冲突(拉链法、二次探测法等)
    • 实例:hashmap、hashset、hashtable

数据运算

数据运算的定义是针对逻辑结构的,表示运算的功能

数据运算的实现是针对存储结构的,表示运算的具体步骤

易错点

  • 如何区分逻辑结构和存储结构:
    • 如果一个数据结构,只能被一种存储结构所实现,例如:单链表(链式存储)、顺序表(顺序存储)、哈希表(散列存储)、循环队列(顺序存储),那么必然和存储结构有关。
    • 如果一个数据结构,可以被多种存储结构实现,例如:队列、栈、二叉树,那么就是逻辑结构。
  • 逻辑结构独立于存储结构,它是抽象表达的,在设计逻辑结构时不需要考虑存储结构的实现。但设计存储结构时,需要考虑数据的逻辑结构,因为存储结构是逻辑结构在计算机上的映射。
  • 链式存储设计中,结点内的存储单元地址(逻辑地址)一定连续
  • 针对两种不同的数据结构,其逻辑结构或物理结构不一定相同:例如,二叉树和二叉排序树,逻辑结构和物理结构可以相同。

算法的概念

定义:算法是对特定问题求解步骤的一种描述,它是指令的有限序列,其中每条指令表示一个或多个操作

5大特性:

  • 有穷性:算法必须在有穷步之后结束,每一步都必须在有穷时间完成。(死循环的程序不是算法
  • 确定性:算法中每条指令必须有确切的含义,对于相同的输入只能得到相同的输出
  • 可行性:算法中描述的操作可以通过已经实现的基本运算执行有限次实现。
  • 输入:一个算法有零个或多个输入。
  • 输出:一个算法有一个或多个输出。

目标:

  • 正确性。算法能正确地求解目标问题。
  • 可读性。算法能够被人们理解。
  • 健壮性。针对非法输入,能够有效处理。
  • 效率与低存储量需求。良好的时间和空间复杂度。

时间复杂度

  • 算法中最深层循环内的语句被重复执行次数的数量级,即为算法的时间复杂度。
  • 包括:
    • 最好时间复杂度
    • 最坏时间复杂度
    • 平均时间复杂度
  • 一般考虑的时间复杂度都是最坏时间复杂度。

空间复杂度

  • 算法需要耗费的存储空间的数量级。
  • 算法原地工作的含义是所需要的额外的辅助空间是常数级别的

时间复杂度和空间复杂度往往不可兼得,需要平衡。

  • 以时间换空间:
    • 虚拟内存技术
    • 交换技术
    • 覆盖技术
  • 以空间换时间:
    • 动态规划技术
    • Cache技术

时间复杂度和空间复杂度只考虑最大的数量级,且不考虑常数项。

复杂度如何计算

扫描二维码关注公众号,回复: 12645835 查看本文章
  • 时间复杂度计算(单个循环体)
    • 直接关注循环体的执行次数,设为k
  • 时间复杂度计算(多个循环体)
    • 两个运算规则:乘法规则,加法规则。

易错点

  • 时间复杂度不等于执行次数,它描述的是一个数量级
  • 计算时间、空间复杂度时需要在脑子中模拟清楚。
  • 时间复杂度指的是:渐进时间复杂度,所以O(n)总是优于O(nlogn),不应找特殊值。
  • 递归程序的时间复杂度要进行数学推导。

参考资料:

1、https://hillzhang1999.gitee.io/2020/05/29/shu-ju-jie-gou-fu-xi/#toc-heading-1

猜你喜欢

转载自blog.csdn.net/ProQianXiao/article/details/109227257