基于一行数据对二维数组进行排序

问题描述:

我不确定标题是否正确地表明了我想要问的内容。比方说,我有如下二维int数组:基于一行数据对二维数组进行排序

int[][] x={{1,7,6},{2,4,8}}; 

现在我想按升序排列的第一行进行排序和数据于第2行必须在排序后的同一列,即后排序,阵列应该是这样的:

x={{1,6,7},{2,8,4}} 

什么是正确的方法来做到这一点?

+0

您是否只有两行数据?或者你可以有N行?如果有N行,您可以将您要排序的行拖入原始索引的值对列表中,按值排序,然后为每行创建一个新数组,并通过索引提取原始值并替换。 – Charlie

这可以通过实现自己的排序例程来完成,但更好的方法是重构。

尝试将数据封装为数组对,每对数组包含在它自己的对象中。然后,您可以对第一个值进行排序并访问任一值。

class Pair<T extends Comparable<T>> implements Comparable<Pair<T>> { 
    final T a; 
    final T b; 

    public Pair (T a, T b) { 
    this.a = a; 
    this.b = b; 
    } 

    @Override 
    public int compareTo(Pair<T> o) { 
    // Comparison on 'a' only. 
    return a.compareTo(o.a); 
    } 

    @Override 
    public String toString() { 
    return "{" + a + "," + b + "}"; 
    } 
} 

public static void main(String args[]) { 
    Pair[] pairs = { 
    new Pair(1,2), 
    new Pair(7,4), 
    new Pair(6,8), 
    }; 
    System.out.println("Before: "+Arrays.toString(pairs)); 
    Arrays.sort(pairs); 
    System.out.println("After: "+Arrays.toString(pairs)); 
} 

打印

Before: [{1,2}, {7,4}, {6,8}] 
After: [{1,2}, {6,8}, {7,4}] 
+0

这个aproche并不好,因为你必须打包许多不需要的对象。并通过创建新类来增加complecity到解决方案。 –

+0

@AleksanderGralak - 另一种方法是编写自己的排序算法。你的选择。 – OldCurmudgeon

+1

没有。您可以使用我的解决方案。这是其中一个答案。没有新的类,没有新的对象。抱歉有一个新对象:比较器。而且你还有阵列效率。 –

最简单的方法是创建一个Pair对象持有的对,对的集合与定制的比较,只有比较一对中的第一项进行排序。

如果需要,您可以随时将对变换回二维数组。

这可能不是最有效的方式,但对于大多数使用情况应该足够好。

可以通过实现自己的排序算法并将值移动到第二行来完成。你可能有一个Obejcts数组。每个对象将保持值。然后实现您的自定义比较器并使用排序功能。

我还有一个想法:重新排列数组(如果可以的话)。然后将对保存在一个int []表中。而外部表是INT表一conatiner:

int [][] a = {{2,5},{1,4},{3,6}}; 
Arrays.sort(a, new Comparator<int[]>() { 
     @Override 
     public int compare(int[] p_o1, int[] p_o2) { 
      return Integer.valueOf(p_o1[0]).compareTo(p_o2[0]); 
     } 
}); 
+0

非常适合我的选择。 – OldCurmudgeon

+0

谢谢。你的想法是我的第一个想法。但是后来我认为没有太多的编码就一定有办法做到这一点。 –

如果所有的第一行的元素是独一无二的,非空,你可以在排序前,填充一个地图,第一行元素指向其第二排同行。在对第一行进行排序之后,可以使用该映射查找第二行的第一个(排序的)行的相应元素。

+0

这根本没有效率。但它会起作用;) –

你基本上在做一个Map,为什么不使用Map实现来帮助你?

TreeMap实现SortedMap,这样一个简单的解决办法是将所有的映射值里面:

SortedMap<Integer, Integer> map = new TreeMap<Integer, Integer>(); 
map.put(1, 2); 
map.put(7, 4); 
map.put(6, 8); 

// You can iterate over map now, it'll be already sorted 
for(Map.Entry<Integer, Integer> entry: map.entrySet()) 
{ 
    System.out.println(entry.getKey()+" : "+entry.getValue()); 
} 

// This is not really necessary 
Integer[][] x = {map.keySet().toArray(new Integer[0]), map.values().toArray(new Integer[0])}; 

// If you have Apache Commons you can: 
int[][] y = {ArrayUtils.toPrimitive(map.keySet().toArray(new Integer[0])), ArrayUtils.toPrimitive(map.values().toArray(new Integer[0]))}; 

我复制从http://www.algolist.net/Algorithms/Sorting/Quicksort,并稍加修改

public static void main(String[] args) throws Exception { 
     int[][] x = { { 1, 7, 6 }, { 2, 4, 8 } }; 
     qsort(x[0], x[1], 0, x[0].length - 1); 
     System.out.println(Arrays.deepToString(x)); 
    } 

    static void qsort(int[] x0, int[] x1, int left, int right) { 
     int index = partition(x0, x1, left, right); 
     if (left < index - 1) 
      qsort(x0, x1, left, index - 1); 
     if (index < right) 
      qsort(x0, x1, index, right); 
    } 

    static int partition(int[] x0, int[] x1, int left, int right) { 
     int i = left, j = right; 
     int tmp; 
     int pivot = x0[(left + right)/2]; 
     while (i <= j) { 
      while (x0[i] < pivot) 
       i++; 
      while (x0[j] > pivot) 
       j--; 
      if (i <= j) { 
       tmp = x0[i]; 
       x0[i] = x0[j]; 
       x0[j] = tmp; 

       // swap x1 too 
       tmp = x1[i]; 
       x1[i] = x1[j]; 
       x1[j] = tmp; 

       i++; 
       j--; 
      } 
     } 
     return i; 
    } 
} 

这个程序打印粘贴的qsort

[[1, 6, 7], [2, 8, 4]] 

这可能看起来很长,但通常对于算法来说效率非常关键,而且这种解决方案似乎是最快的