priorityQueue를 최대 priorityqueue로 변경


124

Java of Integers에 우선 순위 대기열이 있습니다.

 PriorityQueue<Integer> pq= new PriorityQueue<Integer>();

전화 pq.poll()하면 최소 요소를 얻습니다.

질문 : 최대 요소를 얻기 위해 코드를 변경하는 방법은 무엇입니까?


4
이를 위해 비교기를받는 생성자를 사용해야한다고 생각합니다. Collections.reverseOrder를 사용하여 반전 된 비교기를 얻습니다.
— Edwin Dalorzo 2012-06-12

1
비교기를 통과해야합니다. 참조 stackoverflow.com/questions/683041/…
— DarthVader

답변:


232

다음과 같이 어떻습니까?

PriorityQueue<Integer> queue = new PriorityQueue<>(10, Collections.reverseOrder());
queue.offer(1);
queue.offer(2);
queue.offer(3);
//...

Integer val = null;
while( (val = queue.poll()) != null) {
    System.out.println(val);
}

는 Collections.reverseOrder()제공 Comparator의 요소 정렬 할 것이라고 PriorityQueue이 경우 자연 순서 a를 oposite 순서를.


14
Collections.reverseOrder()비교기를 가져 오기 위해 오버로드되기 때문에 사용자 지정 개체를 비교하는 경우에도 작동합니다.
— 날으는 양 '

14
Java 8의 PriorityQueue에는 comparator를 인수로 취하는 새로운 생성자가 PriorityQueue(Comparator<? super E> comparator)있습니다.
— abhisheknirmal

75

Java 8부터 람다 식을 사용할 수 있습니다.

다음 코드는 더 큰 10을 인쇄합니다.

// There is overflow problem when using simple lambda as comparator, as pointed out by Фима Гирин.
// PriorityQueue<Integer> pq = new PriorityQueue<>((x, y) -> y - x);

PriorityQueue<Integer> pq =new PriorityQueue<>((x, y) -> Integer.compare(y, x));

pq.add(10);
pq.add(5);
System.out.println(pq.peek());

람다 함수는 두 개의 정수를 입력 매개 변수로 취하고 서로 빼고 산술 결과를 반환합니다. 람다 함수는 기능 인터페이스 인 Comparator<T>. (이는 익명 클래스 또는 개별 구현과는 반대로 제자리에 사용됩니다.)


람다 함수는 입력 매개 변수 x와 y의 이름을 지정하고 yx를 반환합니다. 이는 기본적으로 xy를 반환하는 것을 제외하고는 int 비교기 클래스가 수행하는 작업입니다.
— Edi Bice

15
같은 비교기 (x, y) -> y - x는 오버플로로 인해 긴 정수에 적합하지 않을 수 있습니다. 예를 들어, 숫자 y = Integer.MIN_VALUE 및 x = 5는 양수입니다. 사용하는 것이 좋습니다 new PriorityQueue<>((x, y) -> Integer.compare(y, x)). 하지만 더 나은 솔루션은 @Edwin Dalorzo가 Collections.reverseOrder().
— Фима Гирин

1
@ ФимаГирин 사실입니다. -2147483648-1이 2147483647이 됨
— Guangtong Shen

27

Comparator요소의 순위를 역순 으로 지정하는 사용자 지정 개체를 제공 할 수 있습니다 .

PriorityQueue<Integer> pq = new PriorityQueue<Integer>(defaultSize, new Comparator<Integer>() {
    public int compare(Integer lhs, Integer rhs) {
        if (lhs < rhs) return +1;
        if (lhs.equals(rhs)) return 0;
        return -1;
    }
});

이제 우선 순위 큐는 모든 비교를 역순으로 수행하므로 최소 요소가 아닌 최대 요소를 얻을 수 있습니다.

도움이 되었기를 바랍니다!


5
최대 우선 순위 q의 경우 lhs <rhs는 +1을 반환합니다. 여기에 쓴 것은 내 테스트 후 최소 q입니다
— sivi

역방향 인쇄의 경우, 즉 가장 높은 요소가 우선 순위 대기열에서 먼저 인쇄되는 경우 다음과 같아야합니다.if (rhs < lhs) return +1; if (rhs > lhs) return -1;
— Tia

@Diksha 내가 가진 코드가 당신이 게시하는 것과 동일하다고 생각합니다. 나는보다 작다보다는보다 큼 관계를 사용했습니다.
— templatetypedef

4
사실, 내 실수 .. 나는 그것이 다음과 같아야한다는 것을 의미했습니다 :if (lhs < rhs) return +1; if (lhs > rhs) return -1;
— Tia

