【编程珠玑】学习笔记4——排序

一、插入排序

基本思想:对于每一个待排数组,从第二个元素开始,跟它之前的元素比较,找到合适的位置,将对应元素后移后插入到该位置。

例如待排数组 A=[6,2,4,1,5,9]。

第一次循环:查找元素2应该在的位置,与前面元素(只有6)比较,所以将6移到2的位置,然后将2移到6的位置;

第二次循环:查找元素4应该在的位置,与前面元素(2、6)比较,小于6,因此将6往后移动,再与2比较,不需要移动,故插入到6所在的位置;

...

以此类推,知道最后一个元素找到合适的位置。

sort1:

for i = [1,n)

      for ( j = i; j>0 && A[j-1]>A[j]; j--)

            swap(A[j-1]. A[j])


结合学习笔记3性能篇可知,可以把代码改成如下形式:

sort2:

for i = [1,n)

      for ( j = i; j>0&&A[j-1]>A[j]; j--)

             t = A[j]; A[j] = A[j-1]; A[j-1] = t;

即将swap函数写成内联的形式,可以提高运行速度。

通过上面一步的改进又可以发现,不用每次交换都引入一个临时变量 t ,于是又可以得到下面这个更加优化的版本:

sort3:

for i = [1, n)

       t = A[i];

       for ( j = i ; j>0&&A[j-1]>A[j]; j--)

               A[j] = A[j-1];

       A[j-1] = t;

显然,从执行效率上来看,sort3 > sort2 > sort1。


二、快速排序

基本思想:基于分治法,排序数组时,将数组划分成为两个较小的部分,然后递归排序他们。

例如现有一个具有8个元素的数组:X = [55,44, 59,26,53,58,97,93]

首先以第一个元素55为中间元素,将数组划分为  [44  26  53  55  59  58  97  93]

然后分别递归子数组[44  26  53]和[59  58  97  93]

...

qsort1:

void  qsort1(l, u)

         bool  go_on = true;

         if l>=u

              return; //只有一个元素,无需排序

         t=x[l];

         i = l+1;

         j = u;

         while(go_on)

                   while(i<=u && x[i]<t)

                            i++;

                   while(x[j]>t)

                           j--;

                   if(i>j)

                          go_on = false;

                   else

                         swap(x[i],x[j]);

         swap(x[l],x[j]);

         qsort1(l,j-1);

         qsort1(j+1,u);

双向扫描,当然如果不想每次都以第一个元素为值,可以生成一个(l, u)之间的随机数作为r,以x[r]作为中间值。

书上还引入了一个中间变量cutoff,相应地在程序中将 返回条件 l>=u 改为 u-l>cutoff ,虽然程序结束时数组并不是有序的,但是被组合成一小块一小块随机顺序的值。


扩展:编写程序,让该程序在O(n)的时间内从数组x[0,1,...,n-1]中找出第k个最小的元素。

void selectk(l,u,k)

        bool go_on = true;

        if l>=u

             return;

        t = x[l]; i = l+1; j = u;

        while(go_on)

                 while(i<=u && x[i]<t)

                          i++;

                 while(x[j]>t)

                          j--;

                 if(i>j)

                         go_on = false;

                 else

                         swap(x[i],x[j]);

        swap(x[l],x[j]);

        if( j > k )

               selectk(l,j-1,k)

        else if(j<k)

               selectk(j+1,u,k) 

此算法在快排的基础上添加判断得到。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值