#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
using namespace std; struct Node {
char character;
unsigned int weight;
unsigned int parent;
unsigned int lchild;
unsigned int rchild;
}; Node *HT = NULL;
char **HC = NULL;
int n = ; void CreatHuffmanTree(void);
void CodeHuffman(void);
void Encode(void);
void Decode(void);
void Free(void);
void Select(const int len, int &a, int &b);
int Search(const char &key); int main(void)
{
freopen("cin.txt", "r", stdin);
freopen("cout.txt", "w", stdout);
while (cout << "请输入字符个数:\n", cin >> n) { // n>=2
getchar(); // 吸收回车,防止空格字符的输入异常 CreatHuffmanTree(); // 建哈夫曼树 CodeHuffman(); // 为每个字符编码 Encode(); // 为明文编码 Decode(); // 从密文译码 Free(); // 释放动态分配的空间
}
system("pause");// 有用?
return ;
} void CreatHuffmanTree(void)
{
// weight存放n个字符的权值(均>0),构造哈夫曼树HT,
// 并求出n个字符的哈夫曼编码HC
if (n <= )
return;
int m = * n - ; HT = (Node *)malloc((m + ) * sizeof(Node)); // 0号单元未用
if( HT == NULL) {
cerr << "Allocate failed!" << endl;
exit(OVERFLOW);
}
memset(HT, , (m + ) * sizeof(Node)); cout << "请输入各字符及其权值:" << endl;
for (int i = ; i <= n; i++) {
HT[i].character = getchar();
cin >> HT[i].weight; // 输入字符及权值的信息
getchar();
}
cout << n << "个字符及其权值:" << endl;
for (int i = ; i <= n; i++) {
printf("%c(%3d) ", HT[i].character, HT[i].weight);
if (i % == )
cout << endl;
}
cout << endl; /* printf("\n哈夫曼树的构造过程如下所示:\n");
printf("HT初态:\n 结点 weight parent lchild rchild");
for (int i = 1; i <= m; i++)
printf("\n%4d%8d%8d%8d%8d", i, HT[i].weight, HT[i].parent, HT[i].lchild, HT[i].rchild);
printf(" 按回车键,继续 ...");
// getchar();*/ for (int i = n + ; i <= m; i++) {
// 在HT[1..i-1]中选择parent为0且weight最小的两个结点,
// 其序号分别为s1和s2。
int s1();
int s2();
Select(i - , s1, s2);
HT[s1].parent = i;
HT[s2].parent = i;
HT[i].lchild = s1;
HT[i].rchild = s2;
HT[i].weight = HT[s1].weight + HT[s2].weight; /* printf("\nselect: s1=%d s2=%d\n\n", s1, s2);
printf(" 结点 weight parent lchild rchild");
for (int j = 1; j <= i; j++)
printf("\n%4d%8d%8d%8d%8d", j, HT[j].weight, HT[j].parent, HT[j].lchild, HT[j].rchild);
printf(" 按回车键,继续 ...");
// getchar();*/
}
} void CodeHuffman(void)
{
//--- 从叶子到根逆向求每个字符的哈夫曼编码 ---
HC = (char **)malloc((n + ) * sizeof(char *)); // 指针数组
if (HC == NULL) {
cerr << "Allocate failed!" << endl;
exit(OVERFLOW);
}
memset(HC, , (n + ) * sizeof(char *)); // 0号单元未用 char *cd = (char *)malloc(n * sizeof(char)); // 分配求编码的工作空间
if (cd == NULL) {
cerr << "Allocate failed!" << endl;
exit(OVERFLOW);
}
memset(cd, , n * sizeof(char)); // 编码结束符。 for (int i = ; i <= n; ++i) { // 逐个字符求哈夫曼编码
int start = n - ; // 编码结束符位置
unsigned int c();
unsigned int f();
for (c = i, f = HT[i].parent; f != ; c = f, f = HT[f].parent) {
if (HT[f].lchild == c) // 从叶子到根逆向求编码
cd[--start] = '';
else
cd[--start] = '';
} HC[i] = (char *)malloc((n - start) * sizeof(char)); // 为第i个字符编码分配空间
if (HC[i] == NULL) {
cerr << "Allocate failed!" << endl;
exit(OVERFLOW);
} strcpy(HC[i], &cd[start]); // 从cd复制编码(串)到HC
}
free(cd);
cd = NULL; printf("\n\n各字符的哈夫曼编码如下:\n");
for(int i = ; i <= n; i++) {
printf("%c(%3d): %s\n" ,HT[i].character, HT[i].weight, HC[i]);
}
} void Encode(void)
{
cout << "请输入报文:" << endl;
string str;
getline(cin, str);
for (unsigned int i = ; i < str.size(); i++) {
int loc = Search(str[i]);
cout << HC[loc] << endl;
}
cout << endl;
} void Decode(void)
{
cout << "请输入密文:" << endl;
string str;
cin >> str;
for (unsigned int i = ; i < str.size();) {
int cursor = * n - ;
while (HT[cursor].lchild != && HT[cursor].rchild != ) { // 全非0
switch (str[i++]) { case '':
cursor = HT[cursor].lchild;
break; case '':
cursor = HT[cursor].rchild;
break; default:
cerr << "Input error!" << endl;
exit ();
}
}
if (!(HT[cursor].lchild == && HT[cursor].rchild == )) { // 此时应是全0
cerr << "Input error!" << endl;
exit ();
}
cout << HT[cursor].character << endl;
}
} void Free(void)
{
free(HT); // 释放动态分配的空间
HT = NULL;
for(int i = ; i <= n; i++) {
free(HC[i]);
HC[i] = NULL;
}
free(HC);
HC = NULL;
} void Select(const int len, int &a, int &b)
{
// 在HT[1..len]中选择parent为0且weight最小的两个结点,
// 其序号分别为a和b。
for (int i = ; i <= len; i++) {
if (HT[i].parent == ) {
a = i;
break;
}
}
for (int i = a + ; i <= len; i++) {
if (HT[i].parent == ) {
b = i;
break;
}
}
if (HT[a].weight > HT[b].weight) // 保持a的始终小于b的,有序
swap(a, b);
for (int i = max(a, b) + ; i <= len; i++) {
if (HT[i].parent == ) {
if (HT[i].weight > HT[b].weight)
continue;
else if (HT[i].weight < HT[a].weight) {
b = a;
a = i;
}
else
b = i;
}
}
if ( !(HT[a].parent == && HT[b].parent == ) ) {
cerr << "Error!" << endl;
exit();
}
} int Search(const char &key) // 找到key在HT中的下标,找不到则返回0
{
HT[].character = key; // 哨兵,顺序查找
int i;
for (i = n; HT[i].character != key; --i);
if (i == ) {
cerr << "Inexistence!" << endl;
exit();
}
return i;
} /*
cin.txt:
27
186
a 64
b 13
c 22
d 32
e 103
f 21
g 15
h 47
i 57
j 1
k 5
l 32
m 20
n 57
o 63
p 15
q 1
r 48
s 51
t 80
u 23
v 8
w 18
x 1
y 16
z 1
this program is my favorite
*/

