1. 程式人生 > >優先順序佇列幾個應用詳解

優先順序佇列幾個應用詳解

優先順序佇列區別於普通佇列的一點是:優先順序佇列如果插入的節點是結構體型別,則要在結構體中過載比較操作符函式。示例程式碼如下:

//優先順序佇列的使用測試
//優先順序佇列跟對列的使用方式的區別是優先順序佇列在插入元素時
//在將元素插入隊尾後還要根據比較值對該元素進行位置的調整
#include<iostream>
#include<queue>
using namespace std;
struct Node
{
	int key;
	char ch;
	//只有<過載操作符函式時,如果將<改為>為什麼不行,出現error C2784的錯誤
	friend bool operator <(Node node1,Node node2)
	{
		//<為從大到小排列,>為從小到大排列
		return node1.key<node2.key;
	}
	friend bool operator >(Node node1,Node node2)
	{
		return node1.key<node2.key;
	}
};
int main()
{
	//對於優先佇列中包含結構體或者類的型別,該結構體或者類必須包含比較操作符的過載
	//因為優先順序佇列在插入時,是按照結構體中的某一個元素進行比較,如果
	//不過載比較操作符,優先順序佇列比較的是結構體,而我們知道結構體是無法直接進行比較的。
	//如下定義優先順序佇列qu,less表示按照遞減的順序插入元素,換成greater則表示按照遞增的
	//方式插入元素
	priority_queue<int,vector<int>,less<int>>qu;
	//定義如下的que優先順序佇列,會預設按照從大到小對插入元素進行排列
	//所以在沒有定義<時,會出現錯誤
	priority_queue<Node>que;
	priority_queue<Node,vector<Node>,less<Node>>qe;
	Node node[10];
	int i;
	int a[10]={4,2,1,3,6,8,7,9,10,5};
	char b[10]={'a','b','c','d','e','f','g','h','i','j'};
	//從小到大插入元素
	for(i=0;i<10;i++)
	{
		qu.push(a[i]);
	}
	for(i=0;i<10;i++)
	{
		cout<<qu.top()<<endl;
		qu.pop();
	}
	cout<<endl;
	//預設從大到小插入元素
	for(i=0;i<10;i++)
	{
		node[i].key=a[i];
		node[i].ch=b[i];
		que.push(node[i]);
	}
	for(i=0;i<10;i++)
	{
		cout<<que.top().key<<" "<<que.top().ch<<endl;
		que.pop();
	}
	cout<<endl;
	//利用了priority_queue<Node,vector<Node>,less<Node>>qe;這個定義後可以
	//將元素從大到小插入元素,但是注意的是結構體中必須過載<操作符,不然會出錯
	for(i=0;i<10;i++)
	{
		node[i].key=a[i];
		node[i].ch=b[i];
		qe.push(node[i]);
	}
	for(i=0;i<10;i++)
	{
		cout<<qe.top().key<<" "<<qe.top().ch<<endl;
		qe.pop();
	}
	return 0;
}


疑問解答:在編寫程式碼的時候,在只有一個過載操作符函式<時,我們將<改為>,que.push(node),出錯,錯誤代號是:C2784.後來發現原因是:我們如下定義的que,  priority_queue<Node>que;而預設的que插入是從大到小,所以在結構體中要過載<,如果我們將其<修gai為>則que的push函式找不到相應的操作符,就會出錯。

另外,如果我們想向優先順序佇列中插入指標元素時該怎麼辦?是不是將priority_queue<Node>que;改為priority_queue<Node*>que;就ok了?

不是!因為我們不能用結構體中過載的操作符對que中的元素進行比較,結構體中過載的操作符是類Node的操作符,而que中的是指標型別的Node節點,它與結構體中過載的操作符無法匹配。所以我們要另想辦法。

那我們將friend bool operator >(Node node1,Node node2)修改為friend bool operator >(Node* node1,Node* node2),也就是傳遞的是Node的指標行不行呢

答案是不可以,因為根據c++primer中過載操作符中講的“程式設計師只能為類型別或列舉型別的運算元定義過載操作符,在吧操作符宣告為類的成員是,至少有一個類或列舉型別的引數

按照值或者引用的方式傳遞”,也就是說friend bool operator >(Node* node1,Node* node2)形參中都是指標型別的是不可以的。我們可以如下解決此問題。

//在優先順序佇列中存入指標型別的節點
#include<iostream>
#include<queue>
using namespace std;
class Comapre;
class Node
{
private:
	friend Comapre;
	int key;
	char ch;
public:
	Node(int num,char c):key(num),ch(c){}
	bool lessthan (const Node* node) const
	{
		return key<node->key;
	}
	int GetKey()
	{
		return key;
	}
	char GetChar()
	{
		return ch;
	}
};
class Comapre
{
public:
	bool operator () (Node*node1,Node*node2)
	{
		return node1->lessthan(node2);
	}
};
int main()
{
	Node *n1=new Node(5,'c');
	Node *n2=new Node(4,'d');
	Node *n3=new Node(6,'e');
	priority_queue<Node*,vector<Node*>,Comapre>qu;
	qu.push(n1);
	qu.push(n2);
	qu.push(n3);
	int i;
	for(i=0;i<3;i++)
	{
		cout<<qu.top()->GetKey()<<" "<<qu.top()->GetChar()<<endl;
		qu.pop();
	}
	return 0;
}