二叉树和堆的联系与区分

首先引出树的定义:

1.树就是不包含回路的连通无向图,本质是!!
2.一棵树中的任意两个结点有且仅有唯一的一条路径连通。
3.一棵树如果有n个结点,那么它一定恰好有n-1条边。

二叉树

二叉树是一种特殊的树。二叉树的特点是每个结点最多有两个儿子,左边的叫做左子树,右边的叫做右子树,也就是说,二叉树要么为空,要么由根结点、左子树和右子树组成,而左子树和右子树分别是一棵二叉树,也就是说根结点左右可能为null。

满二叉树与完全二叉树

如果二叉树中每个内部结点都有两个儿子,这样的二叉树叫做满二叉树。

如果一棵二叉树除了最右边位置上一个或者几个叶结点缺少外其它是丰满的,那么这样的二叉树就是完全二叉树。

完全二叉树如何储存

完全二叉树中父亲和儿子之间有着神奇的规律,我们只需用一个一维数组就可以存储完全二叉树。首先将完全二叉树进行从上到下,从左到右编号。我们发现如果完全二叉树的一个父结点编号为k,那么它左儿子的编号就是2k,右儿子的编号就是2k+1。如果已知儿子(左儿子或右儿子)的编号是x,那么它父结点的编号就是x/2。

堆是什么?堆是一种特殊的完全二叉树,只不过父亲与儿子节点间有关系。也就是首先要满足完全二叉树的定义,只有右下角可能有缺。

所有父结点都比子结点要小的完全二叉树我们称为最小堆(Java中的优先级队列PriorityQueue默认最小堆)。反之,如果所有父结点都比子结点要大,这样的完全二叉树称为最大堆。

这里与二叉搜索树的区别是搜索树中根为中间值,左小右大!

堆的创建

把n个元素建立一个堆,首先我们可以将这n个结点以自顶向下、从左到右的方式从1到n编码,即以层序遍历的顺序编码,这样就可以把这n个结点转换成为一棵完全二叉树。紧接着从最后一个非叶结点(结点编号为n/2)开始到根结点(结点编号为1),逐个扫描所有的结点,根据需要将当前结点向下调整,直到以当前结点为根结点的子树符合堆的特性。
一般以堆排序为例,开始给你个无序数组,先把它写成完全二叉树的形式,就是按层编号一样。

堆的插入与删除

若最小(大)堆要进行删除最小(大)数并返回最小(大)数的操作,我们只需要删掉堆顶元素即最小(大)数,将最后一个数放在堆顶,通过比较与左右儿子的大小向下调整即可恢复为最小(大)堆。

若最小(大)堆要进行删除最小(大)数并插入一个新的数的操作,我们只需要删掉堆顶元素即最小(大)数,将新的数放在堆顶,通过比较与左右儿子的大小向下调整即可恢复为最小(大)堆。

若最小(大)堆只需进行插入一个新的数,我们只需要把新的数放在末尾,通过与父亲的比较向上调整即可恢复最小(大)堆。

总结来说就是删除就是删除堆顶元素,如果同时插入则把插入的数放在堆顶。
如果只删除那么堆顶的空缺就由最后一个元素(也就是最下面一行最右边的元素,即当前序号最大的元素)来填补上,再进行调整。
如果直接插的话就把插的数放在最后一个元素的后面,进行调整。

【堆排序(Heap Sort)】

堆排序的基本思想是:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次大值。如此反复执行,便能得到一个有序序列了。

1.构造初始堆。将给定无序序列构造成一个大顶堆(一般升序采用大顶堆,降序采用小顶堆)。
看堆顶的序号,来判断第一个非叶子节点的索引。这点很重要!
2.此时我们从最后一个非叶子结点开始,从左至右,从下至上进行调整。
调整就是找每个非叶子节点的叶子节点是不是比他大,把大的交换上来,这一层交换结束再交换上一层,直到使根节点即堆顶元素为最大值。
这里要注意,如果上一层交换之后,当前层又不满足堆的要求,继续交换

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值