问题引入
快速排序法(quick sort)是公认的最快的排序方法之一(根据不同的待排序对象而定),虽然快速排序法在最差状况下时间复杂度可以达O(n²),但是在多数的情况下,快速排序法的效率是比较高的。
快速排序法的基本原理是在数列中找出适当的中心点,然后将数列一分为二,分别对左边与右边数列进行排序,决定快速排序法效率的正是中心点的选择。 本文所介绍的“快速排序算法(形式1)”是比较常见的一种快速排序算法的形式,它最容易理解, 也最符合中心点分割数列并进行左右排序的概念。如果你是初次接触“快速排序算法”将对你理解快速排序算法原理大有裨益,如果你想要进行深层次的了解和学习,请在分类栏中点击“算法”并找到“快速排序算法(形式2)、快速排序算法(形式3)”进行了解。
问题分析
如下所示,将最左边的数设定为中心点,并记录其值为 s:
第一步:令索引 i 从数列左方往右方找,直到找到大于 s 的数令索引 j 从数列左右方往左方找,直到找到小于 s 的数 如果 i >= j,则离开回圈;
第二步:如果 i < j,则交换索引i与j两处的值 将左侧的中心点与 j 进行交换对中心点左边进行递回对中心点右边进行递回;
通过以上两个步骤,最终中心点左边的值都会小于s,中心点右边的值都会大于s,如此再对中心点左右两边进行递回,就可以对完成排序的目的。(对1、2两步骤进行多次循环即可)
例如:
“橙色”表示要交换的数,“[红色]”表示中心点:
[41] 24 76 11 45 64 21 69 19 36
[41] 24 36 11 45 64 21 69 19 76
[41] 24 36 11 19 64 21 69 45 76
[41] 24 36 11 19 21 64 69 45 76
21 24 36 11 19 [41] 64 69 45 76
上述例子中,经过一趟快速排序最终 41 左边的值都比它小,而右边的值都比它大,之后再循环进行递回至排序完成,即快速排序算法(形式1)的排序过程。
代码实现
说明:采用C语言,编译环境为DevC++。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX 10
#define SWAP(x,y) {int t; t = x; x = y; y = t;} //用宏命令定义了函数SWAP用于数据交换
void quicksort(int number[], int left, int right){
int i, j, s;
if(left < right){
s = number[left]; i = left;
j = right + 1;
}
while(1){
// 向右找
while(i + 1 < MAX && number[++i] < s) ;
// 向左找
while(j -1 > -1 && number[--j] > s) ;
if(i >= j){
break;
}
SWAP(number[i], number[j]);//元素交换
number[left] = number[j];
number[j] = s;
quicksort(number, left, j-1); // 对左边进行递回
quicksort(number, j+1, right); // 对右边进行递回
}
}
//主函数
int main(){
int number[MAX] = {0};
int i, num;
srand(time(NULL)); //刷新每次产生的随机数,若无此句,每次随机数相同,亲自尝试一下便知
printf("排序前:");
for(i = 0; i < MAX; i++){
number[i] = rand() % 100; //产生0-99的随机数,这里没有采用固定的数组值进行排序,随机生成
printf("%d ", number[i]);//输出数组数据
}
quicksort(number, 0, MAX-1);
printf("\n排序后:");
for(i = 0; i < MAX; i++){
printf("%d ", number[i]);
}
printf("\n");
return 0;
}
运行结果
说明:仅截取了一次过程,可在运行过程中查看,也可根据需要对代码部分进行调整。
写在最后:
读两遍下来,如果仍然有不清楚的地方,可在评论区留言。
如果你有其他感到困惑的问题,欢迎留言。