Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.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_Performance - Fatal编程技术网

Java 按单独的索引数组对数组进行排序的最快方法

Java 按单独的索引数组对数组进行排序的最快方法,java,arrays,sorting,performance,Java,Arrays,Sorting,Performance,假设我有以下设置: int[] vectorUsedForSorting = new int[] { 1,0,2,6,3,4,5 } int[] vectorToBeSorted = new int[] {1,2,3,4,5,6,7} 使用vectorUsedForSorting对vectorToBeSorted进行排序的最有效/最快速的方法是什么?例如,我希望vectorToBeSorted[0]变成vectorToBeSorted[1],因为vectorUsedForSorting的第一个

假设我有以下设置:

int[] vectorUsedForSorting = new int[] { 1,0,2,6,3,4,5 }
int[] vectorToBeSorted = new int[] {1,2,3,4,5,6,7}
使用
vectorUsedForSorting
vectorToBeSorted
进行排序的最有效/最快速的方法是什么?例如,我希望
vectorToBeSorted[0]
变成
vectorToBeSorted[1]
,因为
vectorUsedForSorting
的第一个元素是
1
(即
vectorToBeSorted[0]
应该变成
`vectorToBeSorted[vectorUsedForSorting[0]]
,等等)

我的目标是在排序算法完成后,将
矢量对象排序
设置为
[2,1,3,5,6,7,4]

我希望能很快取得成就。请注意,计算复杂性应该是主要关注点,因为我将对大小为1000000或更大的数组进行排序


如果可能的话,我的目标是次线性时间复杂度。

您可以创建一个新数组,对该数组执行排序,并将
vectorboSorted
设置为新数组

int size = vectorToBeSorted.length;
int[] array = new int[size];
for (int i = 0; i < size; ++i)
    array[vectorUsedForSorting[i]] = vectorToBeSorted[i];
vectorToBeSorted = array;
那么:

int size = size(vectorUsedForSorting); 
int [] sortedVector = new int[size];
for (int i = 0; i < size; ++i)
{
    sortedVector[i] = vectorToBeSorted[vectorUsedForSorting[i]];
}  
int size=size(矢量用于排序);
int[]sortedVector=新的int[大小];
对于(int i=0;i

还是必须就地排序?

有两种方法可以解决这个问题。第一种方法是复制快速排序算法,并使用能够处理间接寻址的方法更改访问和交换值部分:

int valueAt(int index) { return vectorUsedForSorting[index]; }
int swap(int i1, int i2) {
    int tmp = vectorUsedForSorting[i1];
    vectorUsedForSorting[i1] = vectorUsedForSorting[i2];
    vectorUsedForSorting[i2] = tmp;

    tmp = vectorToBeSorted[i1];
    vectorToBeSorted[i1] = vectorToBeSorted[i2];
    vectorToBeSorted[i2] = tmp;
}
第二种方法是将值复制到新对象中:

public class Item {
    int index;
    int value;
}
创建一个数组,并用两个数组中的值创建的
Item
s填充该数组。然后,您可以创建一个
比较器
,该比较器通过
索引
对它们进行比较

当你有了这个,你就可以对数组进行排序了


如果速度不够快,那么可以创建N个线程,并让每个线程按原始数组的1/N排序。当这样做时,你使用合并步骤来加入结果。

< P>当性能是一个问题时,数组是大的,你至少必须考虑一个并行实现(特别是因为这个问题是非常并行的:它不是很大的努力,应该产生一个很好的,接近线性加速,越来越多的内核)。:

import java.util.ArrayList;
导入java.util.array;
导入java.util.Collections;
导入java.util.List;
导入java.util.concurrent.Callable;
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
公共类数组重排序
{
公共静态void main(字符串[]args)
{
基本测试();
性能测试();
}
私有静态void基本测试()
{
int[]vectorUsedForSorting=新的int[]{1,0,2,6,3,4,5};
int[]vectorToBeSorted=新int[]{1,2,3,4,5,6,7};
int[]sortedVectorLinear=新int[vectorToBeSorted.length];
int[]sortedVectorParallel=新int[vectorToBeSorted.length];
sortLinear(用于排序的矢量、已排序的矢量、已排序的矢量);
sortParallel(矢量用于排序、矢量目标排序、分拣目标并行);
System.out.println(“结果线性”+数组.toString(sortedVectorLinear));
System.out.println(“结果并行”+数组.toString(sortedVectorParallel));
}
私有静态void性能测试()
{

对于(int n=1000000;nIs
vectorUsedForSorting
已经有一个未来数组位置的列表,如您的示例中所示?或者可以有任意数字,如
{0,3,4,7}
?我的直觉是,由于无法实现经典排序,无法依赖比较运算符,因此无法快速生成某个对象。我认为可以这样做的方式是创建一个对象,其中包含要分配给该对象的最终索引和值。这意味着值为0的对象将有索引1。@Johnride-Hmm请你重构句子
我认为你可以这样做的方式是创建一个对象,其中包含要分配给这个对象的最终索引加上值。
,无法解析它。哦,我对你的编辑更了解。一个简单的
for
循环就可以了。@user2763361获取次线性我的第一个想法可能会起作用。我将在这里更清楚地说明:vectorUsedForSorting和VectorBeSorted将在一个简单对象(比如sortableObj)中看到它们的值匹配,该对象包含
索引
字段和
字段。这将创建一个sortableObj数组,如下所示:[{index:1,value:1},{index:0,value:2},{index:2,value:3}……]其中,每对花括号代表一个对象。之后,您可以对索引值执行快速排序。您所说的
就地排序是什么意思?
?我的意思是不创建第三个数组。hsun324的解决方案看起来相当不错。但如果内存不重要,则使用第三个数组的解决方案会更快。OP说,计算速度会更快简单性是很重要的。当然,内存分配会花费一些时间,但这里的运行时只是通过数组的一次。它是线性的。所以你会同意我的解决方案吗?使用arrays.sort不会是线性的。因为OP已经知道元素的最终位置,所以只通过一次就可以更快地将em在其最终位置(在一个新数组中)。这将是线性的。@JoshuaTaylor:OP不知道根据我问题的答案,元素的最终位置。我的感觉是,到目前为止,大多数答案(包括公认的答案)都是错的。@Aarondigula我不确定我是否遵循了。
VectorUsedForOrting
(即,
{1,0,2,6,3,4,5}
)是从
0
n-1
(其中有
n
个元素)的整数。如果这些元素用作排序键,则索引为
i
的元素将在排序数组中的
i
位置结束。
int valueAt(int index) { return vectorUsedForSorting[index]; }
int swap(int i1, int i2) {
    int tmp = vectorUsedForSorting[i1];
    vectorUsedForSorting[i1] = vectorUsedForSorting[i2];
    vectorUsedForSorting[i2] = tmp;

    tmp = vectorToBeSorted[i1];
    vectorToBeSorted[i1] = vectorToBeSorted[i2];
    vectorToBeSorted[i2] = tmp;
}
public class Item {
    int index;
    int value;
}
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ArrayReordering
{
    public static void main(String[] args)
    {
        basicTest();
        performanceTest();
    }

    private static void basicTest()
    {
        int[] vectorUsedForSorting = new int[] { 1,0,2,6,3,4,5 };
        int[] vectorToBeSorted = new int[] {1,2,3,4,5,6,7};      
        int[] sortedVectorLinear = new int[vectorToBeSorted.length];
        int[] sortedVectorParallel = new int[vectorToBeSorted.length];

        sortLinear(vectorUsedForSorting, vectorToBeSorted, sortedVectorLinear);
        sortParallel(vectorUsedForSorting, vectorToBeSorted, sortedVectorParallel);

        System.out.println("Result Linear   "+Arrays.toString(sortedVectorLinear));
        System.out.println("Result Parallel "+Arrays.toString(sortedVectorParallel));
    }

    private static void performanceTest()
    {
        for (int n=1000000; n<=50000000; n*=2)
        {
            System.out.println("Run with "+n+" elements");

            System.out.println("Creating input data");
            int vectorUsedForSorting[] = createVectorUsedForSorting(n);
            int vectorToBeSorted[] = new int[n];
            for (int i=0; i<n; i++)
            {
                vectorToBeSorted[i] = i;
            }
            int[] sortedVectorLinear = new int[vectorToBeSorted.length];
            int[] sortedVectorParallel = new int[vectorToBeSorted.length];

            long before = 0;
            long after = 0;

            System.out.println("Running linear");
            before = System.nanoTime();
            sortLinear(vectorUsedForSorting, vectorToBeSorted, sortedVectorLinear);
            after = System.nanoTime();
            System.out.println("Duration linear   "+(after-before)/1e6+" ms");

            System.out.println("Running parallel");
            before = System.nanoTime();
            sortParallel(vectorUsedForSorting, vectorToBeSorted, sortedVectorParallel);
            after = System.nanoTime();
            System.out.println("Duration parallel "+(after-before)/1e6+" ms");

            //System.out.println("Result Linear   "+Arrays.toString(sortedVectorLinear));
            //System.out.println("Result Parallel "+Arrays.toString(sortedVectorParallel));
            System.out.println("Passed linear?   "+
                Arrays.equals(vectorUsedForSorting, sortedVectorLinear));
            System.out.println("Passed parallel? "+
                Arrays.equals(vectorUsedForSorting, sortedVectorParallel));
        }
    }

    private static int[] createVectorUsedForSorting(int n)
    {
        // Not very elegant, just for a quick test...
        List<Integer> indices = new ArrayList<Integer>();
        for (int i=0; i<n; i++)
        {
            indices.add(i);
        }
        Collections.shuffle(indices);
        int vectorUsedForSorting[] = new int[n];
        for (int i=0; i<n; i++)
        {
            vectorUsedForSorting[i] = indices.get(i);
        }
        return vectorUsedForSorting;
    }

    private static void sortLinear(
        int vectorUsedForSorting[], int vectorToBeSorted[], 
        int sortedVector[])
    {
        sortLinear(vectorUsedForSorting, vectorToBeSorted, 
            sortedVector, 0, vectorToBeSorted.length);
    }

    static void sortParallel(
        final int vectorUsedForSorting[], final int vectorToBeSorted[], 
        final int sortedVector[])
    {
        int numProcessors = Runtime.getRuntime().availableProcessors();
        int chunkSize = (int)Math.ceil((double)vectorToBeSorted.length / numProcessors);
        List<Callable<Object>> tasks = new ArrayList<Callable<Object>>();
        ExecutorService executor = Executors.newFixedThreadPool(numProcessors);
        for (int i=0; i<numProcessors; i++)
        {
            final int min = i * chunkSize;
            final int max = Math.min(vectorToBeSorted.length, min + chunkSize);
            Runnable task = new Runnable()
            {
                @Override
                public void run()
                {
                    sortLinear(vectorUsedForSorting, vectorToBeSorted, 
                        sortedVector, min, max);
                }
            };
            tasks.add(Executors.callable(task));
        }
        try
        {
            executor.invokeAll(tasks);
        }
        catch (InterruptedException e)
        {
            Thread.currentThread().interrupt();
        }
        executor.shutdown();
    }

    private static void sortLinear(
        int vectorUsedForSorting[], int vectorToBeSorted[], 
        int sortedVector[], int min, int max)
    {
        for (int i = min; i < max; i++)
        {
            sortedVector[i] = vectorToBeSorted[vectorUsedForSorting[i]];
        }          
    }

}