10.4 选择排序

    Selection Sort的基本思想是:每一趟在n-i+1(i=1, ... ,n-1)个记录中选取最小的记录作为有序序列中第i个记录。

   1:  Simple Selection Sort
   2:  void SelectSort (SqList &L)
   3:      for (i = 1; i < L.length; ++i)
   4:      {
   5:          j = SelectMinKey(L, i);
   6:          if (i != j) Swap(L.r[i], L.r[j]);
   7:      }
   8:  }
 
    能否改进?选择排序主要进行的是关键字间的比较,考虑如何减少比较?在n个关键字中选出最小值,至少需要n-1 次比较,继续在剩下的n-1 个关键字中选择次小值可以考虑如何利用上一次比较所得的信息。
    实例:锦标赛,8名运动员决出前3名至多需要11场比赛,而不是7+6+5=18 场比赛(前提,甲胜已,已胜丙,则甲一定胜丙)
    树形选择排序(Tree Selection Sort),又称锦标赛排序(Tournament Sort)
    首先,选择最小关键字,对n个关键字两两比较,在其中n/2 个较小的之间再两两比较,如此重复,选出最小关键字。
    然后,选择次小关键字,将以前最小关键字所在的叶子结点值写改为MAX,比较,修改,的次小关键字。
    最后,重复,得排序。
    Tree Selection Sort 时间复杂度O(nlogn),但是有所需存储空间较多,和“最大值”进行多余的比较等缺点,于是就有了堆排序(1964 J.willioms)
    堆的定义 如下:n个元素的序列{k1, ... , kn}当且仅当满足如下关系时,称为堆。
            ki <= k2i            ki >= k2i
            ki <= k2i+1   或    ki >= k2i+1

    输出堆顶元素后,使剩余的n-1 个元素的序列重又建成一个堆,则得次小(大)元素,如此反复,得到一个有序序列,这个过程称之为堆排序。
    实现堆排序需要解决的两个问题:1,如何由一个无序序列建成一个堆?2,如何在输出堆顶元素之后调整剩余元素成为一个新的堆。可以考虑先解决第二个问题,而从一个无序序列建堆的过程就是一个反复筛选的过程,!!!若将一个序列看成一个完全二叉树,则最后一个非终端节点是第n/2个元素,由此,筛选从第n/2个元素开始。

算法描述如下:

   1:  typedef SqList HeapType //堆采用顺序表存储表示
   2:  void HeapAdjust(HeapType &H, int s, int m)
   3:  {
   4:      //已知H.r[s...m]中记录的关键字除H.r[s].key外均满足堆的定义,本函数调整H.r[s]的关键字,
   5:      //使H.r[s...m]成为一个大顶堆(对其记录的关键字而言)
   6:      rc = H.r[s];
   7:      for (j = 2 * s; j <= m; j *= 2)
   8:      {
   9:      //沿key较大的孩子结点向下筛选
  10:          if (j < m && LT(H.r[j].key, H.r[j+1].key)) ++j; //j为key较大的记录的下标
  11:          if (!LT(rc.key, H.r[j].key)) break;                //rc应插入在位置s上
  12:          H.r[s] = H.r[j]; s = j;
  13:      }
  14:      H.r[s] = rc;                                        //插入
  15:  }
  16:  void HeapSort(HeapType &H)                              
  17:  {
  18:      for (i = H.length/2; i > 0; --i)                      
  19:          HeapAdjust(H, i, H.length);
  20:      for (i = H.length; i > 1; --i)
  21:      {
  22:          Swap(H.r[1], H.r[i]);
  23:          HeapAdjust(H, 1, i - 1);
  24:      }
  25:  }

    堆排序方法对记录较少的文件不值得提倡,因为其运行时间主要耗费在建立初始堆时进行的反复筛选上,其时间复杂度最坏为O(nlogn),排序时仅需一个记录大小供交换用的辅助空间。

具体实例:

   1:  #include <stdio.h>
   2:  typedef int InfoType;
   3:   
   4:  #define EQ(a, b) ((a) == (b))
   5:  #define LT(a, b) ((a) < (b))
   6:  #define LQ(a, b) ((a) <= (b)) 
   7:   
   8:  #define MAXSIZE 20
   9:  typedef int KeyType;
  10:  typedef struct
  11:  {
  12:      KeyType key;
  13:      InfoType otherinfo;
  14:  }RedType;
  15:  typedef struct
  16:  {
  17:      RedType r[MAXSIZE+1]; //r[0]闲置或作哨兵
  18:      int length; 
  19:  }SqList;
  20:   
  21:  typedef SqList HeapType;
  22:  void HeapAdjust (HeapType *H, int s, int m)
  23:  {
  24:      RedType rc;
  25:      int j;
  26:      rc = (*H).r[s];
  27:      for (j = 2*s; j <= m; j *= 2)
  28:      {
  29:          if (j < m && LT((*H).r[j].key, (*H).r[j+1].key)) ++j;
  30:          if (!LT(rc.key, (*H).r[j].key))
  31:              break;
  32:          (*H).r[s] = (*H).r[j];
  33:          s = j;
  34:      }
  35:      (*H).r[s] = rc;
  36:  }
  37:  void HeapSort(HeapType *H)
  38:  {
  39:      RedType t;
  40:      int i;
  41:      for (i = (*H).length/2; i > 0; --i)
  42:          HeapAdjust(H, i, (*H).length);
  43:      for (i = (*H).length; i > 1; --i)
  44:      {
  45:          t = (*H).r[1];
  46:          (*H).r[1] = (*H).r[i];
  47:          (*H).r[i] = t;
  48:          HeapAdjust(H, 1, i-1); 
  49:      }
  50:  }
  51:  void print(HeapType H)
  52:  {
  53:      int i;
  54:      for(i = 1; i <= H.length; ++i)
  55:          printf("(%d, %d)", H.r[i].key, H.r[i].otherinfo);
  56:      printf("\n"); 
  57:  }
  58:  #define N 8
  59:  int main()
  60:  {
  61:      RedType d[N]={{49,1},{38,2},{65,3},{97,4},{76,5},{13,6},{27,7},{49,8}};
  62:      HeapType h;
  63:      int i;
  64:      for (i = 0; i < N; ++i)
  65:          h.r[i+1] = d[i];
  66:      h.length = N;
  67:      printf("排序前:\n");
  68:      print(h);
  69:      HeapSort(&h);
  70:      printf("排序后:\n");
  71:      print(h);
  72:      return 0;
  73:  }
posted @ 2013-09-30 18:24  ningjing@liunian  阅读(199)  评论(0)    收藏  举报