排序算法-选择排序-堆排序(包括建堆过程)详解

堆排序:

选择排序的一种以大顶堆为例每次都拿堆顶元素放数组的后边然后再建堆再循环此过程即可

堆排序需要你对二叉树以及堆有一定的了解

栗子:

以数组 a[] = { 16,7,3,20,17,8 }; 为栗

首先建立一个二叉树 

然后开始建堆

建堆(大顶堆)规则:从最后一个非叶子节点n/2-1 开始 (注意理解什么是非叶子节点)分别与左孩子和右孩子比较大小如果最大,则不用调整否则和孩子中的值最大的一个交换位置 然后继续找上一个非叶节点 (如果调整的不是最后一个非叶节点那么在调整它的时候可能会影响它的左右孩子因为它的孩子节点下边可能还有孩子节点 所以如果影响到了则要对其孩子节点继续调整 直到叶子节点为止  可能说的不太清楚 下面会有这种情仔细看建堆的流程就行)

找到最后一个非叶子节点 红色位置 然后和左右孩子节点比较 和最大的交换位置  

 

然后找到下一个非叶子节点 红色位置 然后和左右孩子节点比较 和最大的交换位置  

然后找到下一个非叶子节点 到根节点停止 红色位置 然后和左右孩子节点比较 和最大的交换位置 

注意此时并没有完 这就是我说的那种情况 此时左孩子被交换了 但是左孩子也是一个非叶节点 也要在对其进行判断是否需要调整 如果需要调整 调整了其孩子 如果其孩子还是非叶节点还有进行判断直到叶子节点为止

所以此时 对左孩子进行判断 红色位置 和其左右孩子节点比较 和最大的交换位置 

此时一次建堆完成 然后将堆顶元素和最后一个节点交换 

此时堆顶不满足大顶堆条件了 进行第二次调整  

然后 再让堆顶和最后节点交换位置

这样2个元素就排序好了 此时堆顶又不满足大顶堆条件了 继续调整 循环此过程即可最后结果

算法代码:

public class HeapSort {
    public static void main(String[] args) {
        int[] a={49,38,65,97,76,13,27,49,78,34,12,64};
        int arrayLength=a.length;  
        //循环建堆  
        for(int i=0;i<arrayLength-1;i++){  
            //建堆  
            buildMaxHeap(a,arrayLength-1-i);  
            //交换堆顶和最后一个元素  
            swap(a,0,arrayLength-1-i);  
            System.out.println(Arrays.toString(a));  
        }  
    }
    //对data数组从0到lastIndex建大顶堆
    public static void buildMaxHeap(int[] data, int lastIndex){
         //从lastIndex处节点(最后一个节点)的父节点开始 
        for(int i=(lastIndex-1)/2;i>=0;i--){
            //k保存正在判断的节点 
            int k=i;
            //如果当前k节点的子节点存在  
            while(k*2+1<=lastIndex){
                //k节点的左子节点的索引 
                int biggerIndex=2*k+1;
                //如果biggerIndex小于lastIndex,即biggerIndex+1代表的k节点的右子节点存在
                if(biggerIndex<lastIndex){  
                    //若果右子节点的值较大  
                    if(data[biggerIndex]<data[biggerIndex+1]){  
                        //biggerIndex总是记录较大子节点的索引  
                        biggerIndex++;  
                    }  
                }  
                //如果k节点的值小于其较大的子节点的值  
                if(data[k]<data[biggerIndex]){  
                    //交换他们  
                    swap(data,k,biggerIndex);  
                    //将biggerIndex赋予k,开始while循环的下一次循环,重新保证k节点的值大于其左右子节点的值  
                    k=biggerIndex;  
                }else{  
                    break;  
                }  
            }
        }
    }
    //交换
    private static void swap(int[] data, int i, int j) {  
        int tmp=data[i];  
        data[i]=data[j];  
        data[j]=tmp;  
    } 
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值