最常用的排序——快速排序

是一种不浪费空间又可以快一点的排序算法。

假设对“6 1 2 7 9 3 4 5 10 8”这10个数进行排序。首先在这个序列里随便找一个数作为基准数。为了方便,让6作为基准数,将这个序列中所有比基准数大的数放在6的右边,比基准数小的数放在6的左边。

方法:分别从初始序列“6 1 2 7 9 3 4 5 10 8”两端开始探测,先从右往左找一个小于6的数,再从左往右找一个大于6的数,然后交换它们。可以用两个变量i和j,分别指向序列最左边和最右边。刚开始让i指向序列的最左边(即i = 1),指向数字6。让j指向序列的最右边(即j=10),指向数字8。

首先j开始出动,因为基准数是最左边的数,所以j先出动。j向左动(即j–),直到找到一个小于6的数停下来。下边i向右动(即i++),直到找到一个大于6 的数停下来,最后j停在了数字5,i停在了数字7。交换i和j所指向的元素的值。交换后的序列为“6 1 2 5 9 3 4 7 10 8”。

第一次交换结束,j继续向左动(每次必须是j先出发),j停在数字4,i停在数字9,再次交换后序列为“6 1 2 5 4 3 9 7 10 8”。第二次交换结束,继续挪动。j停在数字3。i向右与j相遇。探测结束,将基准数6与3 交换。交换后的序列为“3 1 2 5 4 6 9 7 10 8”。此时第一轮探测真正结束。以基数6为分界点,6左边的数都小于等于6,6右边的数都大于等于6 。其实i和j就是分别要找到大于和小于基准数的数,直到i和j碰头。

以6 为分界点分成两个序列,左边的序列是“3 1 2 5 4”,右边的序列是“9 7 10 8”。要分别处理这两个序列,模拟上边的方法进行处理。
对于“3 1 2 5 4”,以3为基准数,第一次交换“2 1 3 5 4”,3已经归位,再整理3左右两边的序列。

快速排序之所以快,是因为相比冒泡排序,每次交换是跳跃式的。每次排序的时候设置一个基准点,将小于等于基准点的数全都放在基准点的左边,大于等于基准点的数都放在基准点的右边。在每次交换的时候不会像冒泡排序一样只能在相邻的数之间进行交换,交换的距离就大的多。总的比较和交换次数就少了,速度提高了。在最坏的情况下,也可能是相邻的两个数进行交换,快速排序的最差时间复杂度和冒泡排序是一样的。都是O(N^2)。代码如下:`

#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);//继续处理右边的,是一个递归的过程
return;
}

int main()
{
int i ,j ;
//读入数据
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]);

getchar();getchar();
return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值