前言
快速排序是一种交换排序,它由C. A. R. Hoare在1962年提出。
算法思想
快速排序的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分:分割点左边都是比它小的数,右边都是比它大的数。
然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
动态效果示意图:
详细的图解往往比大堆的文字更有说明力,所以直接上图:
上图中,演示了快速排序的处理过程:
初始状态为一组无序的数组:2、4、5、1、3。
经过以上操作步骤后,完成了第一次的排序,得到新的数组:1、2、5、4、3。
新的数组中,以2为分割点,左边都是比2小的数,右边都是比2大的数。
因为2已经在数组中找到了合适的位置,所以不用再动。
2左边的数组只有一个元素1,所以显然不用再排序,位置也被确定。(注:这种情况时,left指针和right指针显然是重合的。因此在代码中,我们可以通过设置判定条件left必须小于right,如果不满足,则不用排序了)。
而对于2右边的数组5、4、3,设置left指向5,right指向3,开始继续重复图中的一、二、三、四步骤,对新的数组进行排序。
代码实现
#include <stdio.h>
int a[1005];
//快速排序
void Quick_Sort(int l, int r) {
if(l >= r) return;
int i = l;
int j = r;
int x = a[l];
while (i < j) {
while (i < j && a[j] >= x) j--;
if (i < j) a[i++] = a[j];
while (i < j && a[i] < x) i++;
if (i < j) a[j--] = a[i];
}
a[i] = x;
Quick_Sort(l, i - 1);//比i小的继续划分
Quick_Sort(i + 1, r);//比i大的继续划分
}
int main() {
int n;
scanf("%d", &n);//输入n个数进行快速排序
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
Quick_Sort(1, n);
for (int i = 1; i <= n; i++) {
printf("%d ", a[i]);
}
printf("\n");
return 0;
}
算法分析
1、快速排序算法的性能
2、时间复杂度
当数据有序时,以第一个关键字为基准分为两个子序列,前一个子序列为空,此时执行效率最差。
而当数据随机分布时,以第一个关键字为基准分为两个子序列,两个子序列的元素个数接近相等,此时执行效率最好。
所以,数据越随机分布时,快速排序性能越好...
课后习题
【2019年真题】排序过程中,对尚未确定最终位置的所有元素进行一遍处理称为一“趟”。下列序列中,不可能是快速排序第二趟结果的是()
A. 5,2,16,12,28,60,32,72 B. 2,16,5,28,12,60,32,72
C. 2,12,16,5,28,32,72,60 D. 5,2,12,28,16,32,72,60
参考答案:D
【2014年真题】下列选项中,不可能是快速排序第2趟排序结果的是()
A.2,3,5,4,6,7,9
B.2,7,5,6,4,3,9
C.3,2,5,4,7,6,9
D.4,2,3,5,7,6,9
参考答案:C
答案解析:快排的阶段性排序结果的特点是,第 i 趟完成时,会有 i 个以上的数出现在它最终将要出现的位置,即它左边的数都比它小,它右边的数都比它大。题目问第二趟排序的结果,即要找不存在 2 个这样的数的选项。A 选项中 2、3、6、7、9 均符合,所以 A 排除;B选项中,2、9 均符合,所以 B 排除;D 选项中 5、9 均符合,所以D选项排除;最后看C选项,只有9一个数符合,所以C不可能是快速排序第二趟的结果。
【2011年这题】为实现快速排序算法,待排序序列宜采用的存储方式是()
A.顺序存储
B.散列存储
C.链式存储
D.索引存储
解答:A。内部排序采用顺序存储结构。
【2010年真题】采用递归方式对顺序表进行快速排序。下列关于递归次数的叙述中,正确的是()。
A.递归次数与初始数据的排列次序无关。
B.每次划分后,先处理较长的分区可以减少递归次数。
C.每次划分后,先处理较短的分区可以减少递归次数。
D.递归次数与每次划分后得到的分区的处理顺序无关。
参考答案:D
答案解析:考查快速排序。
递归次数与各元素的初始排列有关。如果每一次划分后分区比较平衡,则递归次数少,如果划分后分区不平衡,则递归次数多。递归次数与处理顺序无关。
登录后开始许愿
暂无评论,来抢沙发