实用算法实践-第 3 篇 堆排序

虽然堆排序算法是一个很漂亮的算法,但是在实际中,快排序的一个好的实现往往优于堆排序。尽管这样堆数据结构还有很大的用处,例如优先级队列。

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值