4 归并排序

Wu Jun 2019-05-24 21:12:59
01 数据结构与算法 > 数据结构 > 04 排序

归并排序 (Merging Sort) 就是利用归并的思想实现的排序方法。

假设初始序列含有 n 个记录 , 则可以看成是 n 个有序的子序列,每个子序列的长度为 1 ,然后两两归并,得到 [n/2] ([x]表示不小于 x 的最小整数)个长度为 2 或 1 的有序子序列;再两两归并,……,如此重复,直至得到一个长度为 n 的有序序列为止,这种排序方法称为 2 路归并排序。

思路:将一个数组分成两部分(A,B)。
A实现左边有序,再实现右边有序,然后进行合并,最后实现A这一个大部分实现有序。
然后B同样进行以上同样的操作,最后B这一大部分实现有序,最后,AB合并,实现整体有序。 同样,在实现A的有序也是自底向上进行合并的。

public static void mergeSort(int array[],int first,int end,int temp[]){
    int mid = (first+end)/2;
    if(first < end){
        //左边有序
        mergeSort(array,first,mid,temp);
        //右边有序
        mergeSort(array,mid+1,end,temp);
        //进行合并
        merge(array,first,mid,end,temp);
    }
}

public static void merge(int array[],int first,int mid,int end,int temp[]){
    int index1=first,index2=mid+1;
    int k=first;
    for (int i = first; i < end+1; i++) {
        temp[i]=array[i];
    }
    while(true){
        if(index1==mid+1 && index2==end+1){
            break;
        }else{
            if(index1==mid+1){
                for(int n=index2;n<=end;n++){
                    array[k++]=temp[n];
                }
                break;
            }else if(index2==end+1){
                for(int n=index1;n<=mid;n++){
                    array[k++]=temp[n];
                }
                break;
            }else{
                if(temp[index1]<temp[index2]){
                    array[k++]=temp[index1++];
                }else{
                    array[k++]=temp[index2++];
                }
            }
        }
    }
}

复杂度分析

O(nlogn)

归并排序是一种比较占用内存,但却效率高且稳定的算法。

非递归实现归并排序

/* 对顺序表L作归并非递归排序 */
void MergeSort2(SqList *L)
{
  int* TR = (int *)malloc(L->length * sizeof(int));  /* 申请额外空间 */
  int k = 1;
  while (k < L->length)
  {
    MergePass(L->r, TR, k, L->length);
    k = 2 * k;  /* 子序列长度加倍 */
    MergePass(TR, L->r, k, L->length);
    k = 2 * k;  /* 子序列长度加倍 */
  }
}
/* 将SR[]中相邻长度为s的子序列两两归并到TR[] */
void MergePass(int SR[], int TR[], int s, int t)
{
  int i = 1;
  int j;
  while (i <= n - 2 * s + 1)
  {
    Merge(SR, TR, i, i + s - 1, i + 2 * s - 1); /* 两两归并 */
    i = i + 2 * s;
  }
  if (i < n - s + 1) /* 归并最后两个序列 */
    Merge(SR, TR, i, i + s - 1, n);
  else               /* 若最后只剩下单个子序列 */
    for ( j = i; j <= n; j++)
      TR[j] = SR[j];
}