归并排序(MergeSort)递归与非递归的实现

主要关注一下非递归版本,其实就是模拟了从长度为1的子段,不断长度翻倍,一直到最后为全长的过程。】

归并的思想是: 
1.将原数组首先进行两个元素为一组的排序,然后合并为四个一组,八个一组,直至合并整个数组; 
2.合并两个子数组的时候,需要借助一个临时数组,用来存放当前的归并后的两个数组; 
3.将临时数组复制回原数组对应的位置。

代码中最后将tmp数组中的值写回原数组中。(注意归并为稳定的排序方法!)

package mergesort;

import java.util.Arrays;
import java.util.Random;
import java.util.Scanner;
//归并排序的非递归算法
public class MergeSort{
    public static void main(String args[]){
        MergeSort mer = new MergeSort();
        int[] array = mer.getArray();
        System.out.println("OriginalArray:" + Arrays.toString(array));
        mer.mergeSort(array);
        System.out.println("SortedArray:" + Arrays.toString(array));
    }
    public int[] getArray(){
        Scanner cin = new Scanner(System.in);
        System.out.print("Input the length of Array:");
        int length = cin.nextInt();
        int[] arr = new int[length];
        Random r = new Random();
        for(int i = 0; i < length; i++){
            arr[i] = r.nextInt(100);
        }
        cin.close();
        return arr;
    }
//////////开始/////////////////////////

    public void mergeSort(int[] a){
        int len = 1;         //子段长度从1开始
        while(len < a.length){
            for(int i = 0; i < a.length; i += 2*len){  //每2*len段执行一次小归并
                merge(a, i, len);
            }
            len *= 2;
        }
    }

    public void merge(int[] a, int i, int len){
        int start = i;         //左半段开始
        int len_i = i + len;   //前半部分的结束标记位,左半段长度len
        int j = i + len;       //右半段开始
        int len_j = j +len;    //后半部分的结束标记位,右半段长度len
        int[] temp = new int[2*len];   //tmp数组长度2*len
        int count = 0;
        while(i < len_i && j < len_j && j < a.length){  
            if(a[i] <= a[j]){
                temp[count++] = a[i++];
            }
            else{
                temp[count++] = a[j++];
            }
        }
        while(i < len_i && i < a.length){//将各段剩余部分写入。注意:这里i也有可能超过数组长度
            temp[count++] = a[i++];
        }
        while(j < len_j && j < a.length){
            temp[count++] = a[j++];
        }
        count = 0;         //将tmp中排序结果写回原数组中
        while(start < j && start < a.length){
            a[start++] = temp[count++];
        }
    }
}

递归算法的实现代码如下:

public class MergeSort {
    public static void mergeSort(int[] data,int left,int right){ //left,right均为数字元素下标
        if(left<right){
            int half=(left+right)/2;
            mergeSort(data,left,half);
            mergeSort(data,half+1,right);
            merge(data,left,right);
        }
    }
    public static void merge(int []a,int l,int h){
        int mid=(l+h)/2;
        int i=l;
        int j=mid+1;
        int count=0;
        int temp[]=new int[h-l+1];
        while(i<=mid&&j<=h){
            if(a[i]<a[j]){
                temp[count++]=a[i++];
            }else{
                temp[count++]=a[j++];
            }        
        }
        while(i<=mid){
            temp[count++]=a[i++];
        }
        while(j<=h){
            temp[count++]=a[j++];
        }
        count=0;
        while(l<=h){
            a[l++]=temp[count++];
        }
    }
   
}

归并排序的时间复杂度为O(n*log2n),空间复杂度为O(n)

归并排序是一种稳定的排序方法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章