1
@ShrikantPrabhu 좋은 캐치-이제 수정되었습니다!
— templatetypedef

14
PriorityQueue<Integer> pq = new PriorityQueue<Integer> (
  new Comparator<Integer> () {
    public int compare(Integer a, Integer b) {
       return b - a;
    }
  }
);

무엇이 문제입니까?
— CMedina

이것은 완벽하며 최소 힙을 최대 힙으로 변환하여 요청한 작업을 정확히 수행합니다.
— Kamran

2
사용하여 b-a발생할 수 overflow있으므로 것은 그것을 사용하지 않아야하고 사용한다 Collections.reverseOrder();비교기 나와 바 교체 Integer.compare(a,b);에 추가되었습니다Java 8
— 하기 Yug 싱

10

Java 8 이상에서는 다음 방법 중 하나를 통해 최대 우선 순위 대기열을 만들 수 있습니다.

방법 1 :

PriorityQueue<Integer> maxPQ = new PriorityQueue<>(Collections.reverseOrder()); 

방법 2 :

PriorityQueue<Integer> maxPQ = new PriorityQueue<>((a,b) -> b - a); 

방법 3 :

PriorityQueue<Integer> maxPQ = new PriorityQueue<>((a,b) -> b.compareTo(a)); 

8

우선 순위 큐의 요소는 자연스러운 순서에 따라 또는 큐 생성시 제공되는 비교기에 의해 정렬됩니다.

비교기는 비교 방법을 재정의해야합니다.

int compare(T o1, T o2)

기본 비교 메서드는 첫 번째 인수가 두 번째 인수보다 작거나 같거나 크므로 음의 정수, 0 또는 양의 정수를 반환합니다.

Java에서 제공하는 기본 PriorityQueue는 Min-Heap입니다. 최대 힙을 원하는 경우 다음 코드가 있습니다.

public class Sample {
    public static void main(String[] args) {
        PriorityQueue<Integer> q = new PriorityQueue<Integer>(new Comparator<Integer>() {

            public int compare(Integer lhs, Integer rhs) {
                if(lhs<rhs) return +1;
                if(lhs>rhs) return -1;
                return 0;
            }
        });
        q.add(13);
        q.add(4);q.add(14);q.add(-4);q.add(1);
        while (!q.isEmpty()) {
            System.out.println(q.poll());
        }
    }

}

참조 : https://docs.oracle.com/javase/7/docs/api/java/util/PriorityQueue.html#comparator ()


4

다음은 Java의 샘플 Max-Heap입니다.

PriorityQueue<Integer> pq1= new PriorityQueue<Integer>(10, new Comparator<Integer>() {
public int compare(Integer x, Integer y) {
if (x < y) return 1;
if (x > y) return -1;
return 0;
}
});
pq1.add(5);
pq1.add(10);
pq1.add(-1);
System.out.println("Peek: "+pq1.peek());

출력은 10입니다.


4

이는 비교기 만 사용하는 생성자를 도입 한 Java 8의 아래 코드에 의해 달성 될 수 있습니다.

PriorityQueue<Integer> maxPriorityQ = new PriorityQueue<Integer>(Collections.reverseOrder());


3

PriorityQueue를 MAX PriorityQueue로 변경 방법 1 : 대기열 pq = new PriorityQueue <> (Collections.reverseOrder ()); 방법 2 : 대기열 pq1 = new PriorityQueue <> ((a, b)-> b-a); 몇 가지 예를 살펴 보겠습니다.

public class Example1 {
    public static void main(String[] args) {

        List<Integer> ints = Arrays.asList(222, 555, 666, 333, 111, 888, 777, 444);
        Queue<Integer> pq = new PriorityQueue<>(Collections.reverseOrder());
        pq.addAll(ints);
        System.out.println("Priority Queue => " + pq);
        System.out.println("Max element in the list => " + pq.peek());
        System.out.println("......................");
        // another way
        Queue<Integer> pq1 = new PriorityQueue<>((a, b) -> b - a);
        pq1.addAll(ints);
        System.out.println("Priority Queue => " + pq1);
        System.out.println("Max element in the list => " + pq1.peek());
        /* OUTPUT
          Priority Queue => [888, 444, 777, 333, 111, 555, 666, 222]
          Max element in the list => 888
          ......................
           Priority Queue => [888, 444, 777, 333, 111, 555, 666, 222]
           Max element in the list => 888

         */


    }
}

