python 的高阶算法之堆排序

利用完全二叉树的性质来进行堆的运算:
会利用到树的左右孩子判断性质  i=1(根)无双亲,若i>1,则其双亲就是(int/2),向下取整,子结点的编号整除2得到的就是父节点的编号,父结点如果是i,那么左孩子就是2i,右孩子就是2i+1,若2i>n则结点i无左孩子,即结点i为叶子结点,若 2i+1>n 则结点i无右孩子(但是不能说明结点i没有左孩子,否则右孩子结点存在编号为2i+1)
 
二叉树的遍历:
遍历即迭代所有元素一遍
树的遍历: 对树中所有元素不重复的访问一边,也称作扫描
树的遍历次序:
广度优先遍历-->即层序遍历
深度优先遍历-->即三种遍历方法 1.前序遍历,2.中序遍历,3.后序遍历
遍历序列将树中所有元素遍历一遍后,得到的元素的序列,将层次解构转为了线性解构
 
树的层序遍历: -> 按照树的层次,从第一层开始,自左向右遍历元素
 
 
深度优先遍历:
设树的结点为D,左子树为L,右子树为R,且要求L一定再R之前,即可产生以下几种遍历方法;
     前序遍历,即 先根遍历, D L R
     中序遍历,即 中根遍历, L D R
     后序遍历,即 后根遍历, L R D
 
前序遍历:
     从根结点开始由左至右,每个子树内部依然是先根结点,再左子树到右子树,递归遍历
 
顺序为 A-->BDGH-->CEIF
 
中序遍历LDR:
从根结点的最左子树开始遍历,然后根结点,最后右结点
每个子树内部,也是先左子树,后根结点,再根节点,递归遍历
遍历序列:
     
后序遍历L R D:
     先左子树,后右子树,再根结点
     每个子树内部依然是先左子树,后右子树,再根节点,递归遍历
     遍历序列:
 
堆排序:
堆是一个完全二叉树
每个非叶子结点都要大于或者等于其右孩子结点的值称为大顶堆
每个非叶子结点都要小于或者等于其右孩子结点的值称为小顶堆
 
根结点一定是大顶堆中的最大值,一定是小顶堆中的最小值
 
小顶堆:
完全二叉树的每个非叶子结点都要小于或者等于其左右孩子结点的值为小顶堆
根结点一定是小顶堆的最小值
 
 大顶堆
完全二叉树的每个非叶子结点都要大于或者等于其左右孩子结点的值为大顶堆
根结点一定是小顶堆的最大  值
 
构建大顶堆---核心算法:
度数为2的结点A,如果它的左右孩子的结点的最大值比它大的,将这个最大值和该结点交换
度数为1的结点A如果他的左孩子的值大于它,则交换
如果结点A被交换到新的位置,还需和其他孩子结点重复上面的步骤 
 
构建大顶堆--起点结点的选择
从完全二叉树的最后一个结点的双亲结点开始,即最后一层的最右边叶子结点的父结点开始
结点数为n,则起始结点的编号为n//2(性质5)
大顶堆的目标确保每个结点的都比左右结点的值大
 
堆排序:
排序,将大顶堆根结点这个最大值和最后一个叶子结点交换,那么最后一个叶子结点就是最大值,蒋志光叶子结点排除再待排序结点之外
从根结点开始(新的根结点)重新调整为大顶堆后,重复上一步
每次寻找极大值和极小值进行交换!
 
堆排序总结
是利用堆性质的一种选择排序,在堆顶选出最大值或者最小值
时间复杂度     堆排序的时间复杂度为O(nlogn)
由于堆排序对原始记录的排序状态并不敏感,因此无论它是是最好,最坏和平均时间复杂度为O(nlogn)
空间复杂度:
只使用了一个交换用的空间,空间复杂度就是O(1),不稳定的排序算法

posted on 2017-10-23 13:05  pythonerLau  阅读(269)  评论(0编辑  收藏  举报

导航