在用分而治之算法写归并排序的时候,有这么一个步骤,把问题化小,一直划到问题很esay解决的地步,
//对左边一半进行递归
mergerSort(a, low, mid, b);
//对右一边进行递归,一直递归到每一个数字就占用一个表为止
mergerSort(a, mid + 1, high, b); //进行归并
merger(a, low, mid, high, b);// 合,合,合,合到一个大串里面
我的问题是:左递归和右递归之前和之后,a数组里面的元素的位置发生了什么变化,他们不还都存储a数组里面吗?而且他们的位置也没有变化吧,只是几个指针对着数组的索引走来走去?这样理解对嘛,但如果把左递归和右递归去掉,程序排序不成了
[size=24px]看程序[/size]
package algorithm;/*    分治法——归并排序 
      二路归并排序的分治策略是: 
    (1)划分:将待排序序列r1, r2, …, rn划分为两个长度相等的子序列r1, …, rn/2和rn/2+1, …, rn; 
    (2)求解子问题:分别对这两个子序列进行排序,得到两个有序子序列; 
    (3)合并:将这两个有序子序列合并成一个有序序列。*/  
    public class Test1 {  
     static int count;
     public static void main(String[] args) {  
            int a[] = { 25,14,53,32,64,45,32,78 };// 这里对8个元素进行排序  
            int low = 0, high = 7;// 初始化low和high的值,即数组的起始和终止的坐标  
            // 辅助数组b,作为临时数组  
            int b[] = new int[a.length];  
            //输出排序前的数组  
            System.out.print("排序前:");  
            for (int i = 0; i <= high; i++) {  
                System.out.print(a[i] + " ");  
            }  
            // 归并排序  
            
            mergerSort(a, low, high, b); 
            
            //输出排序后的数组  
            System.out.print("排序后:");  
            for (int i = 0; i <= high; i++) {  
                System.out.print(a[i] + " ");  
            }  
        }  
      
        /** 
         * 分治和归并 
       */
        public static void mergerSort(int a[], int low, int high, int b[]) {  
            int mid = 0;  
            count++;
            //如果序列中只有0个或1个记录,就不用排序啦
            if (low < high) {
             mid = (high + low) / 2;// 分治位置,即将数组拆分的位置  
                //对左边一半进行递归
             mergerSort(a, low, mid, b);  //一直分,分到一个数字,占一个串
             /*
              * 没有分开之前,a[0],a[1]有一定的关系,分开之后,没关系了,零散了
              * */
                //对右边一半进行递归
             mergerSort(a, mid + 1, high, b);  //一直分,分到一个数字,占一个串
                //进行归并
             merger(a, low, mid, high, b);// 合,合,合,合到一个大串里面
            }  
           
        }  
      
        /** 
        一次归并
         */  
        public static void merger(int[] a, int low, int mid, int high, int b[]) {  
          //左子串的起始位置
            int i = low; 
            //右子串的起始位置
            int j = mid + 1;  
            int p = 0;  
            // 合并两个有序数组 子序列1 a[low..mid] 子序列2 a[mid+1..high]  
            while (i <= mid && j <= high) {  //任何一个子序列到头了,都停止循环
                b[p++] = (a[i] <= a[j]) ? a[i++] : a[j++]; //都往后面移动一位 
            }  
            // 如果子序列1没有合并完则直接复制到复制数组中去  
            while (i <= mid) {  
                b[p++] = a[i++];  
            }  
            // 如果子序列2没有合并完则直接复制到复制数组中去  
            while (j <= high) {  
                b[p++] = a[j++];  
            }  
            // 把辅助数组的元素复制到原来的数组中去  
            for (p = 0, i = low; i <= high; i++, p++) {  
                a[i] = b[p];  
            }  
        }  
    }  算法分而治之归并排序,递归

解决方案 »

  1.   

    我疑惑的是那个递归,mergerSort(a, low, mid, b);  //一直分,分到一个数字,占一个串
                 /*
                  * 没有分开之前,a[0],a[1]有一定的关系,分开之后,没关系了,零散了
                  * */
                    //对右边一半进行递归
                 mergerSort(a, mid + 1, high, b);  在递归的时候并没有对数组赋值,移位的什么操作,怎么就各自排好序了呢
      

  2.   

    那分的时候,并没有看见排序的操作啊,怎么在  merger(a, low, mid, high, b);方法执行之前,都排好 2个有序子序列了呢
      

  3.   

    递归有结束条件的 left >= right,这时候已经分到只有一个元素了。
      

  4.   


      mergerSort(a, low, mid, b);  //一直分,分到一个数字,占一个串
                 /*
                  * 没有分开之前,a[0],a[1]有一定的关系,分开之后,没关系了,零散了
                  * */
                    //对右边一半进行递归
                 mergerSort(a, mid + 1, high, b);  //一直分,分到一个数字,占一个串
                    //进行归并
                 merger(a, low, mid, high, b);// 合,合,合,合到一个大串里面
    这里面的3个递归方法,什么时候第一个递归结束,什么时候第二个递归结束,?