名词我就不解释了。
注意构造赫夫曼树的过程并不唯一,因为左右孩子次序并无规定,节点权值相等时先后次序也不尽相同。
不过最后得到的一定都是符合要求的编码就是了。
所以我这里按《数据结构》例6.2输入源数据,得到的结果略微有些差异,不过确实是正确的。
实现时,用了较多vector,反倒把代码搞得不太简洁了,不管了,代码如下:
/*
2014.6.11
对一组给定的权值进行赫夫曼编码
考虑到此演示程序输出结果即结束,不再在为防内存泄露编写析构函数上浪费时间
*/
#include <iostream>
#include <vector>
#include <string>
using std::cin;
using std::cout;
using std::endl;
using std::vector;
using std::string;
struct HuffmanTreeNode
{
float data;
HuffmanTreeNode *lchild;
HuffmanTreeNode *rchild;
HuffmanTreeNode *parent;
};
struct Result
{
HuffmanTreeNode *leaf;
string code;
};
class Chuffcode
{
private:
string RootAndEncode(HuffmanTreeNode *leaf);
public:
Chuffcode(vector<float> src);
};
string Chuffcode::RootAndEncode(HuffmanTreeNode *leaf)
{
string result;
while (leaf->parent != NULL)
{
if (leaf->parent->lchild == leaf) //左为0,右为1
{
result.insert(0, "0");
}
else
{
result.insert(0, "1");
}
leaf = leaf->parent;
}
return result;
}
Chuffcode::Chuffcode(vector<float> src)
{
//为每个权值元素建立二叉树,记下叶子地址集(方便将来取结果),并放进森林(循环处理森林)
vector<Result> results;
vector<HuffmanTreeNode *> trees;
vector<float>::iterator iter;
for(iter = src.begin(); iter != src.end(); ++iter)
{
HuffmanTreeNode *pNode = new HuffmanTreeNode;
pNode->data = *iter;
pNode->lchild = NULL;
pNode->rchild = NULL;
pNode->parent = NULL;
Result leafinfo;
leafinfo.leaf = pNode;
leafinfo.code = "";
results.push_back(leafinfo);
trees.push_back(pNode);
}
//重复下个步骤直至只剩一棵树
//遍历森林中树的根节点,剔出权值最低的两棵构成新树的叶子,新树放回森林
while (trees.size() != 1)
{
//找出最小节点
vector<HuffmanTreeNode *>::iterator iter2;
HuffmanTreeNode *minNode1 = trees[0];
float min = trees[0]->data;
vector<HuffmanTreeNode *>::iterator minIter = trees.begin();
for(iter2 = trees.begin() + 1; iter2 != trees.end(); ++iter2)
{
if ((*iter2)->data < min)
{
minNode1 = *iter2;
min = (*iter2)->data;
minIter = iter2;
}
}
//删除最小节点
trees.erase(minIter);
//找出次小节点并删除
HuffmanTreeNode *minNode2 = trees[0];
min = trees[0]->data;
minIter = trees.begin();
for(iter2 = trees.begin() + 1; iter2 != trees.end(); ++iter2)
{
if ((*iter2)->data < min)
{
minNode2 = *iter2;
min = (*iter2)->data;
minIter = iter2;
}
}
trees.erase(minIter);
//组合两节点成一棵树
HuffmanTreeNode *newNode = new HuffmanTreeNode;
newNode->data = minNode1->data + minNode2->data;
newNode->lchild = minNode1;
newNode->rchild = minNode2;
newNode->parent = NULL;
minNode1->parent = newNode;
minNode2->parent = newNode;
//加回森林
trees.push_back(newNode);
}
//从每片叶子寻回根,根据路径确定编码
vector<Result>::iterator leafiter;
for(leafiter = results.begin(); leafiter != results.end(); ++leafiter)
{
(*leafiter).code = RootAndEncode((*leafiter).leaf);
}
//打印结果
for(leafiter = results.begin(); leafiter != results.end(); ++leafiter)
{
cout<<(*leafiter).code<<endl;
}
}
int main()
{
vector<float> src;
float value;
while (cin >> value) //按ctrl+z输入结束符表示输入终止
{
src.push_back(value);
}
Chuffcode encoder(src);
}
/*
运行结果:
0.05 0.29 0.07 0.08 0.14 0.23 0.03 0.11^Z
0001
10
1110
1111
110
01
0000
001
*/