虽然堆排序算法是一个很漂亮的算法,但是在实际中,快排序的一个好的实现往往优于堆排序。尽管这样堆数据结构还有很大的用处,例如优先级队列。
3.1 最小堆
下面的程序就是按照《算法导论》最小堆的优先级队列的实现,修改几个小于号(大于号)可以轻易地将最小堆变成最大堆。
最小堆的一个用法实例是在Huffman编码中。
3.1.1 最小堆的优先级队列程序
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
#define maxNum 100000
#define MAX 0x7FFFFFFF
int minHeap[maxNum] = {0, 4, 1, 3, 2, 16, 9, 10, 14, 8, 7};
int heapSize;
void minHeapify(int i)
{
int l;
int r;
int min;
int temp;
l = i * 2;
r = i * 2 + 1;
min = i;
if((l <=heapSize)&&
(minHeap[l] < minHeap[min])){
min = l;
}
if((r <=heapSize)&&
(minHeap[r] < minHeap[min])){
min = r;
}
if(min !=i)
{
temp = minHeap[min];
minHeap[min] = minHeap[i];
minHeap[i] = temp;
minHeapify(min);
}
}
void buildMinHeap()
{
int i;
for(i =heapSize / 2; i > 0; i--){
minHeapify(i);
}
}
int heapExtractMin()
{
int min;
if(heapSize< 1)
{
return0;
}
min = minHeap[1];
minHeap[1] = minHeap[heapSize];
heapSize--;
minHeapify(1);
return min;
}
void heapIncreaseKey(int i, int key)
{
int temp;
if(key <minHeap[i])
{
cout << "newkey is smaller than current key" << endl;
}
minHeap[i] = key;
while(i> 1 && minHeap[i/2] > minHeap[i])
{
temp = minHeap[i];
minHeap[i] = minHeap[i/2];
minHeap[i/2] = temp;
i = i / 2;
}
}
void minHeapInsert(int key)
{
heapSize++;
minHeap[heapSize] = MAX;
heapIncreaseKey(heapSize, key);
}
int main()
{
int i;
heapSize = 10;
buildMinHeap();
}
3.2 最小堆实现优先队列
由于队列是不断地增删的,所以使用堆来实现优先队列是非常自然而令人愉快的事情。
3.2.1 实例
PKU JudgeOnline, 2312, Battle City.
3.2.2 问题描述
坦克大战中,一辆坦克可以在1步内走到一个没有东西的相邻位置。也可以在1步内打碎泥巴墙,但是不能打破铁墙,也不能过河。试问坦克从出发点到目的地的最少步数。
3.2.3 输入
34
YBEB
EERE
SSTE
00
3.2.4 输出
8
3.2.5 分析
这里很容易想到DFS算法。用DFS需要使用一个队列,该队列是标准的先进先出。但是这个题目的队列取要用优先级队列。优先级的级别和坦克初始出发点到该位置的距离成反比。故此优先队列可以用关于距离的最小堆来实现。
这里用到的方法实际上是代价一致搜索。
1.2.6 程序
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
#define maxNum 100000
#define MAX 0x7F7F7F7F
struct node{
int key;
int x;
int y;
};
nodeminHeap[maxNum];
int heapSize;
void minHeapify(int i)
{
int l;
int r;
int min;
node temp;
l = i * 2;
r = i * 2 + 1;
min = i;
if((l <=heapSize)&&
(minHeap[l].key < minHeap[min].key)){
min = l;
}
if((r <=heapSize)&&
(minHeap[r].key < minHeap[min].key)){
min = r;
}
if(min !=i)
{
temp = minHeap[min];
minHeap[min] = minHeap[i];
minHeap[i] = temp;
minHeapify(min);
}
}
void buildMinHeap()
{
int i;
for(i =heapSize / 2; i > 0; i--){
minHeapify(i);
}
}
nodeheapExtractMin()
{
node min;
if(heapSize< 1)
{
cout << "ERROR:no more" << endl;
}
min = minHeap[1];
minHeap[1] = minHeap[heapSize];
heapSize--;
minHeapify(1);
return min;
}
void heapIncreaseKey(int i, int key)
{
node temp;
if(key >minHeap[i].key)
{
cout << "ERROR:new key is smaller than current key" << endl;
}
minHeap[i].key = key;
while(i> 1 && minHeap[i/2].key > minHeap[i].key)
{
temp = minHeap[i];
minHeap[i] = minHeap[i/2];
minHeap[i/2] = temp;
i = i / 2;
}
}
void minHeapInsert(node temp)
{
heapSize++;
minHeap[heapSize] = temp;
minHeap[heapSize].key = MAX;
heapIncreaseKey(heapSize, temp.key);
}
#define EMPTY 'E'
#define RIVER 'R'
#define STEEL 'S'
#define TARGET 'T'
#define YOU 'Y'
#define BRICK 'B'
int adj[4][2] = {{0, -1}, {0, 1}, {-1, 0}, {1, 0}};
char map[302][302];
int calKey(int X, intY)
{
switch(map[X][Y]){
caseRIVER: return MAX;
caseSTEEL: return MAX;
caseBRICK: return 2;
caseEMPTY: return 1;
caseTARGET: return 1;
caseYOU: return 1;
default:return MAX;
}
return MAX;
}
int main()
{
int M;
int N;
int i;
int j;
int youX;
int youY;
inttargetX;
inttargetY;
int x;
int y;
intdistance;
node temp;
node insertNode;
boolvisited[302][302];
char c;
int min;
while(scanf("%d%d", &M, &N)){
if(M ==0 && N == 0)
{
break;
}
scanf("%c",&c);
memset(visited, 0, sizeof(visited));
memset(map, RIVER, sizeof(map));
for(i =1; i <= M; i++){
scanf("%s",&map[i][1]);
}
for(i =1; i <= M; i++){
for(j= 1; j <= N; j++){
if(map[i][j]== YOU){
youX = i;
youY = j;
}elseif(map[i][j] == TARGET){
targetX = i;
targetY = j;
}
}
}
heapSize = 0;
insertNode.key = 0;
insertNode.x = youX;
insertNode.y = youY;
minHeapInsert(insertNode);
min = MAX;
while(heapSize> 0){
temp = heapExtractMin();
if(temp.x== targetX&& temp.y == targetY)
{
min = temp.key;
break;
}
for(i= 0; i < 4; i++){
x = temp.x + adj[i][0];
y = temp.y + adj[i][1];
distance = calKey(x, y);
if((visited[x][y]== 0)&&
(distance != MAX))
{
visited[x][y] = 1;
insertNode.key = temp.key+ distance;
insertNode.x = x;
insertNode.y = y;
minHeapInsert(insertNode);
}
}
}
if(min!= MAX){
cout << min << endl;
}else{
cout << "-1" << endl;
}
}
return 1;
}
1.3 实例
PKU JudgeOnline, 2312, Battle City.
本文章欢迎转载,请保留原始博客链接http://blog.youkuaiyun.com/fsdev/article