-1

Using Arrays.sort( array ); is a very easy way to sort an array. But there is a problem. For each unsorted array, there is an index which is referring to an object in some other data structure. When sorting an array (using the above code or any other similar ways) the index of each value will be changed. Is there a solution to have the assigned index of each value?

EDIT

Using HashMap<Key, Value> will not be useful since there are a lot of same values in the array.

user3049183
  • 136
  • 1
  • 3
  • 16

2 Answers2

1

Sort both data structures in parallel.

Or make the reference index (to reference the other data structure) an internal field of each element, so that each element maintains the same "reference index" even if the order of the elements is changed by sorting.

Or better yet, just give each element an internal field that is just a direct reference variable to the element in the other data structure. (unless you need the raw index itself for some reason and not just a reference to the associated object / value)

For example: this SO Q&A

Community
  • 1
  • 1
Travis
  • 2,135
  • 17
  • 29
0

First, having two parallel arrays with elements in corresponding indexes indicates you might want to change the data structure to a single array with a container object containing two fields. This container object would then implement Comparable interface.

But, sticking with what you say, one approach could be:

/**
 * Sorts parallel arrays in-place.  Sorted by the first array and updating
 * all other arrays to match.
 * Uses the natural sorting of the objects.
 * All arrays must be the same length.
 *
 * @param  keys         the values used to sort, may be duplicate
 *
 * @param  otherArrays  the arrays to have reordered to match the sorting of
 *                      the keys array.
 *
 * @exception  IllegalArgumentException  if any of otherArrays have a length
 *                      different that the keys array.
 */
public static <E extends Comparable<? super E>> void sortParallelArrays(
    E[] keys,
    Object[] ... otherArrays
) {
    int numKeys = keys.length;
    int numOtherArrays = otherArrays.length;
    for(Object[] otherArray : otherArrays) {
        if(otherArray.length != numKeys) {
            throw new IllegalArgumentException("Mismatched array lengths");
        }
    }
    // A list of all indexes per key
    // This also does the sorting within the TreeMap using natural ordering
    SortedMap<E, List<Integer>> originalIndexesByKey = new TreeMap<E, List<Integer>>();

    // Populate the map
    for(int i = 0; i < numKeys; i++) {
        E key = keys[i];
        List<Integer> originalIndexes = originalIndexesByKey.get(key);
        if(originalIndexes == null) {
            // Optimization for the non-duplicate keys
            originalIndexesByKey.put(key, Collections.singletonList(i));
        } else {
            if(originalIndexes.size() == 1) {
                // Upgrade to ArrayList now that know have duplicate keys
                originalIndexes = new ArrayList<Integer>(originalIndexes);
                originalIndexesByKey.put(key, originalIndexes);
            }
            originalIndexes.add(i);
        }
    }

    // Store back to keys and sort other arrays in a single traversal
    Object[][] sortedOtherArrays = new Object[numOtherArrays][numKeys];
    int pos = 0;
    for(Map.Entry<E, List<Integer>> entry : originalIndexesByKey.entrySet()) {
        E key = entry.getKey();
        for(int index : entry.getValue()) {
            keys[pos] = key;
            for(int ooIndex = 0; ooIndex < numOtherArrays; ooIndex++) {
                sortedOtherArrays[ooIndex][pos] = otherArrays[ooIndex][index];
            }
            pos++;
        }
    }
    assert pos == numKeys : "Arrays should be full";

    // Copy back to original arrays for in-place sort
    for(int ooIndex = 0; ooIndex < numOtherArrays; ooIndex++) {
        System.arraycopy(
            sortedOtherArrays[ooIndex], 0,
            otherArrays[ooIndex], 0,
            numKeys);
    }
}

This is not the most memory efficient strategy, but isn't much code.

The time complexity isn't too bad. Looks something like O((M+1)*N*log(N)), where M is the number of otherArrays and N is the number of keys. No crazy worst-case issues, at least.

Dan Armstrong
  • 469
  • 2
  • 5