输出:

请输入字符个数:
请输入各字符及其权值:
27个字符及其权值:
(186) a( 64) b( 13) c( 22) d( 32) e(103) f( 21) g( 15) h( 47) i( 57)
j( 1) k( 5) l( 32) m( 20) n( 57) o( 63) p( 15) q( 1) r( 48) s( 51)
t( 80) u( 23) v( 8) w( 18) x( 1) y( 16) z( 1)

各字符的哈夫曼编码如下:
(186): 111
a( 64): 1010
b( 13): 100000
c( 22): 00000
d( 32): 10110
e(103): 010
f( 21): 110011
g( 15): 100010
h( 47): 0001
i( 57): 0110
j( 1): 1100001000
k( 5): 11000011
l( 32): 10111
m( 20): 110010
n( 57): 0111
o( 63): 1001
p( 15): 100001
q( 1): 1100001010
r( 48): 0010
s( 51): 0011
t( 80): 1101
u( 23): 00001
v( 8): 1100000
w( 18): 110001
x( 1): 1100001011
y( 16): 100011
z( 1): 1100001001
请输入报文:
1101
0001
0110
0011
111
100001
0010
1001
100010
0010
1010
110010
111
0110
0011
111
110010
100011
111
110011
1010
1100000
1001
0010
0110
1101
010

