快速排序
快速排序(Quicksort)是对冒泡排序的一种改进。由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
以数组首元素为主元的快排实现:
void quickSort_start(int data[], int length, int start, int end)
{
if (data == NULL || length <= 1 || start < 0 || start >= end || end >= length)
return;
int key = data[start];
int index = start;
int i = start + 1;
for (; i < length; i++)
{
if (data[i] < key)//注意此处,< 得到的结果是升序,> 得到的结果是降序
{
++ index;
if (index != i)
{
int temp = data[index];
data[index] = data[i];
data[i] = temp;
}
}
}
if (index != start)
{
int temp = data[index];
data[index] = data[start];
data[start] = temp;
}
quickSort_start(data, length, start, index);
quickSort_start(data, length, index + 1, end);
}
以数据尾元素为主元的快排实现:
void quickSort_end(int data[], int length, int start, int end)
{
if (data == NULL || length <= 1 || start < 0 || end >= length || start >= end)
return;
int key = data[end];
int index = start - 1;
int i = start;
for (; i < end; i++)
{
if (data[i] > key) //注意此处,< 得到的结果是升序,> 得到的结果是降序
{
++ index;
if (index != i)
{
int temp = data[index];
data[index] = data[i];
data[i] = temp;
}
}
}
++ index;
if (index != end)
{
int temp = data[end];
data[end] = data[index];
data[index] = temp;
}
quickSort_end(data, length, start, index - 1);
quickSort_end(data, length, index + 1, end);
}
以数组中间元素为主元的双向扫描快排:
void quickSort_pivot(int data[], int length, int start, int end)
{
if (data == NULL || length <= 1 || start < 0 || end >= length || start >= end)
return;
int left = start;
int right = end;
int pivot = data[(start + end) / 2];
while (left < right)
{
while (data[left] < pivot)
++ left;
while (data[right] > pivot)
-- right;
if (left < right)
{
int temp = data[left];
data[left] = data[right];
data[right] = temp;
++ left;
-- right;
}
}
quickSort_pivot(data, length, start, right);
quickSort_pivot(data, length, right + 1, end);
}
随机快排
随机快排本质上并无太大变化,只是在数组中随机选取一个元素作为主元:
swap(data[rand(start, end)], data[start]);
int key = data[start];
随机选取一个元素后,将这个元素与首元素交换,再选取首元素作为主元,后续便与前面做法无异了,另外亦可将随机元素与尾元素交换,然后选取尾元素作为主元,做法上都是一样的道理。
三数取中
主元的选取可以是数组首元素、尾元素、中间元素或者随机元素,那么主元的选取对排序的效率会不会有影响呢?
答案是肯定的,不同的主元选取,导致的比较次数不同,带来的效率也是不一样的。
采取data[start],data[pivot],data[end]三者中第二大的元素作为主元,便能尽最大限度保证快速排序算法不会出现O(N^2)的最坏情况,这就是所谓的三数取中分割方法。
int pivot=(start + end)/2;
if(data[start] < data[pivot])
swap(data[p], data[pivot]);
if(data[end] < data[pivot])
swap(data[end], data[pivot]);
if(a[end]<a[start])
swap(data[end],data[start]);
int key = data[start];