java基礎-堆排序之java實現

堆排序之java實現

堆積排序(Heapsort)是指利用堆積樹(堆)這種資料結構所設計的一種排序算法,可以利用數組的特點快速定位指定索引的元素。堆排序是不穩定的排序方法,輔助空間爲O(1), 最壞時間複雜度爲O(nlog2n) ,堆排序的堆序的平均性能較接近於最壞性能。
堆排序利用了大根堆(或小根堆)堆頂記錄的關鍵字最大(或最小)這一特徵,使得在當前無序區中選取最大(或最小)關鍵字的記錄變得簡單。

1)用大根堆排序的基本思想
① 先將初始文件R[1…n]建成一個大根堆,此堆爲初始的無序區
② 再將關鍵字最大的記錄R1和無序區的最後一個記錄R[n]交換,由此得到新的無序區R[1…n-1]和有序區R[n],且滿足R[1…n-1].keys≤R[n].key
③由於交換後新的根R[1]可能違反堆性質,故應將當前無序區R[1…n-1]調整爲堆。然後再次將R[1…n-1]中關鍵字最大的記錄R[1]和該區間的最後一個記錄R[n-1]交換,由此得到新的無序區R[1…n-2]和有序區R[n-1…n],且仍滿足關係R[1…n-2].keys≤R[n-1…n].keys,同樣要將R[1…n-2]調整爲堆。
……
直到無序區只有一個元素爲止。
2)大根堆排序算法的基本操作:
① 初始化操作:將R[1…n]構造爲初始堆;
② 每一趟排序的基本操作:將當前無序區的堆頂記錄R[1]和該區間的最後一個記錄交換,然後將新的無序區調整爲堆(亦稱重建堆)。
注意:
①只需做n-1趟排序,選出較大的n-1個關鍵字即可以使得文件遞增有序。
②用小根堆排序與利用大根堆類似,只不過其排序結果是遞減有序的。堆排序和直接選擇排序相反:在任何時刻堆排序中無序區總是在有序區之前,且有序區是在原向量的尾部由後往前逐步擴大至整個向量爲止。
代碼實現:

public class HeapSortTest {   
    public static void main(String[] args) {  
        int[] data5 = new int[] { 5, 3, 6, 2, 1, 9, 4, 8, 7 };  
        print(data5);  
        heapSort(data5);  
        System.out.println("排序後的數組:");  
        print(data5);  
    }  
  
    public static void swap(int[] data, int i, int j) {  
        if (i == j) {  
            return;  
        }  
        data[i] = data[i] + data[j];  
        data[j] = data[i] - data[j];  
        data[i] = data[i] - data[j];  
    }  
  
    public static void heapSort(int[] data) {  
        for (int i = 0; i < data.length; i++) {  
            createMaxdHeap(data, data.length - 1 - i);  
            swap(data, 0, data.length - 1 - i);  
            print(data);  
        }  
    }  
  
    public static void createMaxdHeap(int[] data, int lastIndex) {  
        for (int i = (lastIndex - 1) / 2; i >= 0; i--) {  
            // 保存當前正在判斷的節點  
            int k = i;  
            // 若當前節點的子節點存在  
            while (2 * k + 1 <= lastIndex) {  
                // biggerIndex總是記錄較大節點的值,先賦值爲當前判斷節點的左子節點  
                int biggerIndex = 2 * k + 1;  
                if (biggerIndex < lastIndex) {  
                    // 若右子節點存在,否則此時biggerIndex應該等於 lastIndex  
                    if (data[biggerIndex] < data[biggerIndex + 1]) {  
                        // 若右子節點值比左子節點值大,則biggerIndex記錄的是右子節點的值  
                        biggerIndex++;  
                    }  
                }  
                if (data[k] < data[biggerIndex]) {  
                    // 若當前節點值比子節點最大值小,則交換2者得值,交換後將biggerIndex值賦值給k  
                    swap(data, k, biggerIndex);  
                    k = biggerIndex;  
                } else {  
                    break;  
                }  
            }  
        }  
    }  
  
    public static void print(int[] data) {  
        for (int i = 0; i < data.length; i++) {  
            System.out.print(data[i] + "\t");  
        }  
        System.out.println();  
    }  
}  

運行結果:

[java] view plain copy
5   3   6   2   1   9   4   8   7     
3   8   6   7   1   5   4   2   9     
2   7   6   3   1   5   4   8   9     
4   3   6   2   1   5   7   8   9     
4   3   5   2   1   6   7   8   9     
1   3   4   2   5   6   7   8   9     
2   3   1   4   5   6   7   8   9     
1   2   3   4   5   6   7   8   9     
1   2   3   4   5   6   7   8   9     
1   2   3   4   5   6   7   8   9   

排序後的數組:

1   2   3   4   5   6   7   8   9  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章