优先队列用法

本文详细介绍了 C++ 中 priority_queue 的基本使用方法,包括按照不同顺序进行排序的示例,以及如何处理结构体类型的元素。此外还讨论了如何自定义比较函数以支持指针类型的元素。

[转]priority_queue<int,vector<int>,greater<int>>优先队列 按照由小到大顺序,

C++优先队列的基本使用方法
 #include<iostream>
#include<functional>
#include<queue>
using namespace std;

struct node
{
    friend bool operator< (node n1, node n2)
    {
        return n1.priority < n2.priority;//"<"为从大到小排列,">"为从小打到排列
    }
    int priority;
    int value;
};

int main()
{
    const int len = 5;
    int i;
    int a[len] = {3,5,9,6,2};
    //示例1
    priority_queue<int> qi;//普通的优先级队列,按从大到小排序
    for(i = 0; i < len; i++)
        qi.push(a[i]);
    for(i = 0; i < len; i++)
    {
        cout<<qi.top()<<" ";
        qi.pop();
    }
    cout<<endl;

    //示例2
    priority_queue<int, vector<int>, greater<int> > qi2;//从小到大的优先级队列,可将greater改为less,即为从大到小
    for(i = 0; i < len; i++)
        qi2.push(a[i]);
    for(i = 0; i < len; i++)
    {
        cout<<qi2.top()<<" ";
        qi2.pop();
    }
    cout<<endl;

    //示例3
    priority_queue<node> qn;//必须要重载运算符
    node b[len];
    b[0].priority = 6; b[0].value = 1;
    b[1].priority = 9; b[1].value = 5;
    b[2].priority = 2; b[2].value = 3;
    b[3].priority = 8; b[3].value = 2;
    b[4].priority = 1; b[4].value = 4;
 
    for(i = 0; i < len; i++)
        qn.push(b[i]);
    cout<<"优先级"<<'\t'<<"值"<<endl;
    for(i = 0; i < len; i++)
    {
        cout<<qn.top().priority<<'\t'<<qn.top().value<<endl;
        qn.pop();
    }
    return 0;
}

对于队列里元素为一个结构体类型,按照某一个属性排序,就需要对比较函数进行重载

小结一下:

1、若是定义值类型对象,如: 

int 
 main() 
{      
    priority_queue<node> qn;

    node n1; 
    n1.a = 9; 
    node n2; 
    n2.a = 2; 
    node n3; 
    n3.a = 50;  

    qn.push(n1);

    qn.push(n2);

    qn.push(n3);

     int  size = qn.size();

     for ( int  i = 0; i < size; i++) 
    { 
        cout << qn.top().a << endl;

        qn.pop(); 
    } 
         return  0;


则定义优先级的时候,直接在类中写个friend 的操作符重载函数即可: 

class  node 

public : 
     int  a;

    node(){} 
    node( int  x):a(x){} 
friend   bool  operator<( const  node ne1, const  node ne2)//参数也可以为引用,值传递 
    { 
         if (ne1.a > ne2.a) 
        { 
             return   true ; 
        } 
         else 
        { 
             return   false ; 
        } 
    } 
}; 
其中在c++primer第三版 中文版中关于操作符重载有如下描述:

"程序员只能为类类型或枚举类型的操作数定义重载操作符我们可以这样来实现把重 
载操作符声明为类的成员或者声明为名字空间成员同时至少有一个类或枚举类型的参数 
按值传递或按引用传递"

因此不可用指针类型的参数;

2、如果想定义一个指针类型的优先队列,那就不可这么简单的定义了,你需要自定义一个自己的比较函数,在priority_queue的模板函数中,我们可以利用这样一个template<class _Ty, class _Container = vector<_Ty>, class _Pr = less<typename _Container::value_type> >模板,在我们的程序代码中,则需要自己定义一个类来定义第三个模板参数,如:

class  nodePointerComparer  
{  
public :  
    nodePointerComparer(){}  
     bool  operator ()( const  node* ne1,  const  node* ne2)  const   
    {  
         return  ne1->lessthan(ne2);  
    }  
};  

当然在这之前我们的类Node要重新书写 

class  node  
{  
public :  
     int  a;  
    node(){}  
    node( int  x):a(x){} 

     bool  lessthan( const  node* pnode)  const   
    {  
         return  a < pnode->a;  
    }  
};  
这样在main函数中就可以定义指针类型的优先队列了:

