排序 --- 快速排序
文章目录
- (一)概念
- (二)基本思想
- (三)排序流程
- (三)代码实现
(一)概念
快速排序相当于对冒泡排序的一个优化,也是基于交换的排序算法
时间复杂度 O(nlogn)
(二)基本思想
通过一趟排序,将待排序数据分成两部分,其中一部分数据都比另一部分小,而这两部分数据的内部不要求有序;
然后再对这两部分数据做同样的操作,也各自分成一大一小两部分,依次类推,直到整个数据组有序
(三)排序流程
定义两个下标变量,分别指向待排序的数组段的头和尾
以下图为例:
定义一个flag变量记录左侧第一个元素flag=arr[low]
(为了编程方便,也可以记录右侧第一个元素),然后从右向左开始依次比较flag和数组元素的大小
- 注:此处不要写成
flag=arr[0];
因为之后要对左右半边分别递归使用该函数,当对右半边排序时,应该使flag等于右半边的最左侧的数
如果flag<arr[high],就执行high- -,即下标high向左移动
如果flag>arr[high],就执行arr[low]=arr[high],low++,但是前提条件是low<high
此时再从左往右依次比较flag和arr[low]的大小
如果flag>arr[low],就执行low++
如果flag<arr[low],就执行arr[high]=arr[low],high- -,但是前提条件是low<high
循环上述两个步骤直到low==high时,将arr[low]=flag或者arr[high]=flag
此时flag左边都是比flag小的数,flag右边都是比flag大的数,但是两侧无序
之后再对左半边和右半边分别排序
此处仅以右半边为例,左半边同理,只是low和high的值不同。
右半边:low=5,high=9(左半边:low=0,high=3)
首先使flag=arr[low],此处为7
然后判断flag<arr[high]? 如果小于,就执行high- -
如果大于就执行arr[low]=arr[high],low++
之后判断flag>arr[low]? 如果大于,就执行low++
如果小于就执行arr[high]=arr[low],high- -
直到low==high时,arr[low]=flag或者arr[high]=flag
此时flag左边的值是比flag小的,右边的值是比flag大的,但是左右两边是无序的,因此再次执行上述操作使当前数据段再次分成左右两部分,再次分别对左右两部分进行排序。
因此使用递归即可完成,递归函数中实现的功能就是:
先调用一次sort函数,确定了flag的位置,然后再分别对左半边和右半边排序,直到左右半边无法再继续分隔,即出现low>high或者low==high的情况,此时即是递归函数的出口。
(三)代码实现
#include <stdio.h>
int print(int *arr,int len){
if(NULL==arr) return -1;
for(int i=0;i<len;i++){
printf("%d ",arr[i]);
}
putchar(10);
return 0;
}
int my_sort(int *arr,int low,int high){
if(NULL==arr) return -1;
int flag=arr[low];
while(low < high){
while(flag<arr[high]&&low<high){
high--;
}
if(low<high){
arr[low]=arr[high];
low++;
}
while(flag>arr[low]&&low<high){
low++;
}
if(low<high){
arr[high]=arr[low];
high--;
}
}
arr[low]=flag;
return low;
}
int quick_sort(int *arr,int low,int high){
if(NULL==arr) return -1;
if(low < high){
int ret=my_sort(arr,low,high);
quick_sort(arr,low,ret-1);
quick_sort(arr,ret+1,high);
}
return 0;
}
int main(int argc, char const *argv[]){
int arr[10]={5,2,3,10,7,1,4,9,6,8};
printf("排序前:\n");
print(arr,10);
printf("排序后:\n");
quick_sort(arr,0,9);
print(arr,10);
return 0;
}