1. 程式人生 > >一些常見的排序演算法(二)

一些常見的排序演算法(二)

一、堆排序

如果還不瞭解滿二叉樹完全二叉樹最大堆(或大頂堆)的話,可以先了解一下。因為大頂堆要求根節點的元素大於其孩子,這樣得到大頂堆的堆頂的元素肯定是

序列中的最大值。清楚這些,就很容易理解堆排序了:先構造大頂堆,將大頂堆中堆頂元素與序列中末尾元素交換。這樣序列尾部的發生交換的元素是排列過的,剩下的未排列的元素重新構造大頂堆,繼續執行上面步驟。

用簡單的圖來表示

 

 

import java.util.Arrays;

public class HeapSort {

    public static void main(String[] args) {
        
        
int[] array = {1, 4, 9, 12, 5, 7, 10, 22, 11, 32}; //1、構造大頂堆:從最後一個非葉子節點開始,從按從右至左、從下到上的順序遍歷 for(int i = array.length/2 - 1; i >= 0; i--) { heapSort(array, array.length, i); } for (int i = array.length - 1; i > 0; i--) { //2、最後一個非葉子節點和頭結點交換
swap(array, i, 0); //3、將餘下的陣列重新構造大頂堆 heapSort(array, i, 0); } System.out.println(Arrays.toString(array)); } /** * 排序:(在length長度內)將父節點和其子節點比較,將最大值放到父節點 * @param array * @param length 要排序的陣列的長度 * @param i 索引為i的父節點
*/ public static void heapSort(int[] array, int length, int i) { //最大值指標 int big = i; //左孩子 int left = 2 * i + 1; //右孩子 int right = left + 1; if(left <= length - 1 && array[left] > array[big]) { big = left; } if(right <= length - 1 && array[right] > array[big]) { big = right; } //指標指向交換的位置,遞迴 if(array[i] != array[big]) { swap(array, i, big); heapSort(array, length, big); } } public static void swap(int[] array, int a, int b) { int temp = array[a]; array[a] = array[b]; array[b]= temp; } }

二、快速排序

快速排序其實是一種分治法的思想,將問題分解和原問題類似的但規模小的問題,遞迴求解。快速排序直接說演算法的思想感覺不是很好理解,我是這樣看快速排序的:總是將一組序列的第一個值作為中間值(序列中中間值左邊的數都比中間值小,右邊的數都比中間值大),將中間值放到序列中正確的位置。下面我們再看快速排序的具體實現:

1、取一個數作為中間數

2、將序列中比它大的數全放右邊,比它小的數全放左邊

3、對中間數的左右邊的小序列重複執行第二步,直到小序列中只有一個數

只對序列進行一次取中間值排序:

程式碼:

import java.util.Arrays;

public class QuickSort {

    /**
     * 序列中比某個數(arr[l])大的放arr[l]一邊,比它小的放arr[l]另一邊,然後返回這個數的索引下標
     * @param arr
     * @param l 從左開始的索引下標
     * @param r    從右開始的索引下標
     * @return 
     */
    public static int position(int[] arr, int l, int r) {
        int pointer = arr[l];
        while (l < r) {
            while (l < r && arr[r] >= pointer) {
                r--; 
            }
            //這個數比pointer小,把這個數放arr[l]另一邊
            if (arr[r] < pointer) {
                arr[l] = arr[r];
                l++;
            }
            while (l < r && arr[l] <= pointer) {
                l++;
            }
            //這個數比pointer大,把這個數放arr[l]另一邊
            if (arr[l] > pointer) {
                arr[r] = arr[l];
                r--;
            }
        }
        arr[l] = pointer;
        return l;
    }

    /**
     * 分治法思想:將問題分解和原問題類似的但規模小的問題,遞迴求解
     * @param arr
     * @param i
     * @param j
     */
    public static void sort(int[] arr, int i, int j) {

        if(i < j) {
            int k = position(arr, i, j);
            System.out.println("i:" + i);
            System.out.println("j:" + j);
            sort(arr, i, k - 1);
            sort(arr, k + 1, j);
        }
    }

    public static void main(String args[]) {
        int arr[] = { 6, 10, 3, 8, 9, 1, 9 };
        int n = arr.length;
        //position(arr, 0, arr.length - 1);
        sort(arr, 0, n - 1);

        System.out.println(Arrays.toString(arr));
    }

}