思想
分治法
过程
从数列中取出一个数作为基准数,一般取第一个数
将大于等于这个数的数全放在他的右边,小于等于它的数全放在他的左边
再对左右区间重复第二步,直到各区间只有一个数。
代码实现(C语言)
快排的核心思想是partition,对于实现partition有两种方法:交换法和“挖坑填数法”(后者执行的次数少)
快速排序可以用递归和非递归的形式实现。
递归实现
#include<stdio.h>
#define DEBUG
/* //交换法实现的quicksort
void swap(int *a, int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
void quicksort(int arr[], int left, int right)
{
if (left >= right)//注意要写这个递归跳出的条件
return;
int i = left;
int j = right;
int key = arr[left];
while (i < j){
while(i < j && arr[j] >= key)
j--;
while(i < j && arr[i] <= key)
i++;
if (i < j)
swap(&arr[i], &arr[j]);
}
swap(&arr[left], &arr[i]);
quicksort(arr, left, i-1);
quicksort(arr, i+1, right);
}
*/
//挖坑填数法实现的quicksort
void quicksort(int arr[], int left, int right)
{
if (left >= right)//注意递归跳出的条件
return;
int i = left;
int j = right;
int key = arr[left];
while (i < j){
while (arr[j] >= key && i < j)
j--;
arr[i] = arr[j];
while (arr[i] <= key && i < j)
i++;
arr[j] = arr[i];
}
arr[i] = key;
#ifdef DEBUG
int k;
for (k = left; k <=right; k++)
printf("arr[%d]=%d ", k, arr[k]);
printf("\n");
#endif
quicksort(arr, left, i-1);
quicksort(arr, i+1, right);
}
int main()
{
int arr[100]; //输入序列所存放的数组
int len = 0;
char c;//用于对回车键进行检测
printf("请输入任意个数,按回车键结束\n");
printf("Input:\n");
while(1) {
scanf("%d", &arr[len++]);
c = getchar();
if (c == '\n')
break;
}
quicksort(arr, 0, len-1);
printf("quicksort:\n");
int i;
for (i=0; i<len; i++)
printf("%d ", arr[i]);
printf("\n");
return 0;
}
非递归实现
#include<stdio.h>
//分隔 用"挖坑填数法"实现
int partition(int arr[], int left, int right)
{
int i = left;
int j = right;
int key = arr[left];
while (i < j){
while (arr[j] >= key && i < j)
j--;
arr[i] = arr[j];
while (arr[i] <= key && i < j)
i++;
arr[j] = arr[i];
}
arr[i] = key;
int k;
for (k = left; k <=right; k++)
printf("arr[%d]=%d ", k, arr[k]);
printf("\n");
return i;
}
//非递归实现快排
void quicksort(int arr[], int len)
{
int left = 0;//左指针
int right = len - 1;//右指针
int b[1000] = {0};//用于存放左右索引
int n = 0;//记录当前b中的索引数目
int index;
b[n++] = left;//该思路来自于用C++用栈来实现非递归快排,c语言中没有栈这种数据结构
b[n++] = right;
while(n != 0){
right = b[--n];
left = b[--n];
index = partition(arr, left, right);
printf("index = %d\n", index);
if (index - 1 > left){
b[n++] = left;
b[n++] = index -1;
}
if (index + 1 < right){
b[n++] = index + 1;
b[n++] = right;
}
}
}
int main()
{
int arr[100]; //输入序列所存放的数组
int len = 0;
char c;//用于对回车键进行检测
printf("请输入任意个数,按回车键结束\n");
printf("Input:\n");
while(1) {
scanf("%d", &arr[len++]);
c = getchar();
if (c == '\n')
break;
}
quicksort(arr, len);
printf("quicksort:\n");
int i;
for (i=0; i<len; i++)
printf("%d ", arr[i]);
printf("\n");
return 0;
}
性能分析
时间复杂度
快排的时间性能取决于递归的深度
最优情况,排序n个关键字,递归树深度为
l
o
g
2
n
log_2n
log2n