代码改变世界

归并排序

2012-08-05 19:41  coodoing  阅读(405)  评论(0编辑  收藏  举报

1、算法介绍

     归并排序(Merging Sort)是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的;然后再把有序子序列合并为整体有序序列。归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。 将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。       

2、算法动画演示

3、算法步骤

1、申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列。

2、设定两个指针,最初位置分别为两个已经排序序列的起始位置。

3、比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置。

4、重复步骤3直到某一指针达到序列尾。

5、将另一序列剩下的所有元素直接复制到合并序列尾。

4、算法代码

   1: // 归并排序算法 
   2: public class MergingSort {
   3:  
   4:     public static void mergeSort(int[] arr) {
   5:         int[] temp = new int[arr.length];//临时数组  
   6:         mSort(arr, temp, 0, arr.length - 1);
   7:     }
   8:  
   9:     private static void mSort(int[] arr, int[] temp, int low, int high) {
  10:         if (low >= high)
  11:             return;
  12:         else {
  13:             int middle = (low + high) / 2;
  14:             // 对左边数组进行递归  
  15:             mSort(arr, temp, low, middle);
  16:             // 对右边数组进行递归
  17:             mSort(arr, temp, middle + 1, high);
  18:             // 合并 
  19:             merge(arr, temp, low, middle, high);
  20:         }
  21:     }
  22:  
  23:     // 将有序数组ARR[low...middle]和ARR[middle+1...high]归并为有序的TEMP[low...high] 
  24:     private static void merge(int[] arr, int[] temp, int low, int middle,
  25:             int high) {
  26:         // 左数组第一个元素的索引  
  27:         int leftIndex = low;
  28:         // 右数组第一个元素索引  
  29:         int rightIndex = middle + 1;
  30:         // tmpIndex 记录临时数组的索引  
  31:         int tmpIndex = low;
  32:  
  33:         while (low <= middle && rightIndex <= high) {
  34:             // 从两个数组中取出最小的放入临时数组  
  35:             if (arr[low] <= arr[rightIndex]) {
  36:                 temp[tmpIndex++] = arr[low++];
  37:             } else {
  38:                 temp[tmpIndex++] = arr[rightIndex++];
  39:             }
  40:         }
  41:         // 剩余部分依次放入临时数组(实际上两个while只会执行其中一个)  
  42:         while (rightIndex <= high) {
  43:             temp[tmpIndex++] = arr[rightIndex++];
  44:         }
  45:         while (low <= middle) {
  46:             temp[tmpIndex++] = arr[low++];
  47:         }
  48:         
  49:         // 将临时数组中的内容拷贝回原数组中: (原low-right范围的内容被复制回原数组) 
  50:         while (leftIndex <= high) {
  51:             arr[leftIndex] = temp[leftIndex++];
  52:         }
  53:     }
  54:  
  55:     private static void print(int[] arr) {
  56:         for (int i = 0; i < arr.length; i++) {
  57:             System.out.print(arr[i] + "\t");
  58:         }
  59:         System.out.println();
  60:     }
  61:  
  62:     public static void main(String[] args) {
  63:         int arr[] = { 2, 568, 34, 46, 9, 23, 89, 43, 572, 684, 783, 543 };
  64:         System.out.println("归并排序前:");
  65:         print(arr);
  66:         mergeSort(arr);
  67:         System.out.println("归并排序后:");
  68:         print(arr);
  69:     }
  70: }

5、算法时间复杂度

平均时间复杂度:O(nlgn)

最坏情况下时间复杂度为:O(nlgn)

归并排序算法稳定;数组需要O(n)的额外空间,链表需要O(log(n))的额外空间,时间复杂度为O(nlog(n))。