基本原理:
递归实现
1.Hoare版本
原理图入下所示:
单趟排序步骤入下:
1. 选出一个key,一般选择数组最左面的即下标为0的元素,
2.以最左边的元素为L,最右边的元素为R。R一定先向右走找小于key的数停下,L再向右走找大于 key的数停下,然后交换L 与 R的数据。(若顺序不对会导致key无法到正确的位置)
3.L于R在进行2步骤直到L于R相遇停下。
4.交换key的数据与此时L或R的数据(两者此时相同)然后返回。
递归步骤:
用交换后的key为分割线 分为 [L , key-1] 与 [ key+1,R] 两组进行递归。
// 快速排序hoare版本
int PartSort1(int* a, int left, int right)
{
int keyi = left;
while (left < right)
{
//R一定先向右找小:
while (left < right && a[right] >= a[keyi])
{
right--;
}
//L向左找大:
while (left < right && a[left] <= a[keyi])
{
left++;
}
swap(&a[left], &a[right]);
}
swap(&a[left], &a[keyi]);
return left;
}
void QuickSort(int* a, int left, int right)
{
//当只有一个数据或者没有数据时不要递归。
if (left >= right)
{
return;
}
int keyi = PartSort1(a, left, right);
QuickSort(a, left, keyi - 1);
QuickSort(a, keyi + 1, right);
}
2.挖坑法
由于Hoare版本的单趟存在许多细节,一不小心就会写错。后人逐渐有了其他版本。
原理图入下:
单趟排序步骤入下:
1.选择左边第一个数为坑位。将其数据放在临时变量key中。
2.以最右边的元素为R。R向左走找小于key的数,然后将此R放入坑位中然后R形成新的坑位。
3.以最左边的元素为L,L向左走找大于key的数,然后将此L放入坑位中然后L形成新的坑位。
4.交替走2,3步骤直到L与R相遇停下,将key放入L与R相遇的坑位。然后返回。
递归步骤:
用交换后的key为分割线 分为 [L , key-1] 与 [ key+1,R] 两组进行递归。
// 快速排序挖坑法
int PartSort2(int* a, int left, int right)
{
int key = a[left];
int hole = left;
while (left < right)
{
//找小:
while (left < right && a[right] >= key)
{
right--;
}
a[hole] = a[right];
hole = right;
//找大
while (left < right && a[left] <= key)
{
left++;
}
a[hole] = a[left];
hole = left;
}
a[hole] = key;
return hole;
}
void QuickSort(int* a, int left, int right)
{
//当只有一个数据或者没有数据时不要递归。
if (left >= right)
{
return;
}
int keyi = PartSort2(a, left, right);
QuickSort(a, left, keyi - 1);
QuickSort(a, keyi + 1, right);
}
3.前后指针法
原理图入下:
单趟排序步骤入下:
1.选第一个数为key,第一个数为prev,后一个数为cur;
2.判断cur的值是否小于等于key,若小于等于则prev++,然后交换prev与cur的值,然后cur++;若大于key的值则只有cur++即可。
3.当cur遍历完数组后停止,然后交换此时prev与key的值。然后返回。
递归步骤:
用交换后的key为分割线 分为 [L , key-1] 与 [ key+1,R] 两组进行递归。
// 快速排序前后指针法
int PartSort3(int* a, int left, int right)
{
int prev = left;
int cur = prev + 1;
int keyi = left;
while (cur <= right)
{
if (a[cur] < a[keyi])
{
prev++;
swap(&a[prev], &a[cur]);
}
cur++;
}
swap(&a[prev], &a[keyi]);
return prev;
}
void QuickSort3(int* a, int left, int right)
{
if (left >= right)
{
return;
}
int keyi = PartSort3(a, left, right);
QuickSort(a, left, keyi - 1);
QuickSort(a, keyi + 1, right);
}