基本概念:

  二叉堆是完全二叉树或者是近似完全二叉树。

  当父结点的键值总是大于或等于任何一个子节点的键值时为最大堆

  当父结点的键值总是小于或等于任何一个子节点的键值时为最小堆

  一般将二叉堆简称为堆。

 基本思想:

  1.把n个元素建立最大堆,把堆顶元素A[0]与待排序序列的最后一个数据A[n-1]交换;

  2.把剩下的n-1个元素重新建立最大堆,把堆顶元素A[0]与待排序序列的最后一个元素A[n-2]交换;

  3.把剩下的n-2个元素重新建立最大堆,把堆顶元素A[0]与待排序序列的最后一个元素A[n-3]交换;

  重复以上步骤,直到把最后两个元素建成最大堆并进行交换,得到的序列就是排序后的有序序列。

 

 堆排序是不稳定的排序算法,时间复杂度为:O(NlogN).

 Java实现:

package sort;
public class  HeapSort{
    public static void main(String[] args) 
    {
        new HeapSort().run();
    }
    public void run(){
         int [] a={17,8,45,84,2,94};
        int len=a.length;  
        /**
         * 循环建堆  
         */
        for(int i=0;i<len-1;i++){  
            /**
             * 建堆,建一次最大堆,寻到一个待排序序列的最大数  
             */
            buildMaxHeap(a,len-1-i);  
            /**
             * 交换堆顶(待排序序列最大数)和最后一个元素  
             */
            swap(a,0,len-1-i);  
        }  
        
        for(int j=0;j<len;j++){
            System.out.print(a[j]+" ");
        }
    }
    /**
     * 对数组 从0到lastIndex建大顶堆
     */
    public void buildMaxHeap(int[] arr, 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;
                /**
                 * 如果k节点的左子节点biggerIndex小于lastIndex,即biggerIndex+1代表的k节点的右子节点存在
                 */
                if(biggerIndex<lastIndex){  
                    /**
                     * 若果右子节点的值较大  
                     */
                    if(arr[biggerIndex]<arr[biggerIndex+1]){  
                        /**
                         * biggerIndex总是记录较大子节点的索引  
                         */
                        biggerIndex++;  
                    }  
                }  
                /**
                 * 如果k节点的值小于其较大的子节点的值 ,交换他们
                 */
                if(arr[k]<arr[biggerIndex]){  
                    swap(arr,k,biggerIndex);  
                    /**
                     * 将biggerIndex赋予k,开始while循环的下一次循环,重新保证k节点的值大于其左右子节点的值  
                     */
                    k=biggerIndex;  
                }else{
                    /**
                     * 当前判断结点k(父结点),大于他的两个子节点时,跳出while循环
                     */
                    break;  
                }  
            }
        }
    }
    /**
     * 交换下标为i、j的两个元素
     */
    private void swap(int[] data, int i, int j) {  
        int tmp=data[i];  
        data[i]=data[j];  
        data[j]=tmp;  
    } 
}

 结果展示:

 

  (本文仅供学习交流,如有更好的思路,欢迎留下意见供大家探讨学习~)