优先队列和堆 实战:HDU1242
2016-03-20 14:20
190 查看
什么叫优先队列呢,能完成以下任务的就叫做优先队列:
·插入一个数值
·取出最小的数值(获取数值,并且删除)
实现优先队列,应该使用二叉树完成,是一种叫二叉堆的数据结构(binary heap)
二叉堆分为两种,最小堆和最大堆。最小堆是父节点的键值总是小于等于子节点的键值。最大堆是父节点的键值总是大于等于子节点的键值。
可以将二叉堆看成数组的形式。
代码:
但是在c++的STL中已经包含了优先队列的高效实现——priority_queue,不过与上面的例子不一样的是每次取出数值都是最大值。
看一个简单的实例:
用杭电的一题来实战一下吧
题目点击打开链接
题目的意思是和走迷宫找最短出口差不多,就是有一个天使(在地图上显示为a),你是天使的好基友(在地图上显示为r),为了拯救基友,你打算去劫狱,.代表路, #代表墙壁。每走一步就要花一个时间单位。监狱里当然会有很多狱警(在地图上显示为x)啦,但是基情使你充满力量,轻轻松松能杀死一个狱警,也只要一个时间单位好了。现在你要怎么做才能在最短的时间内救出好基友。
=_=
这题很明显就是使用BFS来做的。因为里面多了一个狱警,所以用队列的话就比较麻烦了,所以在这里使用优先队列。
因为优先队列默认是取出最大值的,所以首先要重载一下运算符,让优先取出最小值。
ac代码如下:
·插入一个数值
·取出最小的数值(获取数值,并且删除)
实现优先队列,应该使用二叉树完成,是一种叫二叉堆的数据结构(binary heap)
二叉堆分为两种,最小堆和最大堆。最小堆是父节点的键值总是小于等于子节点的键值。最大堆是父节点的键值总是大于等于子节点的键值。
可以将二叉堆看成数组的形式。
代码:
// 模拟最小堆 // 最小堆是二叉堆的一种,其特点是父节点的键值总是小于或者等于子节点。 // 实现细节: // push:向堆中插入数据时,首先在堆的末尾插入数据,然后不断向上提升,直到没有大小颠倒时。 // pop:从堆中删除最小值时首先把最后一个值复制到根节点上,并且删除最后一个数值。然后不断向下交换 // 直到没有大小颠倒为止。在向下交换过程中,如果有两个子儿子都小于自己,就选择较小的 #include <iostream> using namespace std; const int MAX_N = 1005; int heap[MAX_N], sz = 0; void push(int x); void display(); int pop(); int main() { // 测试 int x; int cmd; do { cout << "请输入命令:1.push\t2.pop\t3.display\t0.quit\n"; cin >> cmd; switch(cmd) { case 1: cout << "Input X:"; cin >> x; push(x); break; case 2: x = pop(); cout << x << "已取出!\n"; break; case 3: display(); break; } }while(cmd); return 0; } void push(int x) { // i是要插入节点的下标 int i = sz++; while(i > 0) { // p为父亲节点的下标 int p = (i - 1) / 2; // 如果父亲节点小于等于插入的值,则说明大小没有跌倒,可以退出 if(heap[p] <= x) break; // 互换当前父亲节点与要插入的值 heap[i] = heap[p]; i = p; } heap[i] = x; cout << "数据插入成功!\n"; } int pop() { // 取出根节点 int ret = heap[0]; // 将最后一个节点的值提到根节点上 int x = heap[--sz]; int i = 0; while(i * 2 + 1 < sz) { // a,b为左右两个子节点的下标 int a = 2 * i + 1, b = 2 * i + 2; // 去两个子节点中较小的值 if(b < sz && heap[b] < heap[a]) a = b; // 如果已经没有大小颠倒的话则退出循环 if(heap[a] >= x) break; // 将父亲节点与子节点互换 heap[i] = heap[a]; i = a; } heap[i] = x; return ret; } void display() { for(int i = 0; i < sz; i++) cout << heap[i] << "\t"; cout << endl; }
但是在c++的STL中已经包含了优先队列的高效实现——priority_queue,不过与上面的例子不一样的是每次取出数值都是最大值。
看一个简单的实例:
#include <iostream> #include <queue> using namespace std; int main() { // 声明 priority_queue<int> pque; // 插入元素 pque.push(3); pque.push(5); pque.push(1); // 不断循环直到为空为止 while(!pque.empty()) { // 获得最大值并且删除 cout << pque.top() << endl; pque.pop(); } return 0; }
用杭电的一题来实战一下吧
题目点击打开链接
题目的意思是和走迷宫找最短出口差不多,就是有一个天使(在地图上显示为a),你是天使的好基友(在地图上显示为r),为了拯救基友,你打算去劫狱,.代表路, #代表墙壁。每走一步就要花一个时间单位。监狱里当然会有很多狱警(在地图上显示为x)啦,但是基情使你充满力量,轻轻松松能杀死一个狱警,也只要一个时间单位好了。现在你要怎么做才能在最短的时间内救出好基友。
=_=
这题很明显就是使用BFS来做的。因为里面多了一个狱警,所以用队列的话就比较麻烦了,所以在这里使用优先队列。
因为优先队列默认是取出最大值的,所以首先要重载一下运算符,让优先取出最小值。
ac代码如下:
#include <iostream> #include <queue> #include <string> using namespace std; const string fail = "Poor ANGEL has to stay in the prison all his life."; const int INF = 1000005; const int MAX_N = 205; int N, M; int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1}; char pic[MAX_N][MAX_N]; struct Node { int x, y; int num; // 将优先队列每次取出最大值改为每次去最小值 bool operator < (const Node &a) const { return num > a.num; } }first, next; int bfs(); int main() { while(cin >> N >> M) { int i, j; for(i = 0; i < N; i++) { cin >> pic[i]; for(j = 0; j < M; j++) { if(pic[i][j] == 'a') { first.x = i; first.y = j; first.num = 0; pic[i][j] = '#'; } } } int ans = bfs(); if(ans == INF) cout << fail << endl; else cout << ans << endl; } return 0; } int bfs() { priority_queue<Node> que; que.push(first); while(que.size()) { first = que.top(); que.pop(); for(int i = 0; i < 4; i++ ) { next.x = first.x + dx[i]; next.y = first.y + dy[i]; if(next.x >= 0 && next.x < N && next.y >=0 && next.y < M && pic[next.x][next.y] != '#') { next.num = first.num; if(pic[next.x][next.y] == 'r') return next.num + 1; else if(pic[next.x][next.y] == '.') next.num += 1; else if(pic[next.x][next.y] == 'x') next.num += 2; pic[next.x][next.y] = '#'; que.push(next); } } } return INF; }
相关文章推荐
- CentOS-7下安装MySQL5.6.22
- socketlog
- 字符输入函数在屏幕的显示
- iOS runtime
- ICPCCamp2016day8 I Robots 【最短路】
- Python 2.x vs 3.x
- 《Linux内核设计与实现》第1、2章读书笔记
- 百练2973:Skew数
- MYSQL to_days(date)用法
- 最小生成树之MST性质
- 实现Linux命令行上传和下载百度云盘
- lintcode-medium-Find Minimum in Rotated Sorted Array
- Python学习笔记
- iOS中头条新闻滑动效果
- Python 05 自定义函数的创建、调用和函数
- (未写完)Zookeeper学习(六):利用Zookeeper实现配置管理
- Android 坐标系统详解
- 第三周学习进度表
- 大整数模板
- Shell 文件包含