快速排序的单趟排序有三种,分别是hoare法、挖坑法、双指针法
个人比较喜欢最后一种的双指针法
所以下面的单趟排序将使用双指针法实现
cur:寻找比key小的数,找到比key小的数,和prev的下一位交换——丢到左边
prev:是左右区间的临时分界点,prev(右边)紧跟比key大的数
key:哨兵位或最终分界点,不参与比较,最后cur检索完毕时,和prev的下一位交换
第一种方式:key在最左边
以最左边的值作为key,由于key不参与比较,所以cur最开始指向key的下一位
第二种方式:key在最右边
以最右边的值作为key,cur指向第一位
下面的分析采用第一种
侦察兵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; }