用户定义对象的优先队列

Posted

技术标签:

【中文标题】用户定义对象的优先队列【英文标题】:Priority Queue of user defined objects 【发布时间】:2021-06-29 11:42:32 【问题描述】:

我想根据对象的属性创建对象的优先级队列。如何根据特定属性比较队列。例如,如果我在某处输入 id,则队列是为 id 设计的。我在下面有两个不同的 java 文件。我想通过比较对象的属性来获得所有可能的队列。

第一

public class customers 

    int id;
    String name;
    int age;
    double money;
    public customers(int id, String name, int age, double money) 
        this.id = id;
        this.name = name;
        this.age = age;
        this.money = money;
    

public int getId() 
        return id;
    

    public void setId(int id) 
        this.id = id;
    



主文件现在开始



import java.util.ArrayList;
import java.util.PriorityQueue;

public class draft 


    public static void main(String[] args) 

         PriorityQueue<customers> customerList= new PriorityQueue<>();
         customers customer1= new customers(0,"jack",30,180.5);
         customers customer2= new customers(1,"john",52,800.3);
         customers customer3= new customers(2,"alice", 41, 400.5);
         customerList.add(customer1);
         customerList.add(customer2);
         customerList.add(customer3);

        for (customers c:customerList
             ) 
            System.out.println(c.getId());
        

    




我想要一个像这样的简单解决方案。下面的代码无效,但我无法理解复杂的代码。我认为必须有一个简单的解决方案。

         PriorityQueue<customers> customerList= new PriorityQueue<>(customers.age);

我不知道我是否解释了这个问题。例如,如果我比较对象 ID,则队列应按此顺序为对象#0、对象#1、对象#2。如果我比较对象的年龄,队列将是对象#0、对象#2、对象#1

【问题讨论】:

你可以使用 Comparator 来定义你的方法 我如何使用它,您可以输入解决方案。复杂吗? 【参考方案1】:

这里有几种方法可以根据特定类的任何字段来维护 PriorityQueue。 下图是定义一个PriorityQueue,按照id字段排序(升序排列):

    public static void main(String[] args)
    
        // Method 1] Using Custom Comparator
        PriorityQueue<Customers> pq1 = new PriorityQueue<Customers>(Comparator.comparing(Customers::getId));
        Customers customer1 = new Customers(0,"jack",30,180.5);
        Customers customer2 = new Customers(1,"john",52,800.3);
        Customers customer3 = new Customers(2,"alice", 41, 400.5);
        pq1.add(customer1);
        pq1.add(customer2);
        pq1.add(customer3);
        
        // Method 2] Using Lambda Operator
        PriorityQueue<Customers> pq2 = new PriorityQueue<>((x, y) -> x.id-y.id);
        //Method 3] Custom Comparator again
        PriorityQueue<Customers> pq3 = new PriorityQueue<>(new Comparator<Customers>()
        
            @Override
            public int compare(Customers a, Customers b)
            
                return a.id-b.id;
            
        );
        pq2.addAll(pq1);
        pq3.addAll(pq1);
        
        System.out.println(pq1);
        System.out.println(pq2);
        System.out.println(pq3);
    

输出:[(0 , jack , 30 , 180.5), (1 , john , 52 , 800.3), (2 , alice , 41 , 400.5)][(0 , jack , 30 , 180.5), (1 , john , 52 , 800.3), (2 , alice , 41 , 400.5)][(0 , jack , 30 , 180.5), (1 , john , 52 , 800.3), (2 , alice , 41 , 400.5)] 同样,您可以根据您选择的任何字段设计其他队列

为了以相反的顺序(递减/递减顺序)维护优先级队列,我们​​需要颠倒比较器中的顺序,例如:

PriorityQueue<Customers> pq2 = new PriorityQueue<>((x, y) -> y.id-x.id);

请注意,升序是:(x, y) -> x.id-y.id 对于降序,它将是:(x, y) -> y.id-x.id 使用custom Comparator

    PriorityQueue<Customers> pq3 = new PriorityQueue<>(new Comparator<Customers>()
    
        @Override
        public int compare(Customers a, Customers b)
        
            return b.id-a.id; // reversed
        
    );

