【總結】快速排序


基本思想

快排是對冒泡排序的一種改進,是C.R.A.Hoare於1962年提出的一種劃分交換排序,採用了分治的策略,通常稱爲分治法
基本思想:
1、選取一個值爲基準值point
2、將小於或等於point的值放於左邊
3、將大於point的值放於右邊
4、分別對左右子序列重複前三個步驟,直到各子序列只有一個數

在這裏插入圖片描述
上述圖實例爲快速的第一輪過程,顯然是挖坑填數+分治法來實現整個快速排序過程,以序列爲一數組,以i=0指向數組第一個數字,以j=5來指向數組最後一個數字,進行快排。
第一次取下標爲0的數作爲基準值:18

0 1 2 3 4 5
18 98 10 16 2 7

開始時,i=0,j=5,temp=num[i]=18
此時已經將num[0]的值保存到temp中,可理解爲將num[0]這裏挖坑,可以將其他數據填充到這裏。從j=5開始向前尋找小於或等於temp的數字,j=5時,7<18,符合條件,將num[5]的值挖出填入坑num[0]中,即num[0]=num[5];i++;填完坑之後,又出現了新坑num[5],則需要再一次找數字來填這個坑,這次從i開始向後找大於temp的數字,當i=1時,即num[1]=98大於temp,符合條件,挖出num[1]的值填入坑num[5]中,即num[5]=num[1];j++;這樣又出現了新坑num[1]…以此類推,當j等於i時,將基準值賦給num[i],分別對num[i]左右子序列遞歸調用快排方法,遞歸的結束條件爲各子序列只有一個數字


代碼實現

1、以上思想中挖坑填數+分治法結合,Java實現如下

public void quick_sort(int num[], int l, int r)
{
    if (l < r)
    {
        int i = l, j = r, temp = num[l];
        while (i < j)
        {
            // 從右向左找第一個小於或等於x的數來填坑num[i]
            while(i < j && num[j] > temp) 
                j--;  
            if(i < j) 
                num[i++] = num[j];  //將num[j]填到num[i]中,num[j]形成新坑
                
            // 從左向後找第一個大於x的數
            while(i < j && num[i] <= temp) 
                i++;  
            if(i < j) 
                num[j--] = num[i]; //將num[i]填到num[j]中,num[i]形成新坑
        }
        num[i] = temp;
        quick_sort(s, l, i - 1); // 左邊子序列遞歸調用 
        quick_sort(s, i + 1, r); //右邊子序列遞歸調用
    }
}

2、Golang的快排結合切片實現(用填坑法+分治Go重寫1的Java代碼超出時間限制)
注:continue語句執行是跳過本次循環(不管後面未執行的語句)繼續下一次循環

func quick_sort(nums []int){
    i , j := 0 , len(nums) - 1
    for i < j {
        if nums[j] > nums[0] {
            j--
            continue
        }
        if nums[i] <= nums[0] {
            i++
            continue
        }
        nums[i],nums[j] = nums[j] ,nums[i]
    }
    nums[0],nums[i] = nums[i],nums[0]
    if len(nums[:j]) > 1 {
        sortArray(nums[:j]) //左邊子序列遞歸調用
    }
    if len(nums[j+1:]) >1 {
        sortArray(nums[j+1:]) //右邊子序列遞歸調用
    }
}

3、Golang slice方法,很好體現出分治思想

func sortArray(nums []int) []int {
    if len(nums) <= 1 {
		return  nums
	}
    //nums[0]作爲基準值
	key := nums[0]
	var left, right []int
	for _, e := range nums[1:] {
		if e <= key {
			left = append(left, e)
		} else {
			right = append(right, e)
		}
	}
	return  append(append(sortArray(left), key), sortArray(right)...)
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章