Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java迭代合并排序运行时_Java_Arrays_Sorting_Merge_Mergesort - Fatal编程技术网

Java迭代合并排序运行时

Java迭代合并排序运行时,java,arrays,sorting,merge,mergesort,Java,Arrays,Sorting,Merge,Mergesort,我目前正在为学校做一个项目,要求我为不同的排序算法编写代码。最困难的部分是在给定长度为2^N的输入数组的情况下编写merge sort的迭代版本。我使用了一个名为merge的必需助手方法来帮助迭代合并 我的结构如下。给定一个2^N的数组(让我们使用16的数组大小来解释我的方法),我遍历数组,查看每个2个整数,如果一个大于另一个,则使用merge()进行交换。此过程将在长度为16的数组中发生8次。然后,我将遍历数组,查看每4个整数,4次。我将使用我的合并方法来合并每组4中的两个有序对。然后,我会看

我目前正在为学校做一个项目,要求我为不同的排序算法编写代码。最困难的部分是在给定长度为2^N的输入数组的情况下编写merge sort的迭代版本。我使用了一个名为merge的必需助手方法来帮助迭代合并

我的结构如下。给定一个2^N的数组(让我们使用16的数组大小来解释我的方法),我遍历数组,查看每个2个整数,如果一个大于另一个,则使用merge()进行交换。此过程将在长度为16的数组中发生8次。然后,我将遍历数组,查看每4个整数,4次。我将使用我的合并方法来合并每组4中的两个有序对。然后,我会看一个由8个整数组成的块…以此类推。我的代码发布在这里:

