// 哈夫曼树的构造.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include
using namespace std;
#include
struct HashTree
{
double weight;
int parent;
int lchild,rchild;
};
void initWeight(HashTree HT[],int n)
{
cout<<"请输入"<<n<<"个大于0的数"<<endl;
double data;
for(int i = 0; i < n; i++)
{
cin>>data;
HT[i].weight = data;
}
}
void CreateHT(HashTree ht[],int n)
//n为叶子结点,这时可求出共有结点2n-1个
{
int i ,k,lnode,rnode;
double min1,min2;
for(i = 0; i < 2 * n - 1; i++)//置所有数据为-1,初始化数据
{
ht[i].parent = ht[i].lchild = ht[i].rchild = -1;
}
for(i = n; i < 2 * n - 1; i++)//注意这里n到2n-1用来保存生成的新结点
{
min1 = min2 = 99999999999999;//初始化数据无限大
lnode = rnode = -1;//保存两个权重最小结点的位置
for( k = 0; k <= i - 1; k++)
if(ht[k].parent == -1)//只在尚未构造的二叉树节点中查找
{
if(ht[k].weight < min1)//如果小于当前最小值,修改最小值,次小值以及lnode的值
{
min2 = min1;
rnode = lnode;
min1 = ht[k].weight;
lnode = k;
}
else if(ht[k].weight < min2)//如果小于当前次小值,修改次小值以及rnode的值
{
min2 = ht[k].weight;
rnode = k;
}
}
cout<<"最小的两个值为:"<<ht[lnode].weight<<" " <<ht[rnode].weight<<endl;
ht[i].weight = ht[lnode].weight + ht[rnode].weight;//新结点的权值
ht[i].lchild = lnode;//新结点左右子树的下标
ht[i].rchild = rnode;
ht[lnode].parent = i;//设置结点已被构造
ht[rnode].parent = i;
//ht[i].parent = -1;
}
}
void createHCode(HashTree ht[], int n)//哈夫曼树编码
{
int f,c;
for(int i = 0; i < n; i++)//搜索子节点0到n
{
string s="";
c = i;
f = ht[i].parent;//双亲结点
while(f != -1)//从叶子结点到根结点进行扫描
{
if(ht[f].lchild == c)//当前结点是左孩子
{
s= s +'0';
}
else
{
s = s +'1';
}
c = f;
f = ht[f].parent;
}
cout<<"当前结点"<<ht[i].weight<<"的编码为:";
for(int i = (int)s.size() - 1;i>=0;i--)//输出编码
{
cout<<s[i];
}
cout<<endl;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int n = 5;
cout<<"假设目前叶子结点数为5"<<endl;
HashTree ht[9];//在哈夫曼树中,叶子为n的树共有2*n-1 个结点
initWeight(ht,n);//输入权值
CreateHT(ht,n);//构造哈夫曼树
createHCode(ht,5);//构造 哈夫曼编码
return 0;
}