प्राथमिकता प्राथमिकता को अधिकतम प्राथमिकता में बदलें


124

मैं पूर्णांक के जावा में प्राथमिकता कतार है:

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

जब मैं कॉल करता pq.poll()हूं तो मुझे न्यूनतम तत्व मिलता है।

प्रश्न: अधिकतम तत्व प्राप्त करने के लिए कोड को कैसे बदलें?


4
मुझे लगता है कि आपको उस निर्माता का उपयोग करना चाहिए जो इसके लिए तुलनित्र प्राप्त करता है। उलटा तुलनित्र प्राप्त करने के लिए Collections.reverseOrder का उपयोग करें।
एडविन डेलोरजो

1
आपको एक तुलनित्र पारित करने की आवश्यकता है। देखें stackoverflow.com/questions/683041/…
डार्थवेडर

यह मदद कर सकता है: tech693.blogspot.com/2018/09/…
Java गुरु

जवाबों:


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इस मामले में उनके प्राकृतिक क्रम में एक विपरीत क्रम में।


14
Collections.reverseOrder()एक तुलनित्र लेने के लिए भी अतिभारित है, इसलिए यदि आप कस्टम ऑब्जेक्ट्स की तुलना करते हैं तो यह भी काम करता है।
उड़ती हुई भेड़

14
Java 8 के प्रायोरिटी क्यू में एक नया कंस्ट्रक्टर है, जो सिर्फ एक तर्क के रूप में तुलनित्र लेता है PriorityQueue(Comparator<? super E> comparator)
अभिषेकमिरल

75

जावा 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 देता है, जो मूल रूप से int तुलनित्र वर्ग करता है, सिवाय इसके xy रिटर्न करता है
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()
18има Гирин

1
@ ФимаГирин यह सच है। -2147483648 - 1 2147483647
Guangtong शेन

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 returs +1; मेरे परीक्षण के बाद आपने यहां जो लिखा है वह न्यूनतम q है
सिवी

रिवर्स प्रिंटिंग के लिए, यदि उच्चतम तत्वों को प्राथमिकता कतार में पहले मुद्रित किया जाना है, तो यह होना चाहिएif (rhs < lhs) return +1; if (rhs > lhs) return -1;
Tia

@ दीक्षा मुझे विश्वास है कि मेरे पास जो कोड है वह आपके पोस्ट करने के बराबर है। मैंने कम-से-कम के बजाय अधिक से अधिक संबंध का उपयोग किया है।
templatetypedef

4
वास्तव में, मेरी गलती .. मेरा मतलब था कि इसे इस तरह होना चाहिए:if (lhs < rhs) return +1; if (lhs > rhs) return -1;
टिया

1
@ श्रीकांतप्रभु अच्छा कैच - जो अब तय हो गया है!
templatetypedef

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

समस्या क्या है ?
CMedina

यह एकदम सही है और वास्तव में वही किया जाता है जो न्यूनतम ढेर को अधिकतम ढेर में बदलकर पूछा जाता है।
कामरान

2
उपयोग करने के b-aकारण overflowइसका उपयोग करने से बचना चाहिए और Collections.reverseOrder();एक तुलनित्र के रूप में उपयोग करना चाहिए या बा को बदलना चाहिए Integer.compare(a,b);जिसके साथ जोड़ा गया हैJava 8
युग सिंह

10

जावा 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)

डिफ़ॉल्ट तुलना विधि एक नकारात्मक पूर्णांक, शून्य या एक सकारात्मक पूर्णांक लौटाती है क्योंकि पहला तर्क दूसरे के मुकाबले कम या ज्यादा होता है।

जावा द्वारा प्रदान किया गया डिफ़ॉल्ट प्राथमिकता क्यू मिन-हीप है, यदि आप चाहते हैं कि एक अधिकतम हीप निम्नलिखित कोड हो

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

यहाँ जावा में एक नमूना मैक्स-हीप है:

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

यह जावा 8 में नीचे दिए गए कोड द्वारा प्राप्त किया जा सकता है जिसने एक निर्माणकर्ता पेश किया है जो केवल एक तुलनित्र लेता है।

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


3

प्राथमिकता प्राथमिकता को अधिकतम प्राथमिकता में बदलें विधि 1: कतार pq = नया वरीयता क्रम <> (संग्रह .reverseOrder ()); विधि 2: कतार pq1 = नया प्राथमिकता कतार <> ((ए, बी) -> बी - ए); आइए कुछ उदाहरण देखें:

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

         */


    }
}

आइए एक प्रसिद्ध साक्षात्कार समस्या लेते हैं: प्राथमिकता ऐरे का उपयोग करके ऐरे में Kth सबसे बड़ा तत्व

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

मैं सिर्फ डबल हीप सॉर्ट अधिकतम पर दोनों तुलनित्र पर एक मोंटे-कार्लो सिमुलेशन चलाता था और वे दोनों एक ही परिणाम पर आए:

ये मेरे द्वारा उपयोग किए जाने वाले अधिकतम तुलनित्र हैं:

(ए) संग्रह तुलनित्र में निर्मित

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

(बी) कस्टम तुलनित्र

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;अगर (rhs> lhs) रिटर्न -1;
टिया

आप चाहें तो इसे एडिट कर सकते हैं। मेरे पास इस बात की पुष्टि करने का कोई समय नहीं है कि आपने क्या लिखा है। मेरे सेटअप में जो मैंने लिखा था वह सही था
शिवानी

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

हम अपने 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;
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.