快速排序(C语言)
Posted 曹李序员
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了快速排序(C语言)相关的知识,希望对你有一定的参考价值。
简介
快速排序与归并排序一样也是一种分治递归算法,其排序(升序)步骤可以简述如下:
1、在待排元素集合N中任选一元素做为枢纽元
2、开始分割元素,使左部元素均小于枢纽元,右部元素均大于枢纽元
3、对左右子序列递归应用步骤1、2
1、选取枢纽元
有一种极其常见的、错误的、非常糟糕的枢纽元的选取,是选取数组第一个或者最后一个元素为枢纽元,如果输入序列是随机的那么上述做法可以接受,但如果输入的序列与我们要排的序列正好相反,那么在分割元素阶段就会出现所有元素被划分到左半部或者右半部,更糟糕的是,在其后续递归过程中也是如此,那么其排序花费的时间将是二次的,因此该种枢纽元的选取应该摒弃。
void swap(int *p_num, int k, int j)
{
if (NULL == p_num) {
return;
}
int tmp = p_num[k];
p_num[k] = p_num[j];
p_num[j] = tmp;
}
void quick_sort(int * p_num, int left, int right)
{
if ((NULL == p_num) || left >= right) {
return;
}
int last = left;
swap(p_num, left, (left + right) / 2);
for (int i = left + 1; i <= right; i++) {
if (p_num[i] < p_num[left]/* 直接将最左边的元素作为枢纽元 */) {
swap(p_num, ++last, i);
}
}
swap(p_num, left, last);
quick_sort(p_num, left, last - 1);
quick_sort(p_num, last + 1, right);
}
那么我们该如何选取枢纽元呢?有两种常见的做法,一种是使用随机数生成器随机选取(但我们要注意到随机数的选取是昂贵的),另一种做法是选取3个数的中位数,这种选取方式总的来说是好的稳妥的,如下:
void Swap(int *A, int *B)
{
int Tmp = *A;
*A = *B;
*B = Tmp;
}
int median3(int nums[], int left, int right)
{
int center = (left + right) / 2;
if (nums[left] > nums[center]) {
Swap(&nums[left], &nums[center]);
}
if (nums[left] > nums[right]) {
Swap(&nums[left], &nums[right]);
}
if (nums[center] > nums[right]) {
Swap(&nums[center], &nums[right]);
}
Swap(&nums[center], &nums[right]); // 隐藏枢纽元
return nums[right];
}
2、分割策略
分割所做的事就是将小元素移动到数组左边,大元素移动到数组右边,一种安全稳妥的分割策略是,选取枢纽元之后将其与最后一个元素交换,然后对第0个元素和倒数第二个元素分割,因为没有必要对枢纽元进行分割,故将其移动到最后进行隐藏,具体分割步骤如下:
上述分割策略摘自数据结构与算法分析第二版page180
3、代码实现
void Swap(int *A, int *B)
{
int Tmp = *A;
*A = *B;
*B = Tmp;
}
void select_sort(int *p_arr, const int size)
{
assert(p_arr != NULL);
for (int i = 0; i < size; i++) {
for (int j = i + 1; j < size; j++) {
if (*(p_arr + i) > *(p_arr + j)) {
Swap(p_arr + i, p_arr + j);
}
}
}
}
void qsort(int nums[], int left, int right)
{
int i = 0, j = 0, pivot = 0;
if (left + Cutoff <= right) {
pivot = median3(nums, left, right);
i = left;
j = right;
for (;;) {
while (nums[++i] < pivot) { }
while (nums[--j] > pivot) { }
if (i < j) {
Swap(&nums[i], &nums[j]);
}
else {
break;
}
}
Swap(&nums[i], &nums[right]);
qsort(nums, left, i - 1);
qsort(nums, i + 1, right);
}
else {
// 不满3个元素进行选择排序
select_sort(nums + left, right - left + 1);
}
}
void quicksort(int nums[], int size)
{
qsort(nums, 0, size - 1);
}
参考文献
数据结构与算法分析第二版
以上是关于快速排序(C语言)的主要内容,如果未能解决你的问题,请参考以下文章