# 哈夫曼树的实现

#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;

const int MAXVALUE = 99999; //初始设定的权值最大值
const int MAXBIT = 10; //初始设定的最大编码位数
const int MAXN = 1000; //初始设定的最大结点个数

struct HaffNode //哈夫曼树的结点结构
{
int weight; //权值
int flag; //标记
int parent; //双亲结点下标
int leftChild; //左孩子下标
int rightChild; //右孩子下标
};

struct Code //存放哈夫曼编码的数据元素结构
{
int bit[MAXBIT]; //数组
int start; //编码的起始下标
int weight; //字符的权值
};

void Haffman(int weight[], int n, HaffNode haffTree[]);//建树
void HaffmanCode(HaffNode haffTree[], int n, Code haffCode[]);//生成哈夫曼编码
void Coding(char str[], char s[], int n, Code code[]);
void DeCoding(int n, char s[], HaffNode hafftree[]);
void PreOrder(HaffNode haffTree[], int n);
void InOrder(HaffNode haffTree[], int n);

int main()
{
int i, weight[MAXN], len;
char strChar[MAXN], c;
bool flag = true;
HaffNode *hafftree;
Code *haffcode;

while(flag)
{
cin >> c;
switch(c)
{
case 'B':
{
cin>>strChar;
len = strlen(strChar);
for(i=0; i<len; i++)
cin >> weight[i];
hafftree = new HaffNode[2*len-1];
Haffman(weight, len, hafftree);
}
break;

case 'E':
{
haffcode = new Code[len];
HaffmanCode(hafftree, len, haffcode);
}
break;

case 'T':
{
PreOrder(hafftree, 2*len-2);
cout << endl;
InOrder(hafftree, 2*len-2);
cout << endl;
}
break;

case 'C':
{
char strInput[MAXN];
cin >> strInput;
Coding(strInput, strChar, len, haffcode);
}
break;

case 'D':
{
DeCoding(len, strChar, hafftree);
}
break;

case 'P':
{
}
break;

case 'X':
{
flag = false;
}
break;

case 'S':
{
}
break;

default:
break;
}
}
return 0;
}

{
cout<<"********************************************************************"<<endl;
cout<<"* B—建树:   读入字符集和各字符频度，建立哈夫曼树。*****************"<<endl;
cout<<"********************************************************************"<<endl;
cout<<"* T—遍历:   先序和中序遍历二叉树。                *****************"<<endl;
cout<<"********************************************************************"<<endl;
cout<<"* E—生成编码: 根据已建成的哈夫曼树，产生各字符的哈夫曼编码。*******"<<endl;
cout<<"********************************************************************"<<endl;
cout<<"* C—编码:   输入由字符集中字符串组成的任意字符串，利用已生成的 ****"<<endl;
cout<<"*            哈夫曼编码,显示编码结果，并将输入的字符串及其编码  ****"<<endl;
cout<<"*            结果分别保存在磁盘文件textfile.txt和codefile.txt中。***"<<endl;
cout<<"********************************************************************"<<endl;
cout<<"* D—译码:   读入codefile.txt,利用建议建成的哈夫曼树进行译码，******"<<endl;
cout<<"*            并将译码结果放入磁盘文件result.txt。             ******"<<endl;
cout<<"********************************************************************"<<endl;
cout<<"* P—打印:   屏幕显示文件textfile.txt、codefile.txt和result.txt。***"<<endl;
cout<<"********************************************************************"<<endl;
cout<<"* X—退出。                           ******************************"<<endl;
cout<<"********************************************************************"<<endl;
}

void Haffman(int weight[], int n, HaffNode haffTree[])
//建立叶结点个数为n权值为weight的哈夫曼树haffTree
{
int j, m1, m2, x1, x2;
//哈夫曼树haffTree初始化。n个叶结点的哈夫曼树共有2n-1个结点
for(int i = 0; i < 2 * n - 1 ; i++)
{
if(i < n)
haffTree[i].weight = weight[i];
else
haffTree[i].weight = 0;
haffTree[i].parent = 0;
haffTree[i].flag = 0;
haffTree[i].leftChild = -1;
haffTree[i].rightChild = -1;
}
//构造哈夫曼树haffTree的n-1个非叶结点
for(i = 0;i < n-1;i++)
{
m1 = m2 = MAXVALUE;
x1 = x2 = 0;
for(j = 0; j < n+i;j++)
{
if (haffTree[j].weight < m1 && haffTree[j].flag == 0)
{
m2 = m1;
x2 = x1;
m1 = haffTree[j].weight;
x1 = j;
}
else if(haffTree[j].weight < m2 && haffTree[j].flag == 0)
{
m2 = haffTree[j].weight;
x2 = j;
}
}
//将找出的两棵权值最小的子树合并为一棵子树
haffTree[x1].parent = n + i;
haffTree[x2].parent = n + i;
haffTree[x1].flag = 1;
haffTree[x2].flag = 1;
haffTree[n+i].weight = haffTree[x1].weight + haffTree[x2].weight;
haffTree[n+i].leftChild = x1;
haffTree[n+i].rightChild = x2;
}
}

