思路:
首先选出一个key(一般为最右边或者最做左边的数),左右分别有两个指针,右边找比key小的数,左边紧随其后找比key大的数,谁先找到的话先停下,同时找到就交换二者的位置,然后二者相遇时就将相遇的值重新定义为key,即交换其与key的位置,单趟结束时,左边均为比key小的值,右边均为比key大的值
光从思路入手,相信许多小伙伴第一次写的代码是这样的:
- void quicksort(int *a ,size_t size)
- {
- int left = 0;
- int right = size-1;
- int key = a[left];
- while (left<right)
- {
- while (a[right] > key)
- {
- right--;
- }
- while (a[left] < key)
- {
- left++;
- }
- Swap(&a[left], &a[right]);
- }
- }
但这种代码会导致死循环,假设左右值均与key相同的话,哪么二者就会不停的交换从而导致死循环,在这里我们做一些小优化:
- void quicksort(int *a ,size_t size)
- {
- int left = 0;
- int right = size-1;
- int key = a[left];
- while (left<right)
- {
- while (a[right] >= key)
- {
- right--;
- }
- while (a[left] <= key)
- {
- left++;
- }
- Swap(&a[left], &a[right]);
- }
- }
但是随之而来的就有一个更大的问题,那就是如果定义的可以为最左且右边的数都比key大的话,哪么就会造成越界的问题,一次我们在优化一下:
- void quicksort(int *a ,size_t size)
- {
- int left = 0;
- int right = size-1;
- int key = a[left];
- while (left<right)
- {
- while (left<right && a[right] >= key)
- {
- right--;
- }
- while (left<right && a[left] < key)
- {
- left++;
- }
- Swap(&a[left], &a[right]);
- }
- }
故完整的单趟过程如下:
- void quicksort(int *a ,int size)
- {
- int left = 0;
- int right = size-1;
- int key = a[left];
- int prekey = left;
- while (left<right)
- {
- while (left<right && a[right] >= key)
- {
- right--;
- }
- while (left < right && a[left] <= key)
- {
- left++;
- }
- Swap(&a[left], &a[right]);
- }
- Swap(&a[prekey], &a[left]);
- }
在这里顺便说一个问题,为什么要将左边的值作为key,其实这是为了保证第二次的key比第一次的小,这就保证了代码顺利的运行。
具体代码如下:
- #include<stdio.h>
- void print(int*a, int size)
- {
- for (int i = 0; i < size; i++)
- {
- printf("%d ", a[i]);
- }
- }
- void Swap(int* a, int* b)
- {
- int temp = *a;
- *a = *b;
- *b = temp;
- }
- void quicksort(int *a ,int begin,int end)
- {
- if (begin >= end)
- {
- return;
- }
- int left = begin;
- int right = end;
- int key = a[left];
- int prekey = left;
- while (left<right)
- {
- while (left<right && a[right] >= key)
- {
- right--;
- }
- while (left < right && a[left] <= key)
- {
- left++;
- }
- Swap(&a[left], &a[right]);
- }
- Swap(&a[prekey], &a[left]);
- prekey = left;
- quicksort(a, begin, prekey - 1);
- quicksort(a, prekey + 1, end);
- }
-
- int main()
- {
- int a[] = {6,1,2,7,9,3,4,5,10,8 };
- int size = sizeof(a) / sizeof(a[0]);
- quicksort(a, 0, size-1);
- print(a, size);
- return 0;
- }
接下来我们就再来介绍几种方法:
依据上图所示,首先将最左边的位置作为坑,然后让右边先动,找到比原坑位小的就将其作为新的坑位,并交换key的值,以此类推,这样就完成了以此过程,接下来利用递归实现即可。
最主要的就是要明白右边先动,找到变坑,然后左边再动,找到小的再变坑即可完成一次过程。
具体代码如下:
- #include<stdio.h>
- void quicksort(int* a, int begin, int end)
- {
- int key = a[begin];
- int piti = begin;
- while (begin < end)
- {
- //右边找小
- while (begin < end && a[end] >= key)
- {
- --end;
- }
- a[piti] = a[end];
- piti = end;
- //左边找大
- while (begin<end&& a[begin]<=key)
- {
- ++begin;
- }
- a[piti] = a[begin];
- piti = begin;
- }
- a[piti] = key;
- }
思路:
首先定义两个指针指向同一个位置,先让cur先走,找到小就让prev在走,大的话就先停下,让cur在往后找小即可。
完整代码如下:
- void quicksort(int* a, int begin, int end)
- {
- int prev = begin;
- int cur = begin + 1;
- int key = begin;
- while (cur <= end)
- {
- if (a[cur] < a[key] && ++prev!=cur)
- {
- Swap(&a[prev], &a[cur]);
- }
- cur++;
- }
- Swap(&a[prev], &a[key]);
- key = prev;
- }