【队列 queue 与 优先队列 priority_queue】

队列 queue

------ 用法概括

· 实质:对于队列 queue a 数组,可以形象地看作 一个队列,而操作指令可以看作 排队的过程,始终遵循 先进先出 的原则

------ 指令概况

方法描述示例时间复杂度
push队尾入队q.push(x)O(1)
pop队首出队q.pop()O(1)
front返回队首元素q.front()O(1)
back返回队尾元素q.back()O(1)

优先队列 priority_queue

------ 用法概括

· 实质:可以看作 大根堆,对于较大的元素会被放在堆顶,实现 自动排序

priority_queue<int> q;
int main() {
    int x;
	for(int i=1; i<=5; i++) {
		scanf("%d",&x);
		q.push(x);
	}
	for(int i=1; i<=5; i++) {
		printf("%d ",q.top());
		q.pop();
	}
	return 0;
}

输入内容:5 -4 5 0 9
输出结果:9 5 5 0 -4

· 附加理解:priority_queue 优先队列将原本杂乱无章的序列 S:4 2 5 1 3,通过 “<” 运算符将较大元素放在堆顶,自动排序得到新序列 S’:1<2<3<4<5,此时 5 为堆顶元素 (认真体会对重载运算符原理理解更深)

------ 指令概括

方法描述示例时间复杂度
push把元素插入堆q.push(x)O(1)
pop删除堆顶元素q.pop()O(1)
top返回堆顶元素(最大值)q.top()O(1)

------ priority_queue 实现小根堆

· 引:已知 priority_queue 是将 较大元素 放在堆顶,那应如何将 较小元素 放入堆顶,即小根堆:

1. 把 插入元素 取相反数,取出堆顶元素(最大值)时,再次把其取相反数,从而得到原来的元素。
由于相反数的性质,插入原元素的相反数后(设为新元素)
此时优先队列堆顶为 最大新元素(即最小原元素),此时的堆顶为 最小原元素(堆顶新元素取反后)

2. 我们可以直接声明 “大根堆”与“小根堆”,以 int 类型为例

priority_queue<int,vector<int>,greater<int> > q; //小根堆,堆顶元素最小 
priority_queue<int,vector<int>,less<int> > p;  //大根堆,堆顶元素最大 

注:此处 “>” 符号不能相连,否则会被系统当作 位移运算符,直接报错

------ 重载运算符

· 实质:在 priority_queue 中储存的元素按照 从大到小 排序,内部实现就是依靠 “<” 运算符,则较大值会被放在堆顶
内置的 int和string 类型本身就可以比较大小,对于自定义的结构体,则需要重载 “<” 运算符的比较方式

bool operator 重载运算符 (const 自定义结构体类型 &a,const 自定义结构体类型 &b) {
return 重载运算符比较的规则 ; }

struct node { 
	int id;
	double x;
}a[10];
priority_queue<node> q;
bool operator <(const node &a,const node &b) { /*注意上文的附加理解
此时 "<" 运算符将 浮点型 x较大的元素 放在堆顶*/
	return a.x>b.x; //关于浮点型比大小,会出现精度误差,此处省略(偷懒)  
}
int main() {
	for(int i=1; i<=5; i++) {
		scanf("%lf",&a[i].x);
		a[i].id=i; 
		q.push(a[i]);
	}
	for(int i=1; i<=5; i++) {
		printf("%d ",q.top().id);
		q.pop();
	} 
	return 0;
}

输入内容:
0.1
0.01
5.2
5.4
0.1
输出结果:4 3 1 5 2

· 附加:对于 C++ 内置的二元组 pair < 结构类型 > (make_pair 函数创建二元组,成员变量 first 访问第一元,second 访问第二元) 在优先队列中比较大小时,以第一元为第一关键字,第二元为第二关键字

部分 大部分 绝大部分 摘抄于《算法进阶》(一本好书)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值