1.什么是快速排序
快速排序是由东尼·霍尔所发展的一种排序算法。在平均状况下,排序 n 个项目要 Ο(nlogn) 次比较。在最坏状况下则需要 Ο(n²) 次比较,
但这种状况并不常见。事实上,快速排序通常明显比其他 Ο(nlogn) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效
率地被实现出来。
快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists).快速排序又是一种分而治之思想
在排序算法上的典型应用。本质上来看,快速排序应该算是在冒泡排序基础上的递归分治法。
快速排序的名字起的是简单粗暴,因为一听到这个名字你就知道它存在的意义,就是快而且效率高,它是处理大数据最快的排序算法之一了.
虽然最坏情况下的时间复杂度达到了 O(n²),但是快速排序似乎比较优秀,在大多数情况下都比平均时间复杂度为 O(nlogn) 的排序算法表
现要更好,可是这是为什么呢,经网友查了N多资料终于在《算法艺术与信息学竞赛》上找到了满意的答案:快速排序的最坏运行情况是 O(n²),
比如说顺序数列的快排。但它的平摊期望时间是 O(nlogn),且 O(nlogn) 记号中隐含的常数因子很小,比复杂度稳定等于 O(nlogn) 的归并
排序要小很多。所以,对绝大多数顺序性较弱的随机数列而言,快速排序总是优于归并排序。
--引用自https://www.runoob.com/w3cnote/quick-sort-2.html
2. 排序算法步骤
1.从数列中挑出一个元素,称为 "基准"(pivot);
2.重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。
在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
3.递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序;
拓展:
pivot 英 [ˈpɪvət] 美[ˈpɪvət]
n.支点; 枢轴; 中心点; 最重要的人(或事物); 中心; 核心;
v.(使)在枢轴上旋转(或转动) ;
3.快速排序实现及其他排序方法性能比较测试
/*
文件名:performTest.c
作者:Muten
编码时间:20201027
编码目的:简单测试冒泡,希尔及快速排序算法的效率
测试环境:Mircosoft Visual Studio Professional 2015 版本14.0.25431.01 Update3
版本信息:VER1.0
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <windows.h>
#include <sys/timeb.h>
#define MAX 50000
void PrintArr(int arr[], int length)
{
for (int i = 0; i < length; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
long getSystemtime()
{
struct timeb tb;
ftime(&tb);
return tb.time * 1000 + tb.millitm;
}
// 快速排序
void QuickSort(int arr[], int start, int end)
{
int i = start;
int j = end;
// 基准数
int temp = arr[start];
if (i < j)
{
while (i < j)
{
// 从右向左去找比基准数小的,经过本次循环,要么i = j(此时整个大循环退出),要么找到了那个比基准数小的数
while (i < j && arr[j] >= temp)
{
j--;
}
// 填坑
if (i < j)
{
//printf("line 42.用找到的比pivot大的数替换掉原来的pivot所在的位置index[%d]\n", i);
arr[i] = arr[j];
i++;
}
// 从左向右,找比基准数大的数
while (i < j && arr[i] < temp)
{
i++;
}
// 填坑
if (i < j)
{
arr[j] = arr[i];
j--;
}
}
// 把基准数放到i位置
arr[i] = temp;
QuickSort(arr, start, i - 1);
QuickSort(arr, i + 1, end);
}
}
// 从小到大排序 希尔排序
void shellSort(int arr[], int length)
{
int increasement = length;
int i, j, k;
do {
//printf("19 what is wrong?\n");
increasement = increasement / 3 + 1;
for (i = 0; i < increasement; i++)
{
for (j = i + increasement; j < length; j += increasement)
{
if (arr[j] < arr[j - increasement])
{
int temp = arr[j];
for (k = j - increasement; k >= 0 && temp < arr[k]; k -= increasement)
{
arr[k + increasement] = arr[k];
}
arr[k + increasement] = temp;
}
}
}
} while (increasement > 1);
}
void swap(int *a, int *b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
void bubbleSort(int arr[], int length)
{
for (int i = 0; i < length; i++)
{
for (int j = 0; j < length - 1; j++)
{
if (arr[j] > arr[j + 1])//从小到大排序
{
swap(&arr[j], &arr[j + 1]);
}
}
}
}
int main(void)
{
int arr[MAX];
int arr1[MAX];
int arr2[MAX];
srand((unsigned int)time(NULL));
for (int i = 0; i < MAX; i++)
{
int randNum = rand() % MAX;
arr[i] = randNum;
arr1[i] = randNum;
arr2[i] = randNum;
}
//printf("排序前:\n");
long t_start_1 = getSystemtime();
//PrintArr(arr, MAX);
shellSort(arr, MAX);
//printf("排序后:\n");
long t_end_1 = getSystemtime();
//PrintArr(arr, MAX);
printf("希尔排序%d个元素,所需时间:%ld 毫秒\n", MAX, t_end_1 - t_start_1);
long t_insert_start_1 = getSystemtime();
QuickSort(arr1, 0,MAX-1);
//printf("排序后:\n");
long t_insert_end_1 = getSystemtime();
//PrintArr(arr1, MAX);
printf("快速排序%d个元素,所需时间:%ld 毫秒\n", MAX, t_insert_end_1 - t_insert_start_1);
long t_bubble_start_1 = getSystemtime();
bubbleSort(arr, MAX);
long t_bubble_end_1 = getSystemtime();
//PrintArr(arr, MAX);
printf("冒泡排序%d个元素,所需时间:%ld 毫秒\n", MAX, t_bubble_end_1 - t_bubble_start_1);
}
4.测试结果