清晰理解堆排序
2017-09-07 14:50
323 查看
堆的定义
一个完全二叉树中,任意父结点总是大于或等于(小于或等于)任何一个子节点,则为大顶堆(小顶堆)。堆的数组存储方式
完全二叉树适合采用顺序存储的方式,因此一个数组可以看成一个完全二叉树。节点编号:树根起,自上层到下层,每层从左至右,给所有结点顺序编号,能得到一个反映整个二叉树结构的线性序列。
编号特点:
从一个结点的编号就可推得其双亲,左、右孩子,兄弟等结点的编号。假设编号为i的结点是ki(1≤i≤n),则有:
①若i>1,则ki的双亲编号为i/2;若i=1,则Ki是根结点,无双亲。
②若2i≤n,则Ki的左孩子的编号是2i;否则,Ki无左孩子,即Ki必定是叶子。因此完全二叉树中编号i>n/2的结点必定是叶结点。
③若2i+1≤n,则Ki的右孩子的编号是2i+1;否则,Ki无右孩子。
注:ki(0≤i≤n)满足数组下标时,则可能的左右孩子分别为2i+1、2i+2。
堆排序的思想(以大顶堆为例)
利用堆顶记录的是最大关键字这一特性,每一轮取堆顶元素放入有序区,就类似选择排序每一轮选择一个最大值放入有序区,可以把堆排序看成是选择排序的改进。将初始待排序关键字序列(R0,R1,R2....Rn)构建成大顶堆,此堆为初始的无序区;
将堆顶元素R[0]与最后一个元素R
交换,此时得到新的无序区(R0,R1,R2,......Rn-1)和新的有序区(Rn);
由于交换后新的堆顶R[0]可能违反堆的性质,因此需要对当前无序区(R0,R1,R2,......Rn-1)调整为新堆。
不断重复此2、3步骤直到有序区的元素个数为n-1,则整个排序过程完成。
算法分析
筛选算法
//最难理解的地方目标:一个所有子树都为堆的完全二叉树。意思就是这个二叉树只差跟节点不满足堆的结构。//很重要,很重要,很重要
如下图:
方法:首先将root和它的左右子树的根结点进行比较,把最大的元素交换到root节点;然后顺着被破坏的路径一路调整下去,直至叶子结点,就得到新的堆。
运用:1.在上文提到的堆排序思想,2-3步骤中将无序区调整为堆的时候用到。
2.初始化堆
初始化堆
从最后一个非叶子节点i(i=n/2,n为节点个数)开始,将以i为根节点的二叉树通过筛选调整为堆。以第一张图为例,编号顺序为8、7、6...1。从最后一个非叶子节就保证了筛选算法的正确性,因为筛选算法的目标是一个所有子树都为堆的完全二叉树。
java实现堆排序
?相关文章推荐
- 清晰理解堆排序
- 理解堆排序
- servlet清晰理解
- 清晰理解互联网络协议
- Golang 如何将一个函数作为另一个函数的输入值,清晰透彻的注释让你理解该如何阅读抽象的代码
- 真的能将一份糟糕的代码重构成结构清晰,理于理解的代码吗?
- 清晰理解业务分析——《七步掌握业务分析》读书笔记(一)
- 文科生清晰理解傅里叶变换
- 清晰理解红黑树的演变---红黑的含义
- 学习java应该如何理解反射?【很清晰的讲解】
- JSON 数据格式,能比较清晰容易理解的解读json
- 深入理解堆排序及其分析
- 我理解的最大堆排序
- 《Android那些事》——清晰理解各个Animation
- 清晰理解 Android Service
- 关于堆排序的理解
- 我见过最清晰的--理解梯度,散度,旋度
- 几个需要清晰理解的概念
- 对堆排序的理解
- 堆数据结构与堆排序的个人理解