1. 程式人生 > >排序演算法之快速排序

排序演算法之快速排序

快速排序:

通過一趟排序將待排記錄分割成獨立的兩部分,其中一部分記錄的關鍵字比另一部分記錄的關鍵字小,則可以分別對這兩部分記錄繼續進行排序,以達到整個序列有序的目的。

快速排序的時間複雜度,最好情況和平均情況為O(n * lgn ),最差情況下為O(n ^ 2),空間複雜度為O(lg n ), 是不穩定的排序演算法。

基本思想:分治演算法

找基準值的三種方式:

找邊上的(本文中程式碼均以最右邊為例) ;隨機選;三數取中

用基準值和陣列中的所有值進行比較,將比基準值小的都放到基準值的左邊,比基準值大的,放到基準值的右邊,三種方式:左右指標法;挖坑法;前後下標法

終止條件:小區間有序, 長度等於1;小區間內沒有數,長度等於0

左右指標法:

左右指標法:當begin停下來的時候,其值一定大於基準值
//左右指標法,左閉右閉區間[],將選的基準值放在最右邊,
int Partion1(int arr[], int left, int right)
{
	int pivot = arr[right];
	int begin = left;
	int end = right;
	while(begin < end)
	{
		while(begin < end && arr[begin] <= pivot)
		{
			begin++;
		}
		if(begin == end)
		{
			break;
		}
		while(begin < end && arr[end] >= pivot)
		{
			end--;
		}
		if(begin == end)
		{
			break;
		}
		Swap(arr+begin, arr+end);
	}
	Swap(arr+begin, arr+right);
	return begin;
}

挖坑法:

int Partion2(int arr[], int left, int right)
{
	//left, right是不斷變化的
	int pivot = arr[right];
	int begin = left;  
	int end = right;
	while(begin < end)
	{
		//如果基準值在最右邊,先移動begin
		while(begin < end && arr[begin] <= pivot)
		{
			begin++;
		}
		if(begin == end)
		{
			break;
		}
		//pivot已經標記了基準值,當arr[begin]的值大於基準值,則將arr[begin]更換到基準值的位置
		//則在begin處留出一個空位,便於下一個數的填充
		arr[end] = arr[begin]; 
		while(begin < end && arr[end] >= pivot)
		{
			end--;
		}
		if(begin == end)
		{
			break;
		}
		//當end走到這一步,則將arr[end]取代原begin留下的空位
		arr[begin] = arr[end];
	}
	arr[begin] = pivot;  //將基準值放到begin處。
	return begin;
}

前後指標法:

int Partion3(int arr[], int left, int right)
{
	int pivot = arr[right];
	int div = left;
	int cur = left;
	for(cur=left; cur<=right; cur++)
	{
		if(arr[cur] < pivot)
		{
			Swap(arr+cur, arr+div);
			div++;
		}
	}
	Swap(arr+right, arr+div);
	return div;
}