void HaffmanCode(HaffNode haffTree[], int n, Code haffCode[])
//由n个结点的哈夫曼树haffTree构造哈夫曼编码haffCode
{
Code *cd = new Code;
int child, parent;
//求n个叶结点的哈夫曼编码
for(int i = 0; i < n; i++)
{
cd->start = n-1; //不等长编码的最后一位为n-1
cd->weight = haffTree[i].weight; //取得编码对应权值的字符
child = i;
parent = haffTree[child].parent;
//由叶结点向上直到根结点
while(parent != 0)
{
if(haffTree[parent].leftChild == child)
cd->bit[cd->start] = 0; //左孩子结点编码0
else
cd->bit[cd->start] = 1;//右孩子结点编码1
cd->start--;
child = parent;
parent = haffTree[child].parent;
}
//保存叶结点的编码和不等长编码的起始位
for(int j = cd->start+1; j < n; j++)
haffCode[i].bit[j] = cd->bit[j];
haffCode[i].start = cd->start;
haffCode[i].weight = cd->weight; //保存编码对应的权值
}
}

void Coding(char str[], char s[], int n, Code code[])
{
ofstream outf("textfile.txt");
int len = strlen(str);

if(!outf)
{
cout << "cannot open the file\n";
return ;
}

outf << str;
outf << endl;
outf.close();

ofstream outfc("codefile.txt");
if(!outfc)
{
cout << "cannot open the file\n";
return ;
}
for(int i=0; i<len; i++)
{
for(int j=0; j<n; j++)
{
if(str[i] == s[j])
break;
}
for(int k=code[j].start+1; k<n; k++)
outfc << code[j].bit[k];
}
outfc << endl;
outfc.close();
}

void DeCoding(int n, char s[], HaffNode hafftree[])
{
ifstream inf("codefile.txt");
char str[MAXN];
inf >> str;

ofstream outf("result.txt");
int len = strlen(str);

int j = 2 * n - 2;
for(int i=0; i<len; i++)
{
if('0' == str[i])
{
if(0 <= hafftree[j].leftChild && hafftree[j].leftChild < n)
{
outf << s[hafftree[j].leftChild];
j = 2 * n - 2;
}
else
j = hafftree[j].leftChild;
}
else
{
if(0 <= hafftree[j].rightChild && hafftree[j].rightChild < n)
{
outf << s[hafftree[j].rightChild];
j = 2 * n - 2;
}
else
j = hafftree[j].rightChild;
}
}

inf.close();
outf.close();
}

{
ifstream inf(s);
char str[MAXN];
inf >> str;
cout << s << ":" << str << endl;
inf.close();
}

void PreOrder(HaffNode haffTree[], int n)
{
if(n > -1)
{
cout << haffTree[n].weight << " ";
PreOrder(haffTree, haffTree[n].leftChild);
PreOrder(haffTree, haffTree[n].rightChild);
}
}

void InOrder(HaffNode haffTree[], int n)
{
if(n > -1)
{
InOrder(haffTree, haffTree[n].leftChild);
cout << haffTree[n].weight << " ";
InOrder(haffTree, haffTree[n].rightChild);
}
}

#### 利用哈夫曼树实现文件压缩

2017-02-27 10:51:49

#### 哈夫曼树及其算法实现

2016-08-04 22:10:35

#### 哈夫曼树实现压缩解压

2011年11月28日 317KB 下载

#### 设计程序以实现构造哈夫曼树的哈夫曼算法

2007-06-06 23:32:00

#### 哈夫曼树以及文件压缩的实现

2016-12-22 22:20:46

#### 哈夫曼树的c++实现

2016-05-24 11:21:10

#### 九度oj 题目1172：哈夫曼树(优先队列实现最小堆)

2015-07-02 20:32:55

#### 哈夫曼树c语言实现

2013年05月06日 2KB 下载

#### 【数据结构】最小堆实现哈夫曼树构造与解码

2015-09-08 11:34:53

#### 哈夫曼树实现文件压缩与解压缩

2016-06-06 21:23:14