如果您想根据两个字段对优先级队列进行排序,假设ageid 这样如果多个age相等,那么优先级已发送给id。 您可以通过以下方式实现上述目标:

    public static void main(String[] args)
    
        // Method 1] Using Custom Comparator (Increasing order)
        PriorityQueue<Customers> pq1 = new PriorityQueue<Customers>(Comparator.comparing(Customers::getAge).thenComparing(Customers::getId));
        Customers customer1 = new Customers(0,"jack",30,180.5);
        Customers customer2 = new Customers(1,"john",52,800.3);
        Customers customer3 = new Customers(2,"alice", 41, 400.5);
        pq1.add(customer1);
        pq1.add(customer2);
        pq1.add(customer3);
        
        // Method 2] Using Lambda Operator (Increasing order)
        PriorityQueue<Customers> pq2 = new PriorityQueue<>((x, y) -> (x.age == y.age) ? x.id-y.id : x.age-y.age);
        //Method 3] Custom Comparator again (Reverse order)
        PriorityQueue<Customers> pq3 = new PriorityQueue<>(new Comparator<Customers>()
        
            @Override
            public int compare(Customers a, Customers b)
            
                return (a.age == b.age) ? b.id-a.id : b.age-a.age;
            
        );
        pq2.addAll(pq1);
        pq3.addAll(pq1);
        
        System.out.println(pq1);
        System.out.println(pq2);
        System.out.println(pq3);
    

对于基于agemoney 的排序,只需少量修改,因为moneydouble 数据类型。以下是您如何实现预期目标:

    PriorityQueue<Customers> pq1 = new PriorityQueue<Customers>(Comparator.comparing(Customers::getAge).thenComparing(Customers::getMoney));
    PriorityQueue<Customers> pq2 = new PriorityQueue<>((x, y) -> (x.age == y.age) ? Double.compare(x.money,y.money) : x.age-y.age);
    PriorityQueue<Customers> pq3 = new PriorityQueue<>(new Comparator<Customers>()
       @Override
        public int compare(Customers a, Customers b)
        
            return (a.age == b.age) ? Double.compare(a.money,b.money) : a.age-b.age;
        
    );

使用poll 方法验证priorityQueue 中元素的顺序。 所有的实现都很容易理解。但是,如果您很难理解它,请与我们联系。

【讨论】:

如何让它反转?例如,如果我想根据 id 的值创建优先级队列,从大到小。有什么实用的方法吗 我还有一个问题。如果我按年龄比较,但如果他们的年龄相等,按金钱比较,我该怎么办。我该怎么做呢 @Tarık 我已经在我的答案中添加了上述两个查询的答案。看一看。如果有帮助,请接受答案。 非常感谢。我真的很感激。您的回答非常清楚且非常有用。【参考方案2】:

这样做的方法是使用多个比较器类。 Comparator 为我们提供了一种方法来定义我们希望我们的对象如何相互比较 - 在​​您的情况下,它可以是 id、age 等。

public class Comparator<Customer> CustomerAgeComparator implements Comparator<Customer>() 

    public int compare(Customer user1, Customer user2) 

        int userPoints1 = user1.getAge();
        int userPoints2 = user2.getAge();
        if (userPoints1 == userPoints2)
        return 0;
        else if (userPoints1 > userPoints2)
        return 1;
        else
        return -1;
    
 ;

上述比较器将按年龄降序对客户进行排序。 然后您需要以某种方式将此信息传递给您的优先队列。幸运的是,PriorityQueue 有一个构造函数可以做到这一点。调用方式如下:

PriorityQueue oldestCustomerFirst = PriorityQueue<String>(new CustomerAgeComparator);

【讨论】:

以上是关于用户定义对象的优先队列的主要内容,如果未能解决你的问题,请参考以下文章

用户定义类型的优先级队列

优先队列

(转加整理)优先队列

优先级队列与堆排序

STL容器之优先队列(转)

线性表栈队列和优先队列