快速排序中的分割算法實現

這裏介紹快速排序使用到的兩種分割算法。

對於快速排序而言,先選定一個樞軸元素,以樞軸元素爲基準比樞軸元素小的元素放在樞軸元素的左邊,比樞軸元素大的元素放在樞軸元素的右邊。這就是一次分割過程。

1,先介紹第一種分割算法

該算法是《算法導論》中描述的PARTITION過程。這個分割的思想應該有很多應用,比如應用到快速排序中,再比如應用到如果獲取中位數(或者給定一組數,找出其中第K小的元素)

該分割算法的思想是,始終選定數組中的最後一個元素作爲樞軸元素,設置指針 i 初始值爲數組起始元素索引減1,設置指針 j 由數組下標從低到高掃描整個數組,若遇到的元素小於樞軸元素則 i 自增然後交換 i 數組元素的值和i 數組元素的值;若遇到的元素大於 樞軸元素則i指針不動,只有j指針自增。此算法的時間複雜度爲O(n),空間複雜度爲O(1)。

具體的JAVA實現代碼如下,算法僞代碼參考《算法導論》

/*
     * split array
     * this method always use the last elements as pivot.
     * when the method finished, the left elements of array smaller than pivot.
     * and the right elements of array larger than pivot.
     * @return  the pivot element in array
     */
    public int partition(int arr[], int low, int high) {
        int pivot = arr[high];
        int i = low - 1;
        for (int j = low; j < high; j++) {
            if (arr[j] <= pivot) {
                i++;
                swap(arr, i, j);
            }
        }
        swap(arr, i + 1, high);
        return i + 1;
    }

	/*
	 * switch two elements of arry
	 * @param int[] arr an array for switch
	 * @param int i, j index of array
	 * 
	 */
	private void swap(int[] arr, int i, int j){
		int tmp = arr[i];
		arr[i] = arr[j];
		arr[j] = tmp;
	}

2,第二種分割算法的實現思路

假設總是以第一個元素作爲樞軸元素,設置兩個指針low, high。low 指向數組的第一個元素,high 指向數組的最後一個元素。high 指針從後向前掃描,若碰到的元素大於樞軸元素則 high 直接自減,若碰到的元素小於樞軸元素則將該元素與樞軸元素交換並break 此次掃描。

high 指針的當次掃描被中斷後,low 指針開始由前向後掃描,若碰到的元素小於樞軸元素則 low 直接自減,若碰到的元素大於樞軸元素則將該元素與樞軸元素交換並break 此次掃描。

直至low 指針 超過 high指針爲止。

具體的實現參考:使用JAVA泛型實現快速排序


第一種分割算法的完整實現+測試版。

public class Partition {
	/*
	 * split array
	 * this method always use the last elements as pivot.
	 * when the method finished, the left elements of array smaller than pivot.
	 * and the right elements of array larger than pivot.
	 * @return  the pivot element in array
	 */
	public int partition(int arr[], int low, int high) {
		int pivot = arr[high];
		int i = low - 1;
		for (int j = low; j < high; j++) {
			if (arr[j] <= pivot) {
				i++;
				swap(arr, i, j);
			}
		}
		swap(arr, i + 1, high);
		return i + 1;
	}
	
	
	/*
	 * create a random pivot and use it to partition array
	 */
	public int randomPartition(int[] arr, int low, int high){
		int rand = getRandom(low, high);
		swap(arr, arr[rand], arr[high]);//arr[high] is a random and will be as pivot
		return partition(arr, low, high);
	}
	
	/*
	 * return a random between min and max----[min, max]
	 */
	private int getRandom(int min, int max){
		Random random = new Random();
		return  random.nextInt(max + 1) % (max-min+1) + min;
	}
	
	/*
	 * switch two elements of arry
	 * @param int[] arr an array for switch
	 * @param int i, j index of array
	 * 
	 */
	private void swap(int[] arr, int i, int j){
		int tmp = arr[i];
		arr[i] = arr[j];
		arr[j] = tmp;
	}
	
	public static void main(String[] args) {
		Partition p = new Partition();
		int arr[] = {3,5,9,6,2,8};
		int result = p.partition(arr, 0, arr.length - 1);
		System.out.println(result);
		System.out.println(arr);
	}
}


藉助partition方法,實現快速排序就很容易了。代碼如下:

public void quickSort(int[] arr, int low, int high){
		if(low < high){
			int pivot_location = partition(arr, low, high);
			quickSort(arr, low, pivot_location - 1);
			quickSort(arr, pivot_location + 1, high);
		}
	}





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