快速排序的单趟排序有三种,分别是hoare法、挖坑法、双指针法
个人比较喜欢最后一种的双指针法
所以下面的单趟排序将使用双指针法实现
一、基本思路
1、设置指针位置
cur:寻找比key小的数,找到比key小的数,和prev的下一位交换——丢到左边
prev:是左右区间的临时分界点,prev(右边)紧跟比key大的数
key:哨兵位或最终分界点,不参与比较,最后cur检索完毕时,和prev的下一位交换
第一种方式:key在最左边
以最左边的值作为key,由于key不参与比较,所以cur最开始指向key的下一位
第二种方式:key在最右边
以最右边的值作为key,cur指向第一位
下面的分析采用第一种
2、开始比较
侦察兵cur出发,找安全地,
找到没有地雷的点,士兵长跟着走一个位置,侦察兵和士兵长交换当前自身状态信息
没找到安全地,士兵长停下,(侦察兵喊人解决),侦察兵继续走
cur出发找比key小的,
找到了,则prev向右移动一个位置,prev和cur指向的数据交换
没找到比key小的,即找到大于等于key的,prev停下,cur继续走
(1)第一步:
(2)第二步:
找到的是比key小的,步骤同第一步
(3)第三步:
此时cur 指向 7,比 key大,prev停下,cur继续向右移动
(4)第四步:
cur指向 9,比key大,prev继续歇着,cur继续向右移动
(5)第五步:
cur指向3,比key小,prev往前走,两者交换数据
各种情况已经罗列了,下面就不继续分析了
(6)最后一步:
跳出循环的时候,我们需要把key值加入到 调整过的队列中,
key 是最终分界点,prev只是临时分界点
需要将prev和key交换
二、单趟排序代码实现
//单趟排序的范围是 [left , right]
void SingleSort(int* a,int left,int right)
{
int prev, cur, key;
prev = left;
cur = left + 1;
key = a[left]; //将最左边的值作为key值
while (cur<=right)
{
//若找到比key小的数,则交换
if (a[cur] < key)
{
//prev++;
//Swap(a[cur], a[prev]);
Swap(a[cur], a[++prev]);
}
cur++;
}
Swap(a[prev], a[left]); //将临时分界点替换为最终分界点
}
三、结果测试
int main() {
int arr[] = { 6,1,2,7,9,3,4,5,10,8 };
SingleSort(arr, 0, sizeof(arr) / sizeof(arr[0]) - 1);
for (size_t i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}