归并排序

本文针对的读者:了解递归,期望加深对归并排序的理解或者第一次接触归并排序

 

归并排序,前一篇我们讲了插入排序,插入排序之所以叫做插入排序,是因为其复杂度最高的地方在插入的部分,为什么复杂度高?前面一篇已经比较详细的阐述了,因为插入出想的情况有三种,而人脑将三种情况统一在一块代码上,就显得有点困难了。如果是统一在一个概念之下会比较简单。那么这里的归并排序,所谓“归并”,“归”是递归,也就是说这个算法是一个递归的算法,大部分递归的算法都相对来说有容易想的优点,“并”是该算法的核心,也就是说复杂度就在这里了,如何将两个已排好的序列合并成一个排好的序列?这个比较简单,但是在实际编程的时候需要一个小技巧。

下面直接看一下测试代码:

View Code
#include <cstdio>
#include <cstdlib>
/**
 * merge a[p..q] and a[q+1..r]
 */
#define MAX  100
void merge(int a[],int p,int q,int r){
  int n1 = q - p + 1;
  int n2 = r - q;

  int *L = (int *)calloc(n1+1, sizeof(int));
  int *R = (int *)calloc(n2+1, sizeof(int));
  
  //copy data to new space
  int i, j;
  for(i=0;i<n1;i++)
    L[i] = a[p+i];
  for(j=0;j<n2;++j)
    R[j] = a[q+1+j];
  
  //they are flags
  L[n1] = MAX;
  R[n2] = MAX;

  //here is the key process of merge
  i = j = 0;
  int k;
  for(k=p;k<=r;++k){
    if(L[i]<=R[j]){
      a[k] = L[i];
      i++;
    }
    else{
      a[k] = R[j];
      j++;
    }
  }
  
  free(L);
  free(R);
}


void MergeSort(int a[],int p,int r){
  if(p<r){
    int q = (p+r)/2;
    MergeSort(a, p, q);
    MergeSort(a, q+1, r);
    merge(a, p, q, r);
  }
}

int main(){
  
  int a[] = {3, 4, 5, 2, 9 ,1, 7, 6, 8};
  int len = sizeof(a)/sizeof(int);
 
  MergeSort(a, 0, len - 1);
  
  int i;
  for(i=0;i<len;++i){
    printf("%d ", a[i]);
  }
  printf("\n");
  return 0;
}

 

MergeSort这个函数比较简单,核心在于merge这个函数,merge这个函数里,使用了calloc进行动态内存空间申请,

申请的空间用于存储两个待合并的有序数组,并且在每个数组的末尾放置一个MAX,这里是一个小技巧,构造这样一个

MAX有利于循环继续,写出比较优雅的代码。然后就是不断的取两个数组头中最小的,当取满所有的元素个数即完成任务。

 

以上论述,有不妥之处,欢迎指正:)

posted on 2012-05-03 10:01  涅槃火凤  阅读(248)  评论(0编辑  收藏  举报

导航