目录
算法思想
当数组只有一个数或0个数时被认为是有序数组。快速排序使用分治法策略把一个数组分为两个子数组而后分别排序。
步骤:
1.选出一个数作为基准数(pivot)。
2.由后向前找比基准数小的数arr[right]。
3.由前向后找比基准数大的数arr[left]。
4.交换两数。
5.重复执行2、3步骤,直到left==right。
6.交换arr[left]与pivot的位置,此时左边的数都不大于pivot,右边的数不小于pivot。
7.再对左右区间重复以上所有步骤,直到各个区间只有一个或零个数。
实现代码
#define _CRT_SECURE_NO_WARNINGS
#define SIZE 10
#include <stdio.h>
#include <stdlib.h>
void swap(int* x, int* y)
{
int tmp = *x;
*x = *y;
*y = tmp;
}
void myQuick_sort(int* arr, int start, int end) //快速排序
{
if (start >= end)
return;
int pivot = arr[start];
int left = start, right = end;
while (left < right)
{
while (arr[right] >= pivot && left < right)//选择第一个数为pivot一定先从右边开始,这样当left和right重合时指向的数一定<=pivot
right--;//找到第一个右边比pivot小的
while (arr[left] <= pivot && left < right)
left++;//找到第一个左边比pivot大的
if (left < right)
{
swap(&arr[left], &arr[right]);//交换
}
}
swap(&arr[left], &arr[start]);//left与right重合
myQuick_sort(arr, start, left - 1);
myQuick_sort(arr, left + 1, end);
}
void Input(int* arr, int len)
{
for (int i = 0; i < len; i++)
{
scanf("%d", &arr[i]);
}
}
void Output(int* arr, int len)
{
for (int i = 0; i < len; i++)
{
printf("%d ", arr[i]);
}
}
int main()
{
int *arr = (int*)malloc(sizeof(int)*SIZE);
int len = SIZE;
printf("数组元素:\n");
Input(arr, len);
myQuick_sort(arr, 0, len - 1);
printf("排序后:\n");
Output(arr, len);
free(arr);
return 0;
}
运行结果
结果一:
结果二:
时间复杂度
一般在问题规模为n时时间复杂度T(n)= Ο(nlogn)。最坏情况下T(n) = Ο(n2) 。
最好的情况下:
当n=1或0时,T(n) = 1,
当n>1时,T(n) =2T(n/2)+n 2T(n/2)即刚好分一半时,n为while(left<right)时的时间。
T(n) = 2T(n/2)+n
= 2(2T(n/22)+n/2)+n
= 22T(n/22)+2n
= 2K T(n/2K)+Kn
设n = 2K, T(n) = n+nlogn
T(n) = O(nlogn)
在最坏的情况下:
当n=1或0时,T(n) = 1,
当n>1时,T(n) = T(n-1)+n, T(n-1)是只有一个分在一组,其他分在另一组
T(n) = T(n-1)+n
= T(n-2)+(n-1)+n
= (n+(n-1)+……+2+1)
=O(n2)
当基准数选择左边第一个时,快速排序一定是先扫描右边的数,再扫描左边的数!!!!!
这样left、right重合时的数一定小于基准数