目录
快速排序的前世今生
快速排序核心思想
挖坑法代码
挖坑法动图演示
全部代码
如果将来你工作后,你的老板要让你写个排序算法,而你会的算法中竟然没有快速排序,我想你还是不要声张,偷偷去把快速排序算法找来敲进电脑,这样不至于被大伙儿嘲笑。
快速排序算法最早由图灵奖获得者Tony Hoare 设计出来的,是上世纪最伟大的计算机科学家之一。更牛的是,我们现在要学习的这个快速排序算法,被列为20世纪十大算法之一。我们这些学编程的还有什么理由不去学习它呢?
快速排序是冒泡排序的升级版,它们都属于交换类排序。它是通过不断比较和移动交换来实现排序的,只不过它的实现,增大了记录的比较和移动的距离,将较大的直接从前面移动到后面去,较小的直接从后面移动到前面,从而减少了移动的次数和比较的次数。
通过一趟排序将待排序记录分割成独立的两部分,其中一部分均比另一部分小,再分别对这两部分继续进行排序,从而达到有序。
//挖坑法
int PortSort2(int* a, int left, int right)
{
int MidIndex = GetMid(a, left, right);
Swap(&a[right], &a[MidIndex]);
//假设这个位置是坑
int key = a[right];
while (left < right)
{
//左边找到比key大的就填到右边的坑,左边形成新的坑
while (left < right && a[left] <= key)
{
++left;
}
a[right] = a[left];
//右边找到比key小的就填到左边的坑,右边形成新的坑
while (left < right && a[right] >= key)
{
--right;
}
a[left] = a[right];
}
//下标相遇了就把假设的中位数放入
a[left] = key;
return left;//返回中位数下标
}
//快速排序
void QuickSort1(int* a, int left, int right)
{
assert(a);
if (left >= right)//递归结束条件,两下标相遇
return;
//找出第一个中位数
int div = PortSort2(a, left, right);
//Printary(a + left, right - left + 1);
//printf("[%d %d] %d [%d %d]\n", left, div-1 , div ,div+1, right);
//下一次递归的范围:左边[left,div-1],div,右边[div+1,right]
//对中位数左边递归
QuickSort1(a, left, div - 1);
//对中位数右边递归
QuickSort1(a, div + 1, right);
}
#include
#include
#include
//交换函数
void Swap(int* p1, int* p2)
{
int temp = *p1;
*p1 = *p2;
*p2 = temp;
}
//打印函数
void Printary(int* a, int n)
{
for (int i = 0; i < n; i++)
{
printf("%d ", a[i]);
}
printf("\n");
}
//三数取中,保证不是最大也不是最小
int GetMid(int* a, int begin, int end)
{
int MidIndex = (begin + end) / 2;
if (a[begin] > a[MidIndex])
{
if (a[MidIndex] > a[end])
return MidIndex;
else if (a[end] > a[begin])
return begin;
else
return end;
}
else
{
//a[begin] < a[MidIndex]
if (a[MidIndex] < a[end])
return MidIndex;
else if (a[begin] > a[end])
return begin;
else
return end;
}
}
//挖坑法
int PortSort2(int* a, int left, int right)
{
int MidIndex = GetMid(a, left, right);
Swap(&a[right], &a[MidIndex]);
//假设这个位置是坑
int key = a[right];
while (left < right)
{
//左边找到比key大的就填到右边的坑,左边形成新的坑
while (left < right && a[left] <= key)
{
++left;
}
a[right] = a[left];
//右边找到比key小的就填到左边的坑,右边形成新的坑
while (left < right && a[right] >= key)
{
--right;
}
a[left] = a[right];
}
//下标相遇了就把假设的中位数放入
a[left] = key;
return left;//返回中位数下标
}
//快速排序
void QuickSort1(int* a, int left, int right)
{
assert(a);
if (left >= right)//递归结束条件,两下标相遇
return;
//找出第一个中位数
int div = PortSort2(a, left, right);
//Printary(a + left, right - left + 1);
//printf("[%d %d] %d [%d %d]\n", left, div-1 , div ,div+1, right);
//下一次递归的范围:左边[left,div-1],div,右边[div+1,right]
//对中位数左边递归
QuickSort1(a, left, div - 1);
//对中位数右边递归
QuickSort1(a, div + 1, right);
}
//快速排序
void TestQuickSort()
{
int a[] = { 6,1,2,7,9,3,4,5,10,8 };
Printary(a, sizeof(a) / sizeof(a[0]));
QuickSort1(a, 0, sizeof(a) / sizeof(a[0]) - 1);
Printary(a, sizeof(a) / sizeof(a[0]));
}
int main()
{
TestQuickSort();
return 0;
}
排序结果示例