문제

업데이트:사실에서,유일하게 수락가능한 솔루션이 이 문제에 대한 것을 정렬 배열을 오름차순으로 다음 반전니다.

S 수 이벤트 시퀀스는 다음과 같습니다:

Event | Time
  A   | 0:00
  B   | 0:01
  C   | 0:01
  D   | 0:02

내가 있는 간단한 비교기를 정렬 S, 는 종류의 요소에 따라 시간 값이 있습니다.

public int compare(Event e1, Event e2) {

    // Reverse sorting. 
    // _sortOrder is set outside this method.
    if(SORT_DESCENDING.equals(_sortOrder))
        return e2.getTime() - e1.getTime(); /* time is long */

    return e1.getTime() - e2.getTime();
}

문제입니다:을 때는 정렬 순서입니다 오름차순, S 이 올바르게 정렬:A,B,C,D.

하지만 내가 사용하는 경우 역방향 분류 S 은 D,B,C,A:

Event | Time
  D   | 0:02
  B   | 0:01 /* B and C should be reversed */
  C   | 0:01
  A   | 0:00

이런 일이기 때문에 기본 정렬 알고리즘을 유지 원래의 주문을 위한 요소와 동일 시간 값이 있습니다.

그래서,어떻게 정렬 반전을 유지하지 않고 원래의 주문합니까?

참고: 나는 정렬 할 수 있습니다 S 오름차순으로 더욱 단순히 되돌 그것은,그러나 불행하게도 이 옵션을 선택하지 않습니다.

도움이 되었습니까?

해결책

분류 알고리즘이 정확합니다. 0.01은 0.01입니다. 당신이 우리에게 말하지 않는 것이 아니라면. 그러나 오름차순의 정확한 역 순서를 원한다면 오름차순 순서와 사용으로 정렬하십시오. Collections.Reverse (). 이것으로 나는 다음을 의미합니다.

List<SomeObject> list = ...;
Collections.sort(list, myComparator);
Collections.reverse(list);

당신이 원하는 것을 정확하게 줄 것입니다.

그러나 반전이 옵션이 아닌 경우 두 가지 옵션 만 남습니다.

  1. 두 요소가 "동일"할 수 없도록하십시오. 다른 필드를 포함하거나 합성 필드를 추가하십시오 (예 : 현재 색인 또는 숫자 인 경우 기본 키 등). 이것은 당신에게 재현 가능하고 일관되고 거울 된 순서를 제공합니다. 또는
  2. 자신의 정렬 알고리즘을 구현하십시오. 너무 오류가 발생하기 때문에 권장하지 않습니다.

이제 당신이 되돌릴 수 없다고 말하기 전에 (왜?), 당신이 어떻게 정렬하는지 물어 보겠습니다. 사용하는 경우 Collections.sort() 소스 코드 (Java 6U10)를 고려하십시오.

public static <T extends Comparable<? super T>> void sort(List<T> list) {
Object[] a = list.toArray();
Arrays.sort(a);
ListIterator<T> i = list.listIterator();
for (int j=0; j<a.length; j++) {
    i.next();
    i.set((T)a[j]);
}
}

따라서 컬렉션을 배열로 복사하고 배열을 정렬 한 다음이를 사용하여 컬렉션을 재정렬합니다.

반전을 감당할 수 없다고 확신합니까?

다른 팁

정렬하기 위해 무엇을 사용하고 있습니까? 내 생각에 그것은 그것이 안정적인 정렬 - 비교에 관한 한 두 가지 동일한 값이 있습니다.

이 경우 부과 할 수있는 추가 주문이 있습니까? 오름차순 순서에서 어떤 이벤트가 먼저 올지 쉽게 알 수 있습니까? 그렇다면 원래 비교도 사용하여 하강 순서가 자연스럽게 작동하기 시작합니다.

편집 : 데이터에 추가 주문 정보가 없으므로 Oracle에서 동일한 쿼리를 다시 수행 할 때 다른 주문으로 반환 된 경우 놀라지 않을 것입니다. 그러나이 특정 사례에서 주문에 대해서만 신경 쓰는 경우, Java 인 메모리 표현에 추가 필드를 추가하여 원래 색인을로드 된 목록에 저장하는 것이 좋습니다. 데이터를 읽을 때 얼마나 많은지 추적하십시오. 그에 따라 필드를 읽고 할당합니다. 그런 다음 정렬 할 때 사용할 수 있습니다.

내가 무언가를 놓치고 있습니까, 아니면 이벤트 이름 (또는 A, B, C 및 D)을 보조 정렬 키로 사용할 수 없습니까? 비교기를 다음과 같은 것으로 확장하십시오.

public int compare(Event e1, Event e2) {
    int cmp = e1.getTime() - e2.getTime(); // compare times
    if (cmp == 0)  // if times are equal, compare names instead
        cmp = e1.getName().compareTo(e2.getName());
    return SORT_DESCENDING.equals(_sortOrder)? -cmp : cmp;
}

나는 당신이 정말로 원하는 것이 2 차 정렬 기준이라고 생각합니다. 따라서 기본 정렬 기준이 항목을 동일하게 고려하더라도 항목을 정렬 할 수 있습니다. 당신의 예에서, 주요 기준은 시간이며, 이는 이벤트가 될 것입니다. 이런 식으로, 당신은 종류를 수행하기 전에 특정 순서로있는 항목에 의존 할 필요가 없으므로 상황이 훨씬 쉬워집니다.

2 차 기준이 없다면 Jon Skeet과 같이 안정적인 대 불안정한 정렬 알고리즘을 살펴 봐야 할 것입니다.

또 다른 방법이지만 문제를 해결하지 마십시오.

List<SomeObject> list = ...;
Collections.sort(list, Collections.<SomeObject>reverseOrder());

왜 0:01 작/보다 큰 0:01,또는 왜 그것이 정렬되는 매우 특별한 방법으로는 경우 그들은 모두 같습니까?

당신이하지 않고 반대로 정렬한 반전 정렬,죄송합니다.:)

정렬 순서가 올바르게 보입니다. e1.gettime () == e2.gettime () 인 경우 이름을 비교하십시오.

두 요소를 전환하는 것과 비교할 때 두 요소를 비교하는 데 얼마나 빨리 비교되는지에 따라 내림차순 안정적인 종류를 수행 한 다음 "동일한"요소의 모든 영역 만 역전 할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top