请输入密文:
请按任意键继续. . .
请输入字符个数:

考研机试题

 /**************************************
created: 2014/03/14
filename: 13_07_huffman.cpp
purpose: Huffman encode
**************************************/ #pragma warning(disable: 4786)
#include <iostream>
#include <queue>
#include <string>
#include <cmath>
#include <map>
#include <cassert>
using namespace std; struct Node {
double weight;
Node *left;
Node *right;
int num; // 记录输入时的次序,为了按输入顺序输出 Node(double w = 0.0, int n = -) : weight(w), left(NULL), right(NULL), num(n) {} bool is_leaf() const {
return NULL == left && NULL == right;
}
}; struct Cmp {
bool operator()(Node *a, Node *b) const {
return a->weight > b->weight;
}
}; /*
** 使两个结点成为兄弟,返回他们的父亲的地址
*/
Node * conjoin(Node *left, Node *right) {
Node *father = new Node(left->weight + right->weight); // 这里产生的结点都是分支结点
father->left = left;
father->right = right; return father;
} /*
** 根据优先队列建 Huffman 树
*/
Node * create_tree(priority_queue<Node *, vector<Node *>, Cmp> &Q) {
while ( != Q.size()) {
Node *left = Q.top();
Q.pop();
Node *right = Q.top();
Q.pop();
Q.push(conjoin(left, right));
}
Node *tree = Q.top();
Q.pop(); return tree;
} /*
** 前序遍历 Huffman 树得到叶子的编码存储在 code_map 中
*/
void get_code(Node const *const tree, const string str, map<int, string> &code_map) {
if (NULL == tree) {
return ;
}
if (tree->is_leaf()) {
code_map[tree->num] = str;
return ;
}
get_code(tree->left, str + "", code_map);
get_code(tree->right, str + "", code_map);
} /*
** 后序遍历释放树
*/
void free_tree(Node *&tree) {
if (NULL == tree) {
return ;
} free(tree->left);
free(tree->right);
delete tree;
tree = NULL;
} int main(int argc, char **argv) {
FILE *in_stream = freopen("7.in", "r", stdin);
if (NULL == in_stream) {
cerr << "Can not open file." << endl;
exit();
}
FILE *out_stream = freopen("7.out", "w", stdout); priority_queue<Node *, vector<Node *>, Cmp> Q;
double elem;
int n;
cin >> n;
int i;
for (i = ; i < n; ++i) {
cin >> elem;
Q.push(new Node(elem, i));
} Node *tree = create_tree(Q); // 根据输入数据建 Huffman 树
assert(Q.empty());
map<int, string> code_map;
get_code(tree, string(), code_map); // 根据 Huffman 树获取 Huffman 编码 for (i = ; i < n; ++i) {
cout << code_map[i] << endl;
} free_tree(tree); fclose(in_stream);
fclose(out_stream); return ;
} /* 7.in
4
0.3 0.1 0.4 0.2
*/

Huffman编码的更多相关文章

  1. [老文章搬家] 关于 Huffman 编码

    按:去年接手一个项目,涉及到一个一个叫做Mxpeg的非主流视频编码格式,编解码器是厂商以源代码形式提供的,但是可能代码写的不算健壮,以至于我们tcp直连设备很正常,但是经过一个UDP数据分发服务器之后 ...

  2. 【数据压缩】Huffman编码

    1. 压缩编码概述 数据压缩在日常生活极为常见,平常所用到jpg.mp3均采用数据压缩(采用Huffman编码)以减少占用空间.编码\(C\)是指从字符空间\(A\)到码字表\(X\)的映射.数据压缩 ...

  3. 优先队列求解Huffman编码 c++

    优先队列小析      优先队列的模板: template <class T, class Container = vector<T>,class Compare = less< ...

  4. Huffman编码实现电文的转码与译码

    //first thing:thanks to my teacher---chenrong      Dalian Maritime university /* 构造Huffman Tree思路: ( ...

  5. huffman 编码

    huffman压缩是一种压缩算法,其中经典的部分就是根据字符出现的频率建立huffman树,然后根据huffman树的构建结果标示每个字符.huffman编码也称为前缀编码,就是每个字符的表示形式不是 ...

  6. 基于二叉树和数组实现限制长度的最优Huffman编码

    具体介绍详见上篇博客:基于二叉树和双向链表实现限制长度的最优Huffman编码 基于数组和基于链表的实现方式在效率上有明显区别: 编码256个符号,符号权重为1...256,限制长度为16,循环编码1 ...

  7. uvalive 2088 - Entropy(huffman编码)

    题目连接:2088 - Entropy 题目大意:给出一个字符串, 包括A~Z和_, 现在要根据字符出现的频率为他们进行编码,要求编码后字节最小, 然后输出字符均为8字节表示时的总字节数, 以及最小的 ...

  8. Jcompress: 一款基于huffman编码和最小堆的压缩、解压缩小程序

    前言 最近基于huffman编码和最小堆排序算法实现了一个压缩.解压缩的小程序.其源代码已经上传到github上面: Jcompress下载地址 .在本人的github上面有一个叫Utility的re ...

  9. DS二叉树--Huffman编码与解码

    题目描述 1.问题描述 给定n个字符及其对应的权值,构造Huffman树,并进行huffman编码和译(解)码. 构造Huffman树时,要求左子树根的权值小于.等于右子树根的权值. 进行Huffma ...

随机推荐

  1. Java的常用对象①②

    Java的常用对象① Java的常用对象有很多,这里只对lang包中常用的Object,Date(Calendar,DateFormat,Math),System,Runtime进行介绍.㈠Objec ...

  2. autoit小贴士

    如何防止程序重复运行? #include <Misc.au3>_Singleton("test") 如何删除脚本程序自身? ;删除脚本程序自身 Run(@ComSpec ...

  3. JS-为金额添加千分位逗号分割符

    前言:这个功能在前端页面中使用的还是比较多的,正好我们的项目中也有使用此功能,不过YY同学写的代码不像个方法的样子,一个入口中间又插了几道子,所             以,我写了下面这个方法,经过测 ...

  4. onethink入门笔记(一)

    由于公司需求所以大概花了一个星期搞了一个一个基于onethink的数据管理平台demo不得不说onethink这个基于thinkphp3.2.3的框架还是很棒的 让我这个没基础过php的人也能在一星期 ...

  5. javaScript 相关笔记

    1.js中对象复制 思路:将js对象先转成json字符串,然后再将json字符串转换为两个对象

  6. CentOS6上无法启动NFS服务

    CentOS6上无法启动NFS服务 1.系统环境 物理机:Windows 7(32位)旗舰版 虚拟机:CentOS 6.5 2.问题描述 安装好nfs应用程序之后,打算启动nfs服务,却出现以下的报错 ...

  7. Electronic Payment App analysis

    Electronic Payment App is getting more and more popular now. People don't have to bring credit cards ...

  8. 25. vm安装redhat步骤

    详见:http://jingyan.baidu.com/article/49ad8bce532c525834d8fa19.html

  9. rt—移植笔记1

    将rtt源码往stm32f407移植的时候,源码串口打印引脚设置有误,以下是源码引脚配置. 以下是原理图 可见配置有误.

  10. 高可用Hadoop平台-Flume NG实战图解篇

    1.概述 今天补充一篇关于Flume的博客,前面在讲解高可用的Hadoop平台的时候遗漏了这篇,本篇博客为大家讲述以下内容: Flume NG简述 单点Flume NG搭建.运行 高可用Flume N ...