- 快速排序由于排序效率在同为O(N*logN)的几种排序方法中效率较高,因此经常被采用,再加上快速排序思想----分治法也确实实用,因此很多软件公司的笔试面试,包括像腾讯,微软等知名IT公司都喜欢考这个,还有大大小的程序方面的考试如软考,考研中也常常出现快速排序的身影。现在我们就来学习一下快速排序的两种形式:
交换法
假设我们现在对“6 1 2 7 9 3 4 5 10 8”这个10个数进行排序。先将第一个数当成基准数,然后以i, j当成哨兵分别指向数组的首尾,第一次让j先移动,移动到比基准数小的数字时停下,然后让i移动至比基准数大的数字停下,交换arr[i]和arr[j],一直遍历,知道i和j两个哨兵相遇停止,然后让基准数和i和j相遇的值交换,完成第一次遍历,然后进行递归分别计算左右两个小数组。下面上代码,方便大家理解:
#include <stdio.h>
int a[101],n;//定义全局变量,这两个变量需要在子函数中使用
void quicksort(int left,int right){
int i, j, t, temp;
if(left > right){
return;
}
temp = a[left]; //temp中存的就是基准数
i = left;
j = right;
while(i !=j ){//顺序很重要,要先从右往左找
while(a[j] >= temp && i<j){
j--;
}
//再从左往右找
while(a[i] <= temp && i<j){
i++;
}
//交换两个数在数组中的位置
if(i < j){//当哨兵i和哨兵j没有相遇时
t = a[i];
a[i] = a[j];
a[j] = t;
}
}
//最终将基准数归位
a[left] = a[i];
a[i] = temp;
quicksort(left, i-1);//继续处理左边的,这里是一个递归的过程
quicksort(i+1, right);//继续处理右边的,这里是一个递归的过程
}
int main(){
int i, j, t;
//读入数据
scanf("%d", &n);
for(i = 1; i <= n; i++){
scanf("%d",&a[i]);
}
quicksort(1, n); //快速排序调用
//输出排序后的结果
for(i = 1; i <= n; i++){
printf("%d ",a[i]);
}
return 0;
}
埋坑法
这个和交换法很像,不过这个不像交换法一样待两个数都确定后交换,而是发现一个就将它提出来,将它放到应该放到的位置,然后再调整下一个该调整位置的数字。具体代码如下:
(区别可以自行看代码)
#include <stdio.h>
int arr[101],n;//定义全局变量,这两个变量需要在子函数中使用
void quicksort(int left, int right)
{
if (left < right)
{
//Swap(s[l], s[(l + r) / 2]); //将中间的这个数和第一个数交换 参见注1
int i = left, j = right, temp = arr[left];
while (i < j)
{
while(i < j && arr[j] >= temp){// 从右向左找第一个小于x的数
j--;
}
if(i < j) {
arr[i++] = arr[j];
}
while(i < j && arr[i] < temp){// 从左向右找第一个大于等于x的数
i++;
}
if(i < j) {
arr[j--] = arr[i];
}
}
arr[i] = temp;
quicksort(left, i - 1); // 递归调用
quicksort(i + 1, right);
}
}
int main(){
int i, j, t;
//读入数据
scanf("%d", &n);
for(i = 1; i <= n; i++){
scanf("%d",&arr[i]);
}
quicksort(1, n); //快速排序调用
//输出排序后的结果
for(i = 1; i <= n; i++){
printf("%d ",arr[i]);
}
return 0;
}
想必大家在看完这两种不同的快速排序后,肯定会对这种排序有比较深刻的认识吧。