快速排序
算法思想
- 从数列中挑出一个元素,称为"基准"(pivot),
- 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
- 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
动画演示:
实现
C++
int partition(vector<int> &a, int left, int right)
{
int pivotPos = left; //记录轴值位置
int pivot = a[left]; //取最左边的值作为轴值
left++; //避开轴值
while (left < right) //从左右两边各自扫描数组,左边遇到比轴值大的就停下,右边遇到比轴值小的就停下,交换。继续。。。
{
while (a[left] < pivot && left < right)
left++;
while (a[right] > pivot && left < right)
right--;
swap(a[left], a[right]);
}
if (a[right] < a[pivotPos])
{
swap(a[right], a[pivotPos]);
return right;
}
else
{
swap(a[right - 1], a[pivotPos]);
return right - 1;
}
}
void quickSortHelp(vector<int> &a, int left, int right)
{
if (left >= right)
return;
int k = partition(a, left, right); //通过partition将数组按比轴值大小分别放到轴值左右两边,返回最后轴值的位置k。
quickSortHelp(a, left, k - 1);
quickSortHelp(a, k + 1, right);
}
void quickSort(vector<int> &a)
{
int len = a.size();
quickSortHelp(a, 0, len - 1);
}
python
def quickSort(alist):
quickSortHelper(alist,0,len(alist)-1)
def quickSortHelper(alist,first,last):
if first<last:
splitpoint = partition(alist,first,last)
quickSortHelper(alist,first,splitpoint-1)
quickSortHelper(alist,splitpoint+1,last)
def partition(alist,first,last):
pivotvalue = alist[first]
leftmark = first+1
rightmark = last
done = False
while not done:
while leftmark <= rightmark and alist[leftmark] <= pivotvalue:
leftmark = leftmark + 1
while alist[rightmark] >= pivotvalue and rightmark >= leftmark:
rightmark = rightmark -1
if rightmark < leftmark:
done = True
else:
temp = alist[leftmark]
alist[leftmark] = alist[rightmark]
alist[rightmark] = temp
temp = alist[first]
alist[first] = alist[rightmark]
alist[rightmark] = temp
return rightmark
总结
稳定性:
快速排序并不是稳定的,这是因为我们无法保证相等的数据按顺序被扫描到和按顺序存放。
适用场景:
快速排序在大多数情况下都是适用的,尤其在数据量大的时候性能优越性更加明显。但是在必要的时候,需要考虑下优化以提高其在最坏情况下的性能。
复杂度:
\(O(N * \log N)\) 。