归并排序

归并排序的核心思想是将两个已经排序的序列合并成一个序列,那如何得到两个已经排序的序列呢?我们知道, 如果一个序列只有一个元素,那该序列是已经排序的,这样我们就可以利用分治的思想,将未排序的序列划分成更小的序列,只到我们可以很方便的对小序列进行排序(比如划分到序列只有一个元素, 或者序列很小可以方便的使用其它排序算法进行排序),然后再将小序列逐次合并,得到最后的排序结果。

实现:

   1: /*
   2:  * @brief 将两个已排序的序列 in[l...m]和in[m+1...r]合并,放入out中
   3:  * num 为计算逆序对所用 
   4:  */
   5: int num = 0;
   6: void merge(int in[], int out[], int l, int m, int r)
   7: {
   8:     int i = l;
   9:     int k  = m + 1;
  10:     
  11:     while (l <= m && k <= r) {
  12:         if (in[l] <= in[k]) {
  13:             out[i++] = in[l++];
  14:         } else {
  15:             out[i++] = in[k++];
  16:             /* 因为此时in[l...m]已经排序,如果in[l] 与 in[k] 逆序,
  17:                 则in[l+1], in[l+2]...in[m] 都与in[k]逆序, 共 m-l+1 对*/
  18:             num += m - l + 1; /* calculate the inversion number */
  19:         }
  20:     }
  21:     while (l <= m) {
  22:         out[i++] = in[l++];
  23:     }
  24:     while (k <= r) {
  25:         out[i++] = in[k++];
  26:     }
  27: }
  28:  
  29: /*
  30:  * @brief 递归将序列划分为只有一个元素的子序列, 然后逐次对子序列进行合并
  31:  */
  32: void m_sort(int in[], int out[], int l, int r)
  33: {
  34:     /* 仅有一个元素, 已排序, 递归结束 */
  35:     if (l >= r) {
  36:         return;
  37:     }
  38:     
  39:     /* 计算 l 和 r 的中间值, 防止溢出 */
  40:     int m = (l & r) + ((l ^ r) >> 1);
  41:     /* note that in and out are swapped */
  42:     m_sort(out, in, l, m);
  43:     m_sort(out, in, m + 1, r);
  44:  
  45:     merge(in, out, l, m, r);
  46: }
  47:  
  48: /*
  49:  * @brief merge sort
  50:  * 统一申请空间, 避免反复申请释放
  51:  */
  52: int merge_sort(int a[], int n)
  53: {
  54:     int *b = (int *)malloc(n * sizeof(int));
  55:     if (b) {
  56:         memcpy(b, a, n * sizeof(int));
  57:         m_sort(b, a, 0, n - 1);
  58:         free(b);
  59:         return 0;
  60:     }
  61:     
  62:     return -1;
  63: }
posted @ 2012-06-01 08:26  Newerth  阅读(234)  评论(0编辑  收藏  举报