C++中优先队列的基本使用(基本类型&自定义类型)

优先队列(priority_queue)定义在头文件< queue > 中,可以用来实现二叉堆(大顶堆、小顶堆),主要使用包括对于基本类型和自定义类型的排序,顶部元素(优先级最高/最低)访问,出队、入队等操作。

  1. 对于基本类型,可以修改默认排序规则,将大顶堆该为小顶堆。
  2. 对于自定义数据类型,可以创建操作符重载函数(重载<符号),或者自定义比较函数(重载()符号),用于自定义类型的比较操作。

接下来给出优先队列的基本使用:

test_01() : 使用int类型
test_02(): 使用string类型
test_03(): 使用自定义类型struct student

#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>

using namespace std;

// 优先队列:基本数据类型的使用 - int
void test_01()
{
	// 默认为大顶堆
	priority_queue<int> p1;
	p1.push(10);
	p1.push(-10);
	p1.push(100);

	cout << "p1 list 大顶堆(int): ";
	while (p1.size())
	{
		cout << p1.top() << " ";
		p1.pop();
	}
	cout << endl;

	// 改为小顶堆实现
	priority_queue<int, vector<int>, greater<int>> p2;
	p2.push(10);
	p2.push(-10);
	p2.push(100);

	cout << "p2 list 小顶堆(int): ";
	while (p2.size())
	{
		cout << p2.top() << " ";
		p2.pop();
	}
	cout << endl;
}

// 优先队列:基本数据类型的使用 - string
void test_02()
{
	// 默认为大顶堆: C B A
	priority_queue<string> p3;
	p3.push("A");
	p3.push("B");
	p3.push("C");

	cout << "p3 list 大顶堆(string): ";
	while (p3.size())
	{
		cout << p3.top() << " ";
		p3.pop();
	}
	cout << endl;

	// 改为小顶堆实现:A B C
	priority_queue<string, vector<string>, greater<string>> p4;
	p4.push("C");
	p4.push("B");
	p4.push("A");

	cout << "p4 list 小顶堆(string): ";
	while (p4.size())
	{
		cout << p4.top() << " ";
		p4.pop();
	}
	cout << endl;
}

// 优先队列:自定义数据类型的使用 - struct
struct student
{
	int score;
	string name;
	int student_number;

	// 重载 < 运算符,用于优先级比较, 以成绩来排名
	bool operator<(const student& s) const
	{
		return this->score < s.score;	// 大顶堆
	}

	student(int s, string n, int sn) :score(s),name(n),student_number(sn){}
};

// 自定义比较函数
struct student_compare_score_greater
{
	bool operator() (const student& a, const student& b)
	{
		return a.score > b.score;	// 小顶堆
	}
};

void test_03()
{
	student s1(89, "wang", 1001001);
	student s2(76, "Li", 1001721);
	student s3(100, "Zhao", 1001321);

	priority_queue<student> p5;
	p5.push(s1);
	p5.push(s2);
	p5.push(s3);

	cout << "p5 list 大顶堆(student): " << endl << endl;
	while (p5.size())
	{
		cout << p5.top().name << " " << p5.top().score << " " << p5.top().student_number << endl;;
		p5.pop();
	}
	cout << endl;

	// 改为成绩由低到高
	priority_queue<student, vector<student>, student_compare_score_greater> p6;
	p6.push(s1);
	p6.push(s2);
	p6.push(s3);

	cout << "p6 list 小顶堆(student): " << endl;
	while (p6.size())
	{
		cout << p6.top().name << "  " << p6.top().score << "  " << p6.top().student_number << endl;;
		p6.pop();
	}
	cout << endl;
}

int main()
{
	// int
	test_01();
	cout << endl;

	// string
	test_02();
	cout << endl;
	
	// struct
	test_03();

	return 0;
}

运行结果如下:

p1 list 大顶堆(int): 100 10 -10
p2 list 小顶堆(int): -10 10 100

p3 list 大顶堆(string): C B A
p4 list 小顶堆(string): A B C

p5 list 大顶堆(student):

Zhao 100 1001321
wang 89 1001001
Li 76 1001721

p6 list 小顶堆(student):
Li  76  1001721
wang  89  1001001
Zhao  100  1001321

谢谢阅读

### 使用自定义类型优先队列 为了使 `priority_queue` 支持自定义数据类型,需重载 `&lt;` 运算符或提供第三个模板参数作为比较函数对象。当仅存储基本类型的元素时,默认的大顶堆行为通常满足需求;然而对于复杂的数据结构,则需要指定排序逻辑。 #### 方法一:通过运算符重载实现 下面的例子展示了如何创建一个名为 `Person` 的类,并基于年龄属性构建最大堆: ```cpp #include &lt;iostream&gt; #include &lt;queue&gt; using namespace std; class Person { public: string name; int age; Person(string n=&quot;&quot;, int a=0):name(n),age(a){} // Overload the &#39;&lt;&#39; operator to compare by &#39;age&#39; bool operator&lt;(const Person&amp; p) const { return this-&gt;age &lt; p.age; } }; void showQueue(priority_queue&lt;Person&gt; q){ while (!q.empty()){ cout &lt;&lt; &quot;Name: &quot; &lt;&lt; q.top().name &lt;&lt; &quot;, Age:&quot; &lt;&lt; q.top().age &lt;&lt; endl; q.pop(); } } ``` 上述代码片段中,`operator&lt;()` 被重新定义以便按照成员变量 `age` 对象实例进行降序排列[^1]。 #### 方法二:利用仿函数(Functor) 如果不想修改原有类定义中的操作符,可以采用另一种方式&mdash;&mdash;即传入一个额外的比较器来决定顺序关系。这里展示了一个最小堆版本的人名列表案例: ```cpp // Define comparator as struct with () operator overloaded. struct CompareByName { inline bool operator() (const Person&amp; lhs, const Person&amp; rhs){ return lhs.name &gt; rhs.name; // For min heap based on names } }; ... priority_queue&lt;Person,vector&lt;Person&gt;,CompareByName&gt; pq_min_name; pq_min_name.push(Person(&quot;Alice&quot;, 28)); pq_min_name.push(Person(&quot;Bob&quot;, 35)); showQueue(pq_min_name); ``` 这段程序里引入了新的结构体 `CompareByName` 来充当比较准则,它会依据字符串字典序升序组织人员记录[^2]。 #### 完整示例综合应用两种方法 最后给出一段完整的测试代码,其中既包含了按年龄的最大堆也涵盖了依姓名字母表次序建立的小根堆: ```cpp int main(){ priority_queue&lt;Person&gt; pq_max_age; // Max Heap By Age pq_max_age.push(Person(&quot;Charlie&quot;, 47)); pq_max_age.push(Person(&quot;David&quot;, 61)); cout &lt;&lt; &quot;\nMax Heap Based On Ages:\n&quot;; showQueue(pq_max_age); priority_queue&lt;Person,vector&lt;Person&gt;,CompareByName&gt; pq_min_name; // Min Heap By Name pq_min_name.push(Person(&quot;Eve&quot;, 29)); pq_min_name.push(Person(&quot;Frank&quot;, 32)); cout &lt;&lt; &quot;\nMin Heap Based On Names:\n&quot;; showQueue(pq_min_name); return 0; } ``` 此段完整代码实现了两个不同规则下的优先级队列管理机制,分别用于处理不同类型的信息排序需求[^3]。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值