快速排序(Quick Sort)
快速排序(Quicksort)是对冒泡排序的一种改进,由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。—百度百科
- 时间复杂度:最好 O(n)=O(nlogn);平均O(n)=O(nlogn);最差O(n)=O(n2)
- 空间复杂度:O(n)=O(n)
- 稳定性: 不稳定
算法描述
- 设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。
- 分别对步骤1中的小的数和大的数递归进行步骤1中快速排序,直到完成。
图片来自维基百科
排序示例
数组S: [9,1,5,3,8,7,2,4,6,0]
第一趟:[(1,5,3,8,7,2,4,6,0),9] –key=9
第二趟:[0,1,(5,3,8,7,2,4,6),9] –key=1
第三趟:[0,1,(3,2,4),5,(8,7,6),9] –key=5
第四趟:[0,1,2,3,4,5,6,7,8,9] –key=3,8
示例代码
public static void QuickSort(int[] S){ //C#
QuickSort(S, 0, S.Length - 1);
}
private static void QucikSort(int[] S, int low, int high){
if (high > low){
int pivotIndex = Partition(S, low, high);
QuickSort(S, low, pivotIndex - 1);
QuickSort(S, pivotIndex + 1, high);
}
}
/// <summary>
/// 选取第一个数据为关键字,将比其小的数放置其左,比其大的数放置其右
/// </summary>
/// <returns>选取的关键字的位置索引</returns>
private static void Partition(int[] S, int low, int high){
int pivot = S[low];//关键字
while (low < high){
while (low < high && S[high] >= pivot){
high--;
}
S[low] = S[high];//将比关键字小的数放置其左
while (low < high && S[low] >= pivot){
low++;
}
S[high] = S[low];//比关键字大的数放置其右
}
S[low] = pivot;
return low;//关键字的位置
}
def quick_sort(s, low, high): #Python
if high > low:
index_pivot = partition(s, low, high)
quick_sort(s, low, index_pivot-1)
quick_sort(s, index_pivot+1, high)
def partition(s, low, high):
pivot = s[low]
while low < high:
while low < high and s[high] >= pivot:
high -= 1
s[low] = s[high]
while low < high and s[low] <= pivot:
low += 1
s[high] = s[low]
s[low] = pivot
return low
三向切分快速排序
- 三向切分快速排序是对快速排序的改进。根据关键字将待排序列分为三部分:左边均小于关键字,中间均等于关键字,右边均大于关键字。
当待排序列中有较多相等数据时,其排序效率高于快速排序。否则,效率低于快速排序。 - 时间复杂度:最好 O(n)=O(n);平均O(n)=O(nlogn);最差O(n)=O(n2)
- 空间复杂度:O(n)=O(n)
- 稳定性: 不稳定
算法描述
对于每次切分:从数组的左边到右边遍历一次,维护三个指针lt,gthe i,其中
- lt指针使得元素 (arr[0]-arr[lt-1]) 的值均小于切分元素;
- gt指针使得元素(arr[gt+1]-arr[N-1])的值均大于切分元素;
- i指针使得元素(arr[lt]-arr[i-1])的值均等于切分元素,(arr[i]-arr[gt])的元素还没被扫描,切分算法执行到i>gt为止。
每次切分之后,位于gt指针和lt指针之间的元素的位置都已经被排定,不需要再去移动了。之后将(lo,lt-1),(gt+1,hi)分别作为处理左子数组和右子数组的递归函数的参数传入,递归结束,整个算法也就结束。
—简书
排序示例
示例代码
public static void Quick3WaySort(int[] S){ //C#
Quick3WaySort(S, 0, S.Length - 1);
}
private static void Quick3WaySort(int[] S, int low, int high){
if (high <= low){
return;
}
int left = low;
int right = high;
int pivot = S[low];//用于比较的关键字
int i = low + 1;
while (i <= right){
if (S[i] < pivot){
S.Swap(left++, i++); //小于关键字的元素放左边
} else if (S[i] > pivot){
S.Swap(right--, i); //大于关键字的元素放右边
} else{
i++; //等于关键字的元素放中间
}
}
Quick3WaySort(S, low, left -1); //对左边进行排序
Quick3WaySort(S, right + 1, high);//对右边进行排序
}
def quick3way_sort(s, low, high): #Python
if high > low:
left = low
right = high
i = low + 1
pivot = s[low]
while i <= right:
if s[i] < pivot:
s[left], s[i] = s[i], s[left]
i += 1
left += 1
elif s[i] > pivot:
s[i], s[right] = s[right], s[i]
right -= 1
else:
i += 1
quick3way_sort(s, low, left-1)
quick3way_sort(s, right+1, high)
文中若有什么错误,欢迎留言指正。
转载请保留出处:http://blog.csdn.net/x1060549/article/details/78789799