实用算法实现-第 11 篇 贪心算法

11.1 Huffman编码

Huffman设计了一个可以用来构造一种称为Huffman编码的最优前缀码的贪心算法。

11.1.1实例

PKU JudgeOnline, 1521, Entropy.

11.1.2问题描述

给定一组ASCII码组成的字符串,求用Huffman编码该字符串所需的长度,及采用该编码带来的压缩比。

11.1.3输入

AAAAABCD

THE_CAT_IN_THE_HAT

END

11.1.4输出

6413 4.9

144 51 2.8

11.1.5分析

采用贪心算法,使用最小堆就可以实现Huffman树的构建。为了便于计算每种字符对应的码的长度,用update()维护depth数组。如果需要求出每种字符对应的编码,只需要进一步增强update()函数即可。

注意:对于只有同一种字符的字符串要特殊处理。

11.1.6程序

#include <iostream> #include <stdio.h> #include <string.h> using namespace std; #define maxNum ('_' - 'A' + 1) #define MAX 0x7F7F7F7F struct node{ int key; int pos; }; 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); } int f[maxNum + maxNum]; int huffmanLeft[maxNum + maxNum]; int huffmanRight[maxNum + maxNum]; int depth[maxNum]; int huffmanTop; void update(int x) { if(x <0) { return; } if(x <maxNum){ depth[x]++; return; } update(huffmanLeft[x]); update(huffmanRight[x]); } int huffman() { node x; node y; node z; huffmanTop = maxNum; while(heapSize> 1){ x = heapExtractMin(); y = heapExtractMin(); z.pos = huffmanTop; huffmanLeft[z.pos] = x.pos; huffmanRight[z.pos] = y.pos; z.key = x.key + y.key; f[z.pos] = f[x.pos] + f[y.pos]; minHeapInsert(z); update(x.pos); update(y.pos); huffmanTop++; } z = heapExtractMin(); if(z.pos !=huffmanTop - 1) { int *a= (int *)0; *a = 0; printf("error\n"); } returnz.pos; } int main() { charstr[10000]; int pos; int length; int sum; int i; int n; while(scanf("%s", str)){ if(strcmp("END", str) == 0) { break; } memset(f, 0, sizeof(f)); memset(minHeap, 0, sizeof(minHeap)); length = strlen(str); n = 0; for(i =0; i < length; i++){ pos = str[i] - 'A'; if(f[pos]== 0) { n++; } f[pos]++; } pos = 1; for(i =0; i < maxNum; i++){ if(f[i]!= 0){ minHeap[pos].key = f[i]; minHeap[pos].pos = i; pos++; } } if(n> 1){ heapSize = n; buildMinHeap(); memset(huffmanLeft, 0xff, sizeof(huffmanLeft)); memset(huffmanRight, 0xff, sizeof(huffmanRight)); memset(depth, 0, sizeof(depth)); huffman(); sum = 0; for(i= 0; i < maxNum; i++){ sum += depth[i] * f[i]; } }else{ sum = length; } length = length * 8; printf("%d%d %.1f\n", length, sum, (double)length/ sum); } }
本文章欢迎转载,请保留原始博客链接http://blog.csdn.net/fsdev/article

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值