Skip to content

Latest commit

 

History

History
154 lines (96 loc) · 4.52 KB

005-enhancing-go-code-with-data-structures.md

File metadata and controls

154 lines (96 loc) · 4.52 KB

ds 数据结构

前面介绍了基础类型,和上一章的复杂类型

本章的重点在于更加真实的数据结构, 包括二叉树、链表、hash表、栈、队列

本章主题主要包括以下几个:

  • graph 和 node
  • 计算算法复杂度
  • 二叉树
  • 哈希表
  • 链表
  • 双向链表
  • 队列
  • container标准包中的数据结构
  • 随机树的产生
  • 难破解的密码

graph and node

图,一种数据结构, 图G = 顶点V(node) + 叶子E(edge)

图分两种:

  • 循环图 全部或部分node组成一个闭合的链
  • 非循环图 没有闭合的链

有向图:叶子有方向的。有向非循环图没有闭合的链

算法复杂度

算法的评价依据是计算复杂度, O(n) 比 O(n2) 好

二叉树

二叉树,一个node下最多有两个子node

二叉树的应用场景是:要表达分层数据时, 好处是:树自带排序,还出是删除尽量少做

树的深度,也就是叶子的最大层数, 平衡二叉树,最大叶子深度和最小叶子深度相差不超过1

平衡一个已有二叉树很困难,最容易的是创建的时候就创建一个平衡二叉树。 平衡二叉树的复杂度是log(n),深度是log2(n),

  • 10000, 高度是14
  • 10w,高度是17
  • 100w,高度是20,意思是100w的数据中查找一个值,20次就ok了, 这就是为啥二叉树效率那么高,应用那么广。平衡二叉树的效率非常高,非平衡的效率未知

平衡二叉树在搜索时灵活性非常高,非常高效,她的形状取决于数据加入的顺序, 所以key如果很长很复杂,那么搜索的效率也会很低。

当然某些链表和数组的读取速度比二叉树高,但搜索的时候还是二叉树高。

hash table

hash 是一种数据结构,也是一个很大的概念,和graph一样。 graph其中的一种叫树,树中有一种叫二叉树,二叉树有种叫平衡树, 平衡树中有一种叫avl高度平衡树,上一小结认识了avl。 这一节也只认识hash中的一小类:链式hash。

hash里存储的是kv键值对,链式hash有一个数组,还有个hash函数, 通过这个hash函数,key可以计算出一个唯一的索引, 这个索引也叫bucket(翻译是桶,哈希表也叫哈希桶),bucket就是数组元素

多个key计算的bucket可能重复,这叫哈希冲突,解决方式就是链式。 也就是说特征相同(计算结果相同)的放到同一个桶里,而桶里是用链表存的

一个优秀的hash表,她的值是均匀分布的, 最特殊(差)的情况:所有的值都在一个桶里,这时就退化为纯链表了。

hash的优势在于搜索速度的降低,如果bucket有20个, 那么搜索复杂度会降低很多,空间换时间的典型例子, 一般用于字典搜索,或大数据搜索。

list

链表 双向链表

queue

队列

是链表的一种特殊情况

限制了数据结构的操作,只能 pop 和push, 还要一些其他的约束 fifo

stack

栈 类似队列,不过约束是 filo

container 包

我们可以自己写二叉树、hash、链表、队列、栈,标准库也帮我们做了这些

container包括了3个数据结构:

  • heap
  • list
  • ring

ring是一个环链

container/heap

heap 堆,一种数据结构,可以看成一颗树,go中底层存储可以使用数组或链表

这课树要满足什么条件才能称为heap呢:

  • 完全二叉树(除了最底层,其他层节点都是满的,如果最底层也满了,就是满二叉树)
  • 任意一节点都大于或小于她的后裔节点

那么堆就分两种:

  • 大根堆 - 最大值在根节点上
  • 小根堆 - 最小值在根节点上

heap适用于一些 优先级问题

go中提供的container/heap 是小根堆,常用于优先队列

类型断言:x是一个interface,T是一个类型, x.(T) 表达式就是类型断言,判断x里的值是不是类型T

heap的源码是50行左右,实现的功能是"小根堆"

heap的Pop()是根节点,最小值。复杂一点的优先需要自定义

container/list

双向链表

实现了一个基本的双向链表

container/ring

环链,内部是一个双向链表,只是头尾连接在一起了

heap可以做优先队列,list可以补充一下日常需求,ring真心没想到合适的场景, 可能只是go为了充数(炫耀)写的一些玩具

随机数

math/rand包提供了产生随机数的功能,不过需要先有一个seed种子, 这个seed在使用之前需要先初始化,这个seed会影响到生成的随机数, 如果seed不变,那么多次产生的随机数是一样的