マージアルゴリズムの再帰と非再帰

非再帰的

マージソートは何ですか?

  • マージソート(MERGE-SORT)は非常に一般的なアプリケーションは、分割統治(分割統治)を使用しているアルゴリズムをソートマージの効率的な動作に基づいています。すなわち、各第1順序付けられたシーケンス、次いでセグメント間の配列を作るために命じ、複合配列は、完全に順序付けられたシーケンスを命じています。2は、ソートされたリストにマージした場合方向マージと呼ばれる、リストを命じました。安定したソートのソート方法をマージします。
/**
     * 非递归代码实现
     */
    private static <T extends Comparable> void mergeSort(T[] arr){
        for (int i = 1;i<arr.length;i*=2){
            merge(arr,i);
        }
    }
    private static<T extends Comparable> void merge(T[] arr, int gap) {
        int left1 = 0;
        int right1 = left1+gap-1;
        int left2 = right1+1;
        int right2 = left2+gap-1>arr.length-1?arr.length-1:left2+gap-1;//防止right越界
        T []brr =(T[]) new Comparable[arr.length];//brr实质就是一个中间数组,存储每次并归后的值,然后再传给arr
        //为下次归并做准备
        int j = 0;//控制brr数组下标
        //前提有两个归并段
        while (left2<arr.length){//保证了第二个归并段的存在
            while (left1<=right1 && left2<=right2){//防止越界
                if (arr[left1].compareTo(arr[left2])<0){//谁小谁进新数组
                    brr[j++] = arr[left1++];
                }else {
                    brr[j++] = arr[left2++];
                }
            }
            if (left2>right2){//说明left2已经走完了,没元素了,那就让left1到right1剩下元素直接入brr就可以了
                while (left1<=right1){
                    brr[j++] = arr[left1++];
                }
            }
            if (left1>right1){//同理
                while (left2<=right2){
                    brr[j++] = arr[left2++];
                }
            }
            //更新指针
            left1 = right2+1;
            right1 = left1+gap-1;
            left2 = right1+1;
            right2 = left2+gap-1>arr.length-1?arr.length-1:left2+gap-1;
        }
        //只剩一个归并段
        while (left1<=arr.length-1){
            brr[j++] = arr[left1++];
        }
        System.arraycopy(brr,0,arr,0,arr.length);
    }

第二に、再帰

ここに画像を挿入説明

  • 実際には、何も特別なサブステージ、1は、配列要素を打破するためにではありませんが、私たちは、どのように再帰非常に重要であり、再帰的プロセスのシーケンシングを、完了するために使用されています。私たちは、再帰的なコードの実装を見て集中しましたか?どのように使用するには?

コード実装プロセスのポイント:

  • 例えば:INT [] ARR = { 2,5,6,7,8,9,5}、 添字0~6、我々は2つの要素の開始と終了座標がARR定義することができ、その後に準じて、中間要素の座標を定義二分法は、要素分割する
    コードを:
 public static<T extends Comparable> void mergeSort2(T []arr,int left,int right,T[]brr){
        if (left<right){
            int mid = left+(right-left)/2;//中间索引
            mergeSort2(arr,left,mid,brr);//左递归
            mergeSort2(arr,mid+1,right,brr);//右递归
            //合并
            merge2(arr,left,mid,right,brr);
        }
    }

達成するために組み合わせるコード:

 //分合
    public static<T extends Comparable> void mergeSort2(T []arr,int left,int right,T[]brr){
        if (left<right){
            int mid = left+(right-left)/2;//中间索引
            mergeSort2(arr,left,mid,brr);//左递归
            mergeSort2(arr,mid+1,right,brr);//右递归
            //合并
            merge2(arr,left,mid,right,brr);
        }
    }
    /**
     * @param arr 原始数组
     * @param left 左边有序序列的初始索引
     * @param mid 中间索引
     * @param right 右边索引
     * @param brr 中转索引
     * @param <T>
     */
    public static<T extends Comparable<T>> void merge2(T[]arr,int left,int mid,int right,T[]brr){
        int i = left;//初始化 i ,左边序列初始索引
        int j = mid +1;//右边序列初始索引
        int t = 0;//控制brr数组下标
        while (i<= mid && j<=right){
            if (arr[i].compareTo(arr[j])<0){//小的入栈
                brr[t++] = arr[i++];
            }else {
                brr[t++] = arr[j++];
            }
        }
        //把剩余元素直接加到brr中
        while (i<=mid){//左边序列有剩余
            brr[t++] = arr[i++];
        }
        while (j<=right){//右边元素有剩余
            brr[t++] = arr[j++];
        }
        //把brr数组拷贝到arr
        t = 0;
        int brrLeft = left;//
        while (brrLeft<=right){
            arr[brrLeft++] = brr[t++];//0-1,2-3,0-3
        }
    }
公開された22元の記事 ウォンの賞賛2 ビュー358

おすすめ

転載: blog.csdn.net/qq_44682003/article/details/104794000