유명한 인터뷰 문제 : PriorityQueue를 사용하는 어레이에서 K 번째로 큰 요소

public class KthLargestElement_1{
    public static void main(String[] args) {

        List<Integer> ints = Arrays.asList(222, 555, 666, 333, 111, 888, 777, 444);
        int k = 3;
        Queue<Integer> pq = new PriorityQueue<>(Collections.reverseOrder());
        pq.addAll(ints);
        System.out.println("Priority Queue => " + pq);
        System.out.println("Max element in the list => " + pq.peek());
        while (--k > 0) {
            pq.poll();
        } // while
        System.out.println("Third largest => " + pq.peek());
/*
 Priority Queue => [888, 444, 777, 333, 111, 555, 666, 222]
Max element in the list => 888
Third largest => 666

 */
    }
}

또 다른 방법 :

public class KthLargestElement_2 {
    public static void main(String[] args) {
        List<Integer> ints = Arrays.asList(222, 555, 666, 333, 111, 888, 777, 444);
        int k = 3;

        Queue<Integer> pq1 = new PriorityQueue<>((a, b) -> b - a);
        pq1.addAll(ints);
        System.out.println("Priority Queue => " + pq1);
        System.out.println("Max element in the list => " + pq1.peek());
        while (--k > 0) {
            pq1.poll();
        } // while
        System.out.println("Third largest => " + pq1.peek());
        /*
          Priority Queue => [888, 444, 777, 333, 111, 555, 666, 222] 
          Max element in the list => 888 
          Third largest => 666

         */
    }
}

보시다시피, 둘 다 동일한 결과를 제공합니다.


3

이것은 다음을 사용하여 얻을 수 있습니다.

PriorityQueue<Integer> pq = new PriorityQueue<Integer>(Collections.reverseOrder());

1

방금 double heap sort min max의 두 비교기에서 Monte-Carlo 시뮬레이션을 실행했는데 둘 다 동일한 결과를 얻었습니다.

다음은 내가 사용한 최대 비교기입니다.

(A) 컬렉션 내장 비교기

 PriorityQueue<Integer> heapLow = new PriorityQueue<Integer>(Collections.reverseOrder());

(B) 맞춤형 비교기

PriorityQueue<Integer> heapLow = new PriorityQueue<Integer>(new Comparator<Integer>() {
    int compare(Integer lhs, Integer rhs) {
        if (rhs > lhs) return +1;
        if (rhs < lhs) return -1;
        return 0;
    }
});

역방향 인쇄의 경우, 즉 우선 순위 대기열에서 가장 높은 요소가 먼저 인쇄되는 if (rhs < lhs) return +1;경우 if (rhs> lhs) return -1;
— Tia

원하는 경우 편집 할 수 있습니다. 당신이 쓴 것을 확인할 시간이 없습니다. 내 설정에서 내가 쓴 내용이 정확했습니다
— sivi

1

다음과 같이 시도 할 수 있습니다.

PriorityQueue<Integer> pq = new PriorityQueue<>((x, y) -> -1 * Integer.compare(x, y));

다른 기본 비교 기능에서 작동합니다.



0

역 기호로 요소를 밀어 볼 수 있습니다. 예 : a = 2 & b = 5를 추가 한 다음 b = 5를 폴링합니다.

PriorityQueue<Integer>  pq = new PriorityQueue<>();
pq.add(-a);
pq.add(-b);
System.out.print(-pq.poll());

대기열의 헤드를 폴링하면 사용량에 대한 기호를 뒤집습니다. 그러면 5 (더 큰 요소)가 인쇄됩니다. 순진한 구현에 사용할 수 있습니다. 확실히 신뢰할 수있는 수정이 아닙니다. 나는 그것을 추천하지 않는다.


0

Comparator 인터페이스를 구현하는 CustomComparator 클래스를 만들고 비교 메서드를 재정 의하여이를 수행 할 수 있습니다 . 다음은 동일한 코드입니다.

import java.util.PriorityQueue;
import java.util.Comparator;
public class Main
{
    public static void main(String[] args) {
        PriorityQueue<Integer> nums = new PriorityQueue<>(new CustomComparator());
        nums.offer(21);
        nums.offer(1);
        nums.offer(8);
        nums.offer(2);
        nums.offer(-4);
        System.out.println(nums.peek());
    }
}
class CustomComparator implements Comparator<Integer>{
    @Override
    public int compare(Integer n1, Integer n2){
        int val = n1.compareTo(n2);
        if(val > 0)
           return -1;
        else if(val < 0)
            return 1;
        else
            return 0;
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.