int  main()  
{  
    priority_queue <node*, vector <node*>, nodePointerComparer> qn;  
    node *n1 =  new  node(90);  
    node *n2 =  new  node(2);  
    node *n3 =  new  node(50); 

    qn.push(n1);  
    qn.push(n2); /span>


    qn.push(n3); 

     int  size = qn.size();  
     for ( int  i = 0; i < size; i++)  
    {  
        cout << qn.top()->a << endl;  
        qn.pop();  
    }  
     return  0; 

}  
疑问之处:如果你使用第一种值传递的操作符重载,来实现第二种的指针类型优先队列,是不会达到想要的结果的,个人理解是因为在指针类型的优先队列中找“<”运算符的时候,重载的不是我们写的值传递friend bool operator<(const node ne1,const node ne2)//

也就是没有找到指针类型的"<"重载,所有不会达到优先队列的效果。


### Java 优先队列 `PriorityQueue` 使用教程及示例 Java 中的 `PriorityQueue` 是一个基于堆(heap)实现的优先队列,默认情况下按照自然顺序进行排序。它常用于需要根据优先级处理任务或数据的场景,例如调度算法、图算法中的 Dijkstra 算法等。 #### 1. 创建与初始化 可以通过不同的构造方法创建 `PriorityQueue` 实例: - **默认构造函数**:使用默认容量(初始为 11),并按照自然顺序排序。 ```java PriorityQueue<Integer> queue = new PriorityQueue<>(); ``` - **指定初始容量**: ```java PriorityQueue<Integer> queue = new PriorityQueue<>(10); ``` - **自定义比较器**:通过提供 `Comparator` 来定义自定义排序规则。 ```java PriorityQueue<Integer> queue = new PriorityQueue<>((a, b) -> b - a); // 降序排列 ``` - **从集合中初始化**:可以将已有的 `SortedSet` 或其他集合转换为 `PriorityQueue` [^2]。 ```java SortedSet<Integer> sortedSet = new TreeSet<>(Arrays.asList(5, 3, 4, 1, 2)); PriorityQueue<Integer> queue = new PriorityQueue<>(sortedSet); ``` #### 2. 常用方法 | 方法名 | 描述 | |--------------|--------------------------------| | `add(E e)` | 将元素插入队列,若队列已满则抛出异常。 | | `offer(E e)` | 将元素插入队列,若队列已满则返回 `false`。 | | `poll()` | 获取并移除队列头部元素(优先级最高的)。 | | `peek()` | 获取但不移除队列头部元素。 | | `size()` | 返回队列中元素的数量。 | | `isEmpty()` | 判断队列是否为空。 | #### 3. 示例代码 以下是一个简单的 `PriorityQueue` 使用示例,展示了如何添加元素并按优先级取出: ```java import java.util.PriorityQueue; public class PriorityQueueExample { public static void main(String[] args) { PriorityQueue<Integer> queue = new PriorityQueue<>(); queue.add(5); queue.add(4); queue.add(3); queue.add(2); queue.add(1); while (!queue.isEmpty()) { System.out.println(queue.poll()); // 输出顺序为 1, 2, 3, 4, 5 } } } ``` 上述代码中,`PriorityQueue` 默认是小顶堆,因此最小的元素始终在队列头部被取出 [^3]。 #### 4. 自定义对象排序 当使用自定义类时,必须实现 `Comparable` 接口或提供 `Comparator`,否则会抛出 `ClassCastException` [^4]。 ```java class Customer implements Comparable<Customer> { private String name; private int priority; public Customer(String name, int priority) { this.name = name; this.priority = priority; } @Override public int compareTo(Customer other) { return Integer.compare(this.priority, other.priority); // 按优先级升序排列 } @Override public String toString() { return name + " (Priority: " + priority + ")"; } } // 使用示例 PriorityQueue<Customer> customerQueue = new PriorityQueue<>(); customerQueue.add(new Customer("Alice", 3)); customerQueue.add(new Customer("Bob", 1)); customerQueue.add(new Customer("Charlie", 2)); while (!customerQueue.isEmpty()) { System.out.println(customerQueue.poll()); } ``` 输出结果将是按照优先级从小到大排序的客户信息。 #### 5. 应用场景 - **任务调度**:操作系统中进程调度可使用优先队列实现。 - **事件驱动系统**:如模拟系统中事件按时间顺序处理。 - **图算法**:Dijkstra 算法中使用优先队列优化查找最短路径的过程。 - **合并多个有序流**:如归并多个排序好的输入流。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值