public static void MergeSortNonRec(long[] a) {
    //======================
    //FILL IN YOUR CODE HERE
    //======================    
    /*
    System.out.print("Our array is: ");
    printArray(a);
    System.out.println('\n');
    */
    int alength = a.length;
    int counter = 2;
    //the counter will iterate through levels 2n - 2 4 8 16 32 etc.
    int pointtracker = 0;
    //the point tracker will keep track of the position in the array
    while (counter <= alength) {
        long [] aux = new long [alength];
        int low = pointtracker;
        int high = pointtracker + counter - 1;
        int mid = (low + high)/2;

        merge(a, aux, low, mid, high);

        if (high < alength - 1) {
            pointtracker += counter; 
            //move to the next block
        }
        else {
            //if our high point is at the end of the array
            counter *= 2;
            pointtracker = 0;
            //start over at a[0], with a doubled counter
        }
    }
    /*
    System.out.print("Final array is: ");
    printArray(a);
    System.out.println('\n');
    */
}//MergeSortNonRec()
publicstaticvoidmergesortnonrec(长[]a){
//======================
//在这里填写您的代码
//======================    
/*
System.out.print(“我们的数组是:”);
打印阵列(a);
System.out.println('\n');
*/
int alength=a.长度;
int计数器=2;
//计数器将遍历级别2n-2 4 8 16 32等。
int pointtracker=0;
//点跟踪器将跟踪阵列中的位置
while(柜台)
我可以做些什么来减少迭代合并排序的时间

Wiki有一个迭代(自底向上)合并排序的简化示例:

为了减少时间,只需一次性分配aux[]数组,不要在每次合并过程中复制数据,而是在每次合并过程中交换对数组的引用

        long [] t = a;      // swap references
        a = aux;
        aux = t;
如果数组的大小是2的奇数次幂,则需要将数组复制一次或就地交换,而不是执行第一次合并过程

迭代合并排序应该比递归合并排序运行得更快

假设这两个函数的版本都经过合理优化,迭代合并排序通常会更快,但相对差异会随着数组大小的增加而减小,因为大部分时间将花费在merge()函数中,该函数对于迭代合并排序和递归合并排序都是相同的

这是一个折衷方案。递归版本将把length-2或2*length-2对索引推送到堆栈或从堆栈中弹出,而迭代则会动态生成索引(可以保存在寄存器中)。在更深层次的递归过程中,递归版本似乎对缓存更友好,因为它在数组的一部分上运行,而迭代版本在每次传递时总是在整个数组上运行,但我从未见过这样的情况,即递归合并排序能带来更好的整体性能。MoPC上的st缓存是4路或更多路集关联的,因此两行用于输入,一行用于合并过程中的输出。在我的测试中,多线程迭代合并排序比单线程迭代合并排序快得多,因此我测试的系统上的合并排序没有内存带宽限制

下面是一个经过优化的迭代(自底向上)合并排序示例以及一个测试程序:

package jsortbu;
import java.util.Random;

public class jsortbu {
    static void MergeSort(int[] a)          // entry function
    {
        if(a.length < 2)                    // if size < 2 return
            return;
        int[] b = new int[a.length];
        BottomUpMergeSort(a, b);
    }

    static void BottomUpMergeSort(int[] a, int[] b)
    {
    int n = a.length;
    int s = 1;                              // run size 
        if(1 == (GetPassCount(n)&1)){       // if odd number of passes
            for(s = 1; s < n; s += 2)       // swap in place for 1st pass
                if(a[s] < a[s-1]){
                    int t = a[s];
                    a[s] = a[s-1];
                    a[s-1] = t;
                }
            s = 2;
        }
        while(s < n){                       // while not done
            int ee = 0;                     // reset end index
            while(ee < n){                  // merge pairs of runs
                int ll = ee;                // ll = start of left  run
                int rr = ll+s;              // rr = start of right run
                if(rr >= n){                // if only left run
                    do                      //   copy it
                        b[ll] = a[ll];
                    while(++ll < n);
                    break;                  //   end of pass
                }
                ee = rr+s;                  // ee = end of right run
                if(ee > n)
                    ee = n;
                Merge(a, b, ll, rr, ee);
            }
            {                               // swap references
                int[] t = a;
                a = b;
                b = t;
            }
            s <<= 1;                        // double the run size
        }
    }

    static void Merge(int[] a, int[] b, int ll, int rr, int ee) {
        int o = ll;                         // b[]       index
        int l = ll;                         // a[] left  index
        int r = rr;                         // a[] right index
        while(true){                        // merge data
            if(a[l] <= a[r]){               // if a[l] <= a[r]
                b[o++] = a[l++];            //   copy a[l]
                if(l < rr)                  //   if not end of left run
                    continue;               //     continue (back to while)
                do                          //   else copy rest of right run
                    b[o++] = a[r++];
                while(r < ee);
                break;                      //     and return
            } else {                        // else a[l] > a[r]
                b[o++] = a[r++];            //   copy a[r]
                if(r < ee)                  //   if not end of right run
                    continue;               //     continue (back to while)
                do                          //   else copy rest of left run
                    b[o++] = a[l++];
                while(l < rr);
                break;                      //     and return
            }
        }
    }

    static int GetPassCount(int n)          // return # passes
    {
        int i = 0;
        for(int s = 1; s < n; s <<= 1)
            i += 1;
        return(i);
    }

    public static void main(String[] args) {
        int[] a = new int[10000000];
        Random r = new Random();
        for(int i = 0; i < a.length; i++)
            a[i] = r.nextInt();
        long bgn, end;
        bgn = System.currentTimeMillis();
        MergeSort(a);
        end = System.currentTimeMillis();
        for(int i = 1; i < a.length; i++){
            if(a[i-1] > a[i]){
                System.out.println("failed");
                break;
            }
        }
        System.out.println("milliseconds " + (end-bgn));
    }
}
jsortbu包;
导入java.util.Random;
公共类jsortbu{
静态void MergeSort(int[]a)//输入函数
{
if(a.length<2)//if size<2返回
返回;
int[]b=新的int[a.长度];
BottomUpMergeSort(a,b);
}
静态void BottomUpMergeSort(int[]a,int[]b)
{
int n=a.长度;
int s=1;//运行大小
if(1==(GetPassCount(n)&1)){//if奇数个过程
对于(s=1;s=n){//如果只剩下左运行
复制它吗
b[ll]=a[ll];
而(++lln)
ee=n;
合并(a、b、ll、rr、ee);
}
{//交换引用
int[]t=a;
a=b;
b=t;
}

s我能够解决我的问题-只是必须将long[]aux移到while循环之外,因为它基本上是一个空数组,只是被merge()改变了方法,但不需要在每次传递时都实例化。@TVK-我用一个稍微优化的合并排序版本更新了我的答案。在我的系统(英特尔3770K 3.5ghz,Win 7 Pro 64位,NetBeans 8.1)上对1000万个整数进行排序大约需要1.1秒。
        long [] t = a;      // swap references
        a = aux;
        aux = t;
package jsortbu;
import java.util.Random;

public class jsortbu {
    static void MergeSort(int[] a)          // entry function
    {
        if(a.length < 2)                    // if size < 2 return
            return;
        int[] b = new int[a.length];
        BottomUpMergeSort(a, b);
    }

    static void BottomUpMergeSort(int[] a, int[] b)
    {
    int n = a.length;
    int s = 1;                              // run size 
        if(1 == (GetPassCount(n)&1)){       // if odd number of passes
            for(s = 1; s < n; s += 2)       // swap in place for 1st pass
                if(a[s] < a[s-1]){
                    int t = a[s];
                    a[s] = a[s-1];
                    a[s-1] = t;
                }
            s = 2;
        }
        while(s < n){                       // while not done
            int ee = 0;                     // reset end index
            while(ee < n){                  // merge pairs of runs
                int ll = ee;                // ll = start of left  run
                int rr = ll+s;              // rr = start of right run
                if(rr >= n){                // if only left run
                    do                      //   copy it
                        b[ll] = a[ll];
                    while(++ll < n);
                    break;                  //   end of pass
                }
                ee = rr+s;                  // ee = end of right run
                if(ee > n)
                    ee = n;
                Merge(a, b, ll, rr, ee);
            }
            {                               // swap references
                int[] t = a;
                a = b;
                b = t;
            }
            s <<= 1;                        // double the run size
        }
    }

    static void Merge(int[] a, int[] b, int ll, int rr, int ee) {
        int o = ll;                         // b[]       index
        int l = ll;                         // a[] left  index
        int r = rr;                         // a[] right index
        while(true){                        // merge data
            if(a[l] <= a[r]){               // if a[l] <= a[r]
                b[o++] = a[l++];            //   copy a[l]
                if(l < rr)                  //   if not end of left run
                    continue;               //     continue (back to while)
                do                          //   else copy rest of right run
                    b[o++] = a[r++];
                while(r < ee);
                break;                      //     and return
            } else {                        // else a[l] > a[r]
                b[o++] = a[r++];            //   copy a[r]
                if(r < ee)                  //   if not end of right run
                    continue;               //     continue (back to while)
                do                          //   else copy rest of left run
                    b[o++] = a[l++];
                while(l < rr);
                break;                      //     and return
            }
        }
    }

    static int GetPassCount(int n)          // return # passes
    {
        int i = 0;
        for(int s = 1; s < n; s <<= 1)
            i += 1;
        return(i);
    }

    public static void main(String[] args) {
        int[] a = new int[10000000];
        Random r = new Random();
        for(int i = 0; i < a.length; i++)
            a[i] = r.nextInt();
        long bgn, end;
        bgn = System.currentTimeMillis();
        MergeSort(a);
        end = System.currentTimeMillis();
        for(int i = 1; i < a.length; i++){
            if(a[i-1] > a[i]){
                System.out.println("failed");
                break;
            }
        }
        System.out.println("milliseconds " + (end-bgn));
    }
}