高级数据结构——优先队列求n个最小和

1.优先队列的简介:

想必我们之前了解过了队列这个数据结构。利用队列的先进先出的性质,可以解决很多实际问题,但对于一些特殊的情况,队列是无法解决的。
例如,
我们在医院里,重症急诊患者肯定不能像普通患者那样依次排队就诊。这时候我们还是使用队列的先进先出的原则,那重症患者不就凉凉了,所以我们要使用一种更高级的数据结构——优先队列,先访问优先级高的元素。
优先队列的操作与普通队列差不多。但是相比于队列,优先队列里的元素增加了优先级的属性,优先级越高的元素先被删除。就像上面的重症患者一样,人家优先级高所以并不是插队。先删除在这里可以理解为先治疗。

2.Code 演示:

#include 
#include 
using namespace std;

priority_queue<int> q;  //声明一个装int类型数据的优先队列

int main() {
	for (int i = 1; i <= 10; i++) q.push(i);
	while (!q.empty()) {
		cout << q.top() << endl;
		q.pop();
	}
	return 0;
} 

运行这一段代码会发现输出的元素不像普通的queue中是1 2 3 4 5 6 7 8 9 10
而是倒序输出10 9 8 7 6 5 4 3 2 1
这是因为在你没有定义优先队列的优先级,对于整型,默认整型变量的值大的优先输出,你可以改一下自己输入便可以知道是否是这样了,至于其他数据类型的默认优先级你可以改一下,后面会介绍重载优先级。

3.优先队列的优先级重载:

优先队列,可以存放数值,也可以存放其他数据类型(包括自定义数据类型).该容器支持查询优先级最高的元素这一操作,而优先级的高低是可以自行定义的。
在C++中我们可以通过重载小于运算符bool operator < 来实现;
比如整数,程序默认是较大的元素优先级较高,我们也可以定义数值较小的元素优先级较高。又如下面的例子,在算法竞赛中经常出现,这里定义距离值较小的node优先级较高。
Code:

struct node {
    int dist, loc;
    node() { }
    bool operator < (const node & a) const {
        return dist > a.dist;
    }
};

priority_queue <node> Q;

为什么补重载大于号,因为重载大于号会编译错误,因为从数学的角度来说只需要重载小于号,即f1 > f2等价于f2 < f1,而f1 == f2等价于!(f1 < f2) && !(f2 < f1)

4.例题解析:

给出两个包含n个整数的数组A,B。在A、B中任意取出一个数并将两个数相加,可以得到n^2个和求这些和中最小的n个。

解析:
如果使用暴力法,依次在A和B中分别取出一个数,然后生成和值,最后排序以后取前面的n个和。这样的时间复杂度为n^2 * lgn。效率不是很高。

高级数据结构——优先队列求n个最小和_第1张图片
高级数据结构——优先队列求n个最小和_第2张图片

大概思想就是使用优先队列去维护这样一个堆,因为优先队列的本质就是堆实现的。

高级数据结构——优先队列求n个最小和_第3张图片
高级数据结构——优先队列求n个最小和_第4张图片
按照我们之前的思想,
所以我们可以:
读取 A B数组并排序
a.将 A[0] + B[0] 到 A[0] + B[n] 的和值加入优先队列中(此时优先队列中最小的值,肯定是所有和值里最小的)
b.开始出队,并入队和值的下一组,比如第一次出队的和值肯定是 A[0] + B[0],那么我们入队 A[1] + B[0] (A[1] + B[0] 和 A[0] + B[1] 接近 A[0] + B[0],而后者已经在优先队列中了)

AC Code:

#include
#include
#include
const int maxn = 5e4 + 5;
using namespace std;
struct node{
	int sum;
	int a;
	int b;
	bool operator<(const node &A)const{
		return sum > A.sum; 
	}
};

priority_queue<node> sum;
int a[maxn] ,b[maxn];

int main(){
	int n,t;
	node tmp;
	cin>>n;
	for(int i=0;i<n;i++){
		cin >> a[i];
	}
	sort(a, a + n);
	for(int i=0;i<n;i++){
		cin >> b[i];
	}
	sort(b, b + n);
	for(int i=0;i<n;i++){
		tmp.a = 0;
		tmp.b = i;
		tmp.sum = a[tmp.a] + b[tmp.b];
		sum.push(tmp);
	}
	for(int i=0;i<n;i++){
		tmp = sum.top();
		sum.pop();
		if(i == 0)
			cout<<tmp.sum;
		else
			cout<<" "<<tmp.sum;
		tmp.a++;
		tmp.sum = a[tmp.a] + b[tmp.b];
		sum.push(tmp);
	}
	return 0;
}

ly’s Blog

你可能感兴趣的:(C++,计蒜客,数据结构)