实验目的:
掌握赫夫曼二叉树的建立及赫夫曼编码的生成。
实验内容与要求:
根据给定的n个权值生成赫夫曼二叉树,输出赫夫曼编码及进行译码。
#include<iostream>
#include<vector>
#include<stack>
using namespace std;
const int MAX = 9999;
class HuffmanTree {
private:
struct HTnode {
char name; //节点名称
unsigned int weight; //权重
unsigned int parent, lchild, rchild; //双亲、左右孩子节点
//初始化
HTnode() {
name = 'n';
weight = 0;
parent = 0; lchild = 0; rchild = 0;
}
};
vector<HTnode>hu;
public:
void accept(int n); //接受给定的n个权值
void select(int& a, int& b); //找到hu中权值最小且无双亲的两个节点,返回值a,b
void create(); //创建赫夫曼树
void print(int n,string s); //输出赫夫曼编码
void code(); //进行译码
};
void HuffmanTree::accept(int n)
{
for (int i = 0; i < n; i++) {
HTnode p;
cout << "输入节点名称及权值(例如:A 1):";
cin >> p.name;
cin >> p.weight;
hu.push_back(p);
}
}
void HuffmanTree::select(int& a, int& b)
{
vector<HTnode>v;
//排除所有双亲不为0的节点
for (unsigned i = 0; i < hu.size(); i++) {
if (hu[i].parent == 0)v.push_back(hu[i]);
else {
HTnode p;
p.weight = MAX;
v.push_back(p);
}
}
//找到权最小的两个节点
unsigned int tmp = MAX;
for (unsigned i = 0; i < v.size(); i++) {
if (v[i].weight < tmp) {
a = i;
tmp = v[i].weight;
}
}
tmp = MAX;
for (unsigned i = 0; i < v.size(); i++) {
if(i!=a)
if (v[i].weight < tmp) {
b = i;
tmp = v[i].weight;
}
}
}
void HuffmanTree::create()
{
unsigned int s = 2*this->hu.size()-1;
int i, j;
while (this->hu.size() != s) {
select(i, j);
//将这两个节点合并成一棵二叉树
HTnode p;
p.name = hu[i].name + hu[j].name;
p.weight = hu[i].weight + hu[j].weight;
if (i < j) {
p.lchild = j;
p.rchild = i;
}
else {
p.lchild = i;
p.rchild = j;
}
hu.push_back(p);
hu[i].parent = hu.size() - 1;
hu[j].parent = hu.size() - 1;
}
}
void HuffmanTree::print(int n,string s)
{
unsigned int i = 0, j = 0;
stack<char>st; //利用栈输出编码信息
for (unsigned int x= 0; x < s.size(); x++) {
for (unsigned int y = 0; y < n; y++) {
if (s[x] == hu[y].name) {
j = y;
i = y;
}
}
//求每个字符的赫夫曼编码
while (hu[j].parent != 0) {
if (j == hu[hu[j].parent].lchild) st.push('0');
if (j == hu[hu[j].parent].rchild) st.push('1');
j = hu[j].parent;
}
//输出编码
while (!st.empty()) {
cout << st.top();
st.pop();
}
}
}
void HuffmanTree::code()
{
cout <<endl<< "输入编码找到相应节点,以#结尾(例:000#):";
unsigned int j = hu.size()-1;
int a = 0;
string s;
cin >> s;
for(unsigned i=0;i<s.size();i++) {
if (s[i] == '0' && (hu[j].lchild != 0|| hu[j].rchild != 0)) j = hu[j].lchild;
else if (s[i] == '1' && (hu[j].lchild != 0 || hu[j].rchild != 0))j = hu[j].rchild;
else {
cout << hu[j].name;
j = hu.size() - 1;
if(s[i]!='#')i--;
}
}
}
int main() {
HuffmanTree T;
int n; string s;
cout << "输入权值个数:";
cin >> n;
cout << endl;
if (n < 2) {
cout << "error";
}
else {
T.accept(n);
T.create();
cout << endl;
cout << "输入一串字符:";
cin >> s;
T.print(n, s);
cout << endl;
T.code();
cout << endl;
}
}