貌似需要整理一下排序算法了,正好最近在看的宋劲杉的《LINUX一站式编程》也提到了几个排序算法,于是决定把几个常见的排序算法都写写吧。
快速排序是我觉得排序算法中趣味排名top 1的排序。
快速排序每次只做一件事儿。在当前数组中,找到一个元素(叫做pivot),然后把比pivot小的放在pivot的左边,把比pivot打的放在pivot的右边。这样一趟下来,pivot被排好序了。也就是说,每趟就排序一个数。这个过程一般用函数partition(){}来表达。
然后,对pivot左边的数组重复刚才的那趟过程。
然后,对pivot右边的数组也重复刚才的那趟过程。
当最后发现每个数组都只有1个元素的时候,就OK了。
和归并排序一样,快速排序也使用了分治的思想, 所以时间复杂度都是Θ(n lg n)但是,快速排序比归并排序牛的地方在于,首先,快速排序的常数因子更小,也就是说,平均下来,虽然快速排序和归并排序是同一量级的时间复杂度,但是快速排序的需要时间比归并排序的需要时间少。第二,快速排序就地解决,无需额外空间,归并排序需要额外空间。
(theconstant factors hidden in the Θ(n lg n) notation are quite small theadvantage of sorting in place 《CLRS算法导论》)
这里有个视频,展示快速排序的声音。
//下面两个函数用来依次打印数组。功能一样,参数不一样,这是为了方便不同的数据类型的调用要求。
void print_num_1(uint32_t* arr, uint32_t len){
for(int i=0;i<len;i++)
std::cout<<arr[i]<<"\t";
std::cout<<std::endl;
return;
}
void print_num_2(int* arr, int len){
for(int i=0;i<len;i++)
std::cout<<arr[i]<<"\t";
std::cout<<std::endl;
return;
}
下面是快速排序的过程
//quick_sort_version_1
int partition(int* arr, int st, int ed){
int j=st;
int i=j-1;
int pivot=arr[ed];
int temp;
while (j<=ed-1) {
if (pivot>arr[j]) {
i++;
temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
j++;
}
i++;
temp=arr[ed];
arr[ed]=arr[i];
arr[i]=temp;
//print_num_2(arr+st,ed-st+1);
return i;
}
void quick_sort_1(int* arr, int st, int ed){
if(st<ed) {
int pivot=partition(arr, st, ed);
quick_sort_1(arr,st, pivot-1);
quick_sort_1(arr,pivot+1,ed);
}
}
后来,又看到了一个荷兰三色旗问题,于是扩展了一下快速排序的做法,详见 这里。