算法熟记-排序系列-快速排序
1. 简述
假设待排序数组为 int array[], 数组长度为n。快速排序是一个递归得方法。
当n==1的时候,停止排序。
当n>1的时候,首先选择数组中得一个元素作为基准,然后,把小于这个基准得元素放到这个基准的左边,把大于这个基准得元素放到这个元素得右边。
具体实现下面进行简单得说明,假设array[0]作为基准:
首先,存储基准得值,int tmp=array[0];
然后,两个指针,int left=0; int right = n-1;
bool flag_left = false; // 初始从右边开始
while(left < right) {
if(flag_left == true) {
如果当前值小于基准,则left++;
否则,array[right]=array[left]; right--; flag_left = false;
}
else {
如果当前值大于基准,则right--;
否则,array[left]=array[right]; left++; flag_left = true;
}
}
array[left] = tmp;
上面这段代码中,当轮到left指针执行时,right指针向的位置是可以使用的。当轮到right指针执行时,left指针指向的位置是可以使用的。
初始时,备份了array[0],left指针指向的位置是可以使用 得,因此从右边开始。
最后,递归排序array[0]-array[left-1]和array[left+1]-array[n-1]两个部分的数组。
2. 复杂度
平均时间复杂度是O(N*logN)。当数组本身已经有序得情况下,需要比较得次数是N*N次。为了解决这样的问题,可以使用乱数快速排序,即每次基准是随即选择的。
稳定性属于非稳定排序。因为在与基准的比较过程中的交换很可能打破已有的顺序。
3. 代码
if(n <= 1)
return;
int tmp = array[0];
int left = 0; int right = n-1;
bool left_flag = false;
while(left < right) {
if(left_flag == true) { // 当前left指针
if(array[left] < tmp) {
left++;
}
else {
array[right] = array[left];
right--;
left_flag = false;
}
}
else { // 当前right指针
if(array[right] > tmp) {
right--;
}
else {
array[left] = array[right];
left++;
left_flag = true;
}
}
}
array[left] = tmp;
quick_sort(array, left); // array[0]-array[left-1]
quick_sort(array+left+1, n-left-1); // array[left+1], array[n-1]
}
实际上,快速排序是作为冒泡排序的改进提出来的,很多实现都是通过元素交换实现的,上面的代码是改进后的,更加有效率,把元素交换变成了元素的赋值。
一般来说,交换排序包括:冒泡排序和快速排序。
下面贴一个快速排序使用交换元素的实现:
if (end >= beg + 1) {
int piv = arr[beg], k = beg + 1, r = end;
while (k < r) {
k++;
else
swap(&arr[k], &arr[r--]);
}
if (arr[k] < piv){
quicksort(arr, beg, k);
quicksort(arr, r, end);
}
if (end - beg == 1)
return;
swap(&arr[--k],&arr[beg]);
quicksort(arr, beg, k);
quicksort(arr, r, end);
}
}
4. 参考资料
维基百科-快速排序 http://en.wikipedia.org/wiki/Quicksort