堆排序(Java語言描述)

堆排序(Heapsort)是指利用堆積樹(堆)這種數據結構所設計的一種排序算法,它是選擇排序的一種。可以利用數組的特點快速定位指定索引的元素。堆分爲大根堆和小根堆,是完全二叉樹。大根堆的要求是每個節點的值都不大於其父節點的值,即A[PARENT[i]] >= A[i]。在數組的非降序排序中,需要使用的就是大根堆,因爲根據大根堆的要求可知,最大的值一定在堆頂。

時間複雜度:O(nlogn)

現象:可比較我的其他算法的時間消耗
(正確情況下)
組建數組元素個數:10000000
組件隨機數組運行時間:158
排序時間:2744
(錯誤情況下,未真正變換成大根堆)
組建數組元素個數:10000000(千萬)
組件隨機數組運行時間:160ms
排序時間:67ms

//正確版本

import java.util.Random;

/**
 * 堆排序
 * @author moxianbin
 */
public class HeapSort {
    /**
     * 組建隨機數組
     * @param len
     * @return
     */
    public static int[] get_intarr(int len){
        long begin = System.currentTimeMillis();
        Random ran = new Random();
        int [] result = new int[len];
        for(int i=0;i<len;i++){result[i] = ran.nextInt(10000); }
        long runtime = System.currentTimeMillis()-begin;
        System.out.println("組建數組元素個數:"+len);
        System.out.println("組件隨機數組運行時間:"+runtime);
        return result;
    }
    //交換元素
    public static void swap(int []a,int i,int j){
        int temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }
    public static void show(int [] a){
        for(int i=0;i<a.length;i++){
            System.out.print(a[i]+"、");
        }
        System.out.println();
    }

    /**
     * 下面執行堆排序
     */

    //左孩子節點
    private static int leftChild(int i){return 2*i+1;}
    //右孩子節點
    private static int rightChild(int i){return 2*i+2;}
    //父節點
    private static int parent(int i){return (i-1)/2;}

    //以第i個節點爲頂點建立大根堆
    public static void MaxHeapFixdown(int []a,int n,int i){

        int big_child=leftChild(i), temp=a[i];  

        while (big_child < n)  //直至遍歷到最後的節點
        {  
            if (big_child + 1 < n && a[big_child + 1] > a[big_child]) //在左右孩子中找最大的  
                big_child++;  

            if (a[big_child] <= temp){  //若該節點大於最大子節點,則此時爲大根堆
                break;  
            }else{    
                a[i] = a[big_child];     //把較大的子結點往上移動,替換它的父結點  
                a[big_child] = temp;
                i = big_child;  //以子節點位置繼續建立大根堆
                big_child = 2 * i + 1;
            }
        }  
    }

    //堆排序,大根堆排序,堆中最大那個永遠在a[0],然後調換a[0]與a[len-1]
    public static void heapSort(int []a){
        long begin = System.currentTimeMillis();
        //將每個堆的最大節點都放在父節點上
        for(int j=a.length/2-1;j>=0;j--){
            MaxHeapFixdown(a,a.length,j);
        }
        //不斷更換最大節點至末尾
        for(int i=a.length;i>=1;i--){
            swap(a,i-1,0);
            MaxHeapFixdown(a,i-1,0);
        }
        long runtime = System.currentTimeMillis()-begin;
        System.out.println("排序時間:"+runtime);
    }
    /**
     * 堆排序結束
     */

    public static void main(String[] args) {
        int [] a = get_intarr(10000000);
//      show(a);
        heapSort(a);
//      show(a);
    }
}

//錯誤版本,結果有誤

import java.util.Random;

/**
 * 堆排序
 * @author moxianbin
 */
public class HeapSort {
    /**
     * 組建隨機數組
     * @param len
     * @return
     */
    public static int[] get_intarr(int len){
        long begin = System.currentTimeMillis();
        Random ran = new Random();
        int [] result = new int[len];
        for(int i=0;i<len;i++){result[i] = ran.nextInt(10000); }
        long runtime = System.currentTimeMillis()-begin;
        System.out.println("組建數組元素個數:"+len);
        System.out.println("組件隨機數組運行時間:"+runtime);
        return result;
    }
    //交換元素
    public static void swap(int []a,int i,int j){
        int temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }
    public static void show(int [] a){
        for(int i=0;i<a.length;i++){
            System.out.print(a[i]+"、");
        }
        System.out.println();
    }

    /**
     * 下面執行堆排序
     */

    //左孩子節點
    private static int leftChild(int i){return 2*i+1;}
    //右孩子節點
    private static int rightChild(int i){return 2*i+2;}
    //父節點
    private static int parent(int i){return (i-1)/2;}

    //從第i個節點開始調整,比較該節點與最大子節點,如果最大子節點還大就調換位置
    public static void MaxHeapFixdown(int []a,int n,int i){
        //左右孩子節點
        int lchild = 2*i+1,rchild = 2*i+2;
        //找出最大孩子節點
        if(lchild < n){
            int tmp = a[i];
            int big_child = 0;//用於存儲最大的孩子節點
            if(rchild < n && a[rchild] > a[lchild]){
                big_child = rchild;
            }else{
                big_child=lchild;
            }
            if(a[big_child]>a[i]){
                a[i] = a[big_child];
                a[big_child] = tmp;
            }
        }
    }

    //堆排序,大根堆排序,堆中最大那個永遠在a[0],然後調換a[0]與a[len-1]
    public static void heapSort(int []a){
        long begin = System.currentTimeMillis();
//將每個堆的最大節點都放在父節點上
        for(int j=a.length/2-1;j>=0;j--){
            MaxHeapFixdown(a,a.length,j);
        }
        //不斷更換最大節點至末尾
        for(int i=a.length;i>=1;i--){
            swap(a,i-1,0);
            MaxHeapFixdown(a,i-1,0);
        }
        long runtime = System.currentTimeMillis()-begin;
        System.out.println("排序時間:"+runtime);
    }
    /**
     * 堆排序結束
     */

    public static void main(String[] args) {
        int [] a = get_intarr(10000000);
//      show(a);
        heapSort(a);
//      show(a);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章