Skip to content

Latest commit

 

History

History
72 lines (50 loc) · 4.04 KB

2.data_structure.md

File metadata and controls

72 lines (50 loc) · 4.04 KB

数据结构

线性表数据结构

线性表数据结构

数组

  • 数组(Array)是一种线性表数据结构。它用一组连续的内存空间,来存储一组具有相同类型的数据
  • 数组支持随机访问,根据下标随机访问的时间复杂度为O(1)
  • 数组的缺点是大小固定,一经声明就要占用整块连续内存空间

散列表

  • 通过散列函数把元素的键值映射为下标,然后将数据存储在数组中对应下标的位置。当按照键值查询元素时,用同样的散列函数,将键值转化数组下标,从对应的数组下标的位置取数据
  • 装载因子越大,说明空闲位置越少,冲突越多,散列表的性能会下降
  • 常用的散列冲突解决方法有两类,开放寻址法(open addressing)和链表法(chaining)
  • 将链表法中的链表改造为其他高效的动态数据结构,比如跳表、红黑树。极端情况下,所有的数据都散列到同一个桶内,那最终退化成的散列表的查找时间也只不过是 O(logn)。这样也就有效避免了散列碰撞攻击
  • 针对散列表,当装载因子过大时,可以进行动态扩容,重新申请一个更大的散列表,将数据搬移到这个新散列表中。为了解决一次性扩容耗时过多的情况,可以将扩容操作穿插在插入操作的过程中,分批完成

链表

  • 链表通过指针将一组零散的内存块串联在一起
  • 在链表中插入或者删除一个数据,并不需要为了保持内存的连续性而搬移结点,因为链表的存储空间本身就不是连续的。所以,在链表中插入和删除一个数据是非常快速的

跳表

跳表

  • 链表加多级索引的结构,就是跳表
  • 在跳表中查询任意数据的时间复杂度就是 O(logn)。查找的时间复杂度跟 N 分查找是一样的,其实是基于单链表实现了 N 分查找
  • 跳表插入、删除操作的时间复杂度也是 O(logn)
  • 对于按照区间查找数据这个操作,跳表可以做到 O(logn)的时间复杂度定位区间的起点,然后在原始链表中顺序往后遍历就可以了

  • 从栈的操作特性上来看,栈是一种操作受限的线性表,只允许在一端插入和删除数据
  • 用数组实现的栈,叫作顺序栈,用链表实现的栈,叫作链式栈
  • 操作系统给每个线程分配了一块独立的内存空间,这块内存被组织成这种结构, 用来存储函数调用时的临时变量。每进入一个函数,就会将临时变量作为一个栈帧入栈,当被调用函数执行完成,返回之后,将这个函数对应的栈帧出栈

队列

  • 先进者先出,这就是典型的队列
  • 队列也是一种操作受限的线性表数据结构
  • 用数组实现的队列叫作顺序队列,用链表实现的队列叫作链式队列

非线性表数据结构

非线性表数据结构

红黑树

  • 红黑树是一种平衡二叉查找树。为了解决普通二叉查找树在数据更新的过程中,复杂度退化的问题而产生的。红黑树的高度近似 log2n,所以是近似平衡,插入、删除、查找操作的时间复杂度都是 O(logn)
  • 红黑树是一种性能非常稳定的二叉查找树

  • 堆是一个完全二叉树
  • 堆中每一个节点的值都必须大于等于(或小于等于)其子树中每个节点的值。堆顶元素存储的就是堆中数据的最大值或者最小值
  • 用数组来存储完全二叉树是非常节省存储空间的。不需要存储左右子节点的指针,单纯地通过数组的下标,就可以找到一个节点的左右子节点和父节点