Huffman编码算法可用于文字压缩或加密解密
采用C++语言给出其高效实现,读者可思考实现算法中指针用法和树的构建过程
代码如下:
//Huffman algorithm demo
//本算法主要掌握树的构建过程,尤其,掌握指针的使用方法
//author: Liping chen
//email: alaclp@qq.com
//published date: 2015-4-7
#include <iostream>
#include <string>
using namespace std;
//定义树类型————认为最小的树是一个节点
typedef struct Tree {
int val;
int times;
Tree *left, *right, *parent, *next; //如果使用了next,则认为是森林
//构造函数
Tree() : val(-1), times(0), left(NULL), right(NULL), parent(NULL), next(NULL) {}
Tree(int val, int times) : val(val), times(times), left(NULL), right(NULL),
parent(NULL), next(NULL) {}
//递归输出树的叶子节点
void output() {
Tree *ptr = this;
string info;
//根节点,输出总信息
if (parent == NULL) cout << "Huffman编码方案:" << endl;
if (val != -1) { //叶子节点
while(ptr->parent) {
info += (ptr->parent->left == ptr) ? "0":"1";
ptr = ptr->parent;
}
cout << (char)val << "[" << times << "]=" << info << endl;
}
else { //非叶子节点
if (left) left->output();
if (right) right->output();
}
}
//析构函数
~Tree() {
if (left) delete left;
if (right) delete right;
//cout << "delete :" << val << "(times: " << times << ")" << endl;
}
} Tree;
//定义森林类或多棵树的类
typedef struct Trees {
Tree *head, *tail; //头树,尾树指针
//向森林里添加树
void addTree(Tree *tree) {
if (head == NULL) {
head = tail = tree;
return;
}
Tree *ptr = head, *last = NULL;
bool inserted = false;
while(ptr) {
if (ptr->times > tree->times) {
if (last == NULL) {
tree->next = head;
//tail = head;
head = tree;
}
else {
last->next = tree;
tree->next = ptr;
}
inserted = true;
break;
}
last = ptr;
ptr = ptr->next;
}
if (!inserted) {
last->next = tree;
tail = tree;
tree->next = NULL;
}
}
//构造函数——利用字母和其统计次数,构造森林
Trees(int vals[], int times[], int n) : head(NULL), tail(NULL) {
Tree *tree;
//动态创建树,并加入森林
for(int i = 0; i < n; i++) {
tree = new Tree(vals[i], times[i]);
addTree(tree); //添加树到森林并按times排序
}
//
while(head->next != NULL) {
outputTrees();
Tree *t1 = head, *t2 = t1->next;
tree = new Tree(-1, t1->times + t2->times);
tree->left = t1;
tree->right = t2;
head = t2->next;
tree->left->next = NULL;
tree->right->next = NULL;
tree->left->parent = tree;
tree->right->parent = tree;
addTree(tree);
}
outputTrees();
}
//编写output类辅助方法用于观察程序中间结果以调试程序
//用于输出森林————多棵树间的next关系遍历
void outputTrees() {
Tree *ptr = head;
cout << "森林:";
while(ptr) {
cout << (char)(ptr->val) << "[" << ptr->times << "] ";
ptr = ptr->next;
}
cout << endl;
}
//输出huffman编码
void output() {
head->output();
}
~Trees() {
delete head;
}
} Trees;
int main()
{
int vals[] = {'a', 'b', 'c', 'd', 'e', 'f'};
int times[] = {45, 13, 12, 16, 9, 5};
Trees trees(vals, times, 6);
trees.output();
return 0;
}
程序运行结果:
~$ ./a.out
森林:f[5] e[9] c[12] b[13] d[16] a[45]
森林:c[12] b[13] �[14] d[16] a[45]
森林:�[14] d[16] �[25] a[45]
森林:�[25] �[30] a[45]
森林:a[45] �[55]
森林:�[100]
Huffman编码方案:
a[45]=0
c[12]=001
b[13]=101
f[5]=0011
e[9]=1011
d[16]=111