算法熟记-排序系列-快速排序
2011-06-08 15:58
197 查看
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. 代码
void quick_sort(int array[], int n) {
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]
}
实际上,快速排序是作为冒泡排序的改进提出来的,很多实现都是通过元素交换实现的,上面的代码是改进后的,更加有效率,把元素交换变成了元素的赋值。
一般来说,交换排序包括:冒泡排序和快速排序。
下面贴一个快速排序使用交换元素的实现:
void quicksort(int arr[],int beg,int end) {
if (end >= beg + 1) {
int piv = arr[beg], k = beg + 1, r = end;
// 从基准(array[0])右边的元素开始扫描,对于小于基准的元素跳过,对于大于基准的元素,交换到右边的位置上去,缩减右边的位置。
// 当右边可以交换的位置与当前元素重叠了,结束循环
while (k < r) {
if (arr[k] < piv)
k++;
else
swap(&arr[k], &arr[r--]);
}
// 交换基准
if (arr[k] < piv){
swap(&arr[k],&arr[beg]);
quicksort(arr, beg, k);
quicksort(arr, r, end);
}
else {
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
假设待排序数组为 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. 代码
void quick_sort(int array[], int n) {
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]
}
实际上,快速排序是作为冒泡排序的改进提出来的,很多实现都是通过元素交换实现的,上面的代码是改进后的,更加有效率,把元素交换变成了元素的赋值。
一般来说,交换排序包括:冒泡排序和快速排序。
下面贴一个快速排序使用交换元素的实现:
void quicksort(int arr[],int beg,int end) {
if (end >= beg + 1) {
int piv = arr[beg], k = beg + 1, r = end;
// 从基准(array[0])右边的元素开始扫描,对于小于基准的元素跳过,对于大于基准的元素,交换到右边的位置上去,缩减右边的位置。
// 当右边可以交换的位置与当前元素重叠了,结束循环
while (k < r) {
if (arr[k] < piv)
k++;
else
swap(&arr[k], &arr[r--]);
}
// 交换基准
if (arr[k] < piv){
swap(&arr[k],&arr[beg]);
quicksort(arr, beg, k);
quicksort(arr, r, end);
}
else {
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
相关文章推荐
- 算法熟记-排序系列-选择排序
- 算法熟记-排序系列-计数排序
- 算法熟记-排序系列-归并排序
- 算法熟记-排序系列-基数排序
- 算法熟记-排序系列-希尔排序
- 傻瓜学算法系列之排序——5.快速排序
- 每天学习算法系列—内部排序之归并排序和快速排序
- 算法熟记-排序系列-冒泡排序
- 算法熟记-排序系列-插入排序
- 算法熟记-排序系列-堆排序
- 白话经典算法系列之四 直接选择排序及交换二个数据的正确实现
- 白话经典算法系列之五 归并排序的实现
- 算法系列15天速成——第三天 七大经典排序【下】
- 白话经典算法系列之五 归并排序的实现
- 坐在马桶上学算法@最常用的排序——快速排序
- 白话经典算法系列之五 归并排序的实现
- 数据结构和算法学习系列之快速排序的Partition函数一种实现方法
- 算法系列15天速成——第二天 七大经典排序【中】
- 七大排序问题之快速排序(参考算法导论PHP版)
- 白话经典算法系列之六 高速排序 高速搞定