《啊哈!算法》阅读笔记-神奇的树

ps:详情可见《啊哈!算法》第7章

ps:从自己的印象笔记里复制过来的,某些小标号和格式有一点问题,想要看的清晰的可以留言印象笔记分享给你

 

  1. 定义:树是指任意两个结点间有且只有一条路径的无向图。(或者说树其实就是不包含回路的连通无向图)

  2. 树的特性:

  • 一棵树中的任意两个结点有且仅有唯一的一条路径连通。

  • 一棵树中如果有n个结点,那么他一定恰好有n-1条边。

  • 在一棵树中加一条边将会构成一个回路。

   3.每个结点都有深度,深度是指从根到这个结点的层数(根为第一层)。

 

二叉树

  1. 特点:每个结点最多有两个儿子(子树)。

  2. 满二叉树:每个内部结点都有两个儿子;或者说所有的叶结点都有同样的深度;深度为h且有2h-1个结点的树。

  3. 完全二叉树:若二叉树的高度为h,除第h层外,其他各层结点数都达到最大个数,第h层从右向左连续缺若干结点,则这个二叉树就是完全二叉树。(如果一个结点有右子结点,那么它一定也有左子结点)

  4. 完全二叉树中父亲与儿子之间有着神奇的规律,只需要用一个一维数组就可以存储完全二叉树。将完全二叉树从上到下,从左到右编号(如下图),如果一个父结点的编号是k,那么它的左儿子的编号就是2*k,右儿子的编号就是2*k+1。如果已知儿子(左或右)的编号是x,那么它父结点的编号就是x/2

     

  1. 如果一棵完全二叉树有N个结点,那么这个完全二叉树的高度为log2N,简写为logN,即最多有logN层结点。(实际上是logN去掉小数部分并加上1层)

  2. 完全二叉树最典型的的应用就是堆。

 

堆——神奇的优先队列

  1. 最小堆:所有父结点都比子结点小。

  2. 最大堆:所有父结点都比子结点大。

    ps:以下只讨论最小的情况,最大时情况类似。

  1. 找最小的数的几种情况:

  • 每次删除最小的数,并增加一个数:删除根结点(最小的数),将新增的数放在根结点,然后向下调整。

  • 每次新增一个数,依旧求最小的数,但不删除:在末尾添加上一个新的结点,将该节点向上调整。插入第N个数的时间复杂度为O(logN)。

  • 每次删除最小的数:(我的想法)可以维护一个队列,计算的时候减去head的下标,这样子计算N次后多占用N单位的空间;或者每次将末尾的结点放到根结点去维护,这样子计算N次后多用了N*logN的时间。(分号前的想法是错误的,因为通过队列维护的时候,本质上改变了树的所有节点的排列顺序,而分号后的想法正是堆排序的一种方法,时间复杂度就为 O(N*logN ) )

  1. 建立一个最小堆的方法:

  • 从空的堆开始,每一次插入一个结点,然后向上调整,插入第 i 个元素的时间是log i,所以插入所有元素的整体时间复杂度是O(N*logN)

  • 还有一种更为巧妙的方法,将所有数依次输入进堆,确保每个节点的子节点满足最小堆的特性,所有的叶结点因为没有子节点,所有肯定满足特性,因此,从第 n/2(n/2是最后面一个非叶节点,可以思考一下)个节点开始处理,每次和子节点比较,确保子节点满足最小堆特性,即向下调整。(注意,向下调整是具有延续性的,不是只比较一次,而是比较到确保子节点都满足最小堆特性为止)不太理解为什么该方法的时间复杂度是O(N)?

  1. 堆排序的两种方法:

  • 事实上堆排序就是每次删除最小的元素,然后将删除的元素都输出的排序方法。

  • 每次删掉一个,然后将末尾的节点放到根结点再向下调整,O(N*logN)。

  • 还有一种方法,维护一个最大堆,然后每次将根结点与末尾节点的数交换,将堆的长度减1,并将根结点向下调整,这样最后树就是按从小到大的顺序排列的。这种方法事实上只是节省了空间,时间方面并没有改进。

 

并查集

  1. 并查集也称为不相交集数据结构。

  2. 并查集通过一个一维数组来实现,其本质是维护一个森林。刚开始时,森林里每个点都是孤立的,也可以理解为每个点就是一棵只有一个结点的树,之后通过一些条件,将这些点合成一棵大树。合并的过程就是“认爹”的过程,在“认爹”的过程中,要遵循“靠左”原则和“擒贼先擒王”原则。在每次判断两个结点是否已经在同一棵树中的时候,也要注意必须求其根源,中间父亲结点是不能说明问题的,必须找到其祖宗(根结点),判断两个根结点的祖宗是否是同一个根结点才行。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值