# [数据结构] 二叉树--赫夫曼数的建立、编码与解码

1
5 15 4 4 3 2

15-1
4-010
4-011
3-001
2-000

#include <iostream>
#include <string>
using namespace std;

class HuffNode
{
public:
unsigned int weight;
unsigned int parent, Lchild, Rchild;
};

class HuffManTree
{
private:
void MakeTree();
void SelectMin(int pos, int *s1, int *s2);
public:
int len; //结点数量
int lnum; //叶子数量
HuffNode *hufftree;
string * huffCode; //每个字符对应Huffman编码
void MakeTree(int n, int wt[]);
void Coding();
~HuffManTree();
};

void HuffManTree::MakeTree(int n, int wt[])
{
int i;
lnum = n;
len = 2*n - 1;
hufftree = new HuffNode[2*n];
huffCode = new string[lnum+1]; //位置从1开始计算
//huffCode实质是个二维字符数组，第i行表示第i个字符对应的编码

//赫夫曼树初始化 -- 叶子结点部分
for(i=1; i<=n; i++)
{
hufftree[i].weight = wt[i-1]; //填入叶子权值，位置从1开始
hufftree[i].parent = 0;
hufftree[i].Lchild = 0;
hufftree[i].Rchild = 0;
} //end for

//赫夫曼树初始化 -- 非叶子结点部分
for(i=n+1; i<=len; i++)
{
hufftree[i].weight = 0;
hufftree[i].parent = 0;
hufftree[i].Lchild = 0;
hufftree[i].Rchild = 0;
} //end for

MakeTree();
}

void HuffManTree::MakeTree()
{
int i, s1, s2;
//赫夫曼数构建
for(i=lnum+1; i<=len; i++)
{
SelectMin(i-1, &s1, &s2);
hufftree[s1].parent = i;
hufftree[s2].parent = i;
hufftree[i].Lchild = s1;
hufftree[i].Rchild = s2;
hufftree[i].weight = hufftree[s1].weight + hufftree[s2].weight;
} //end for

}

void HuffManTree::SelectMin(int pos, int *s1, int *s2)
{
int i=1;
int min1=0x3f3f3f3f, min2=0x3f3f3f3f; //置为最大值
while(i<=pos)
{
if(hufftree[i].parent==0 && hufftree[i].weight<min1)
{
min1 = hufftree[i].weight;
*s1 = i;
}
i++;
}

i=1;
while(i<=pos)
{ //求第二小的值
if(hufftree[i].parent==0 && hufftree[i].weight<min2 && i!=*s1)
{
min2 = hufftree[i].weight;
*s2 = i;
}
i++;
}
//cout<<min1<<" "<<min2<<endl;
}

void HuffManTree::Coding()
{
char *cd;
int i, c, f, start;

cd = new char[lnum];
cd[lnum-1] = '\0';
for(i=1; i<=lnum; i++)
{
start = lnum-1;
for(c=i, f=hufftree[i].parent; f!=0; c=f, f=hufftree[f].parent)
{
if(hufftree[f].Lchild == c)
cd[--start] = '0';
else
cd[--start] = '1';
}

//huffCode[i] = new char[lnum-start];    //为第i各字符编码分配空间
huffCode[i].assign(&cd[start]);
//cout<<"test: "<<huffCode[i]<<endl;
}
delete []cd;
}

HuffManTree::~HuffManTree()
{
len = 0;
lnum = 0;
delete []hufftree;
delete []huffCode;
}

int main()
{
int t, n,i,j;
int wt[800];
HuffManTree myHuff;
cin>>t;
for(i= 0; i< t; i++){
cin>>n;
for(j= 0; j< n; j++)
cin>>wt[j];

myHuff.MakeTree(n, wt);
myHuff.Coding();
for(j= 1; j<= n; j++){
cout<<myHuff.hufftree[j].weight<<'-';
cout<<myHuff.huffCode[j]<<endl;
}
//myHuff.Destroy();
}
return 0;
}


int Decode(const string codestr, char txtstr[]);
//输入编码串codestr，输出解码串txtstr

2
5 15 4 4 3 2
A B C D E
3
11111
10100001001
00000101100
4 7 5 2
4 A B C D
3
1010000
111011
111110111

AAAAA
error
BBAAA
error
DCD

#include <iostream>
#include <string>
using namespace std;

#define ok 1
#define error -1

class HuffNode
{
public:
unsigned int weight;
unsigned int parent, Lchild, Rchild;
char value;
};

class HuffManTree
{
private:
void MakeTree();
void SelectMin(int pos, int *s1, int *s2);
public:
int len; //结点数量
int lnum; //叶子数量
HuffNode *hufftree;
string * huffCode; //每个字符对应Huffman编码
void MakeTree(int n, int wt[], char val[]);
void Coding();
int Decode(const string codestr, char txtstr[]);
~HuffManTree();
};

void HuffManTree::MakeTree(int n, int wt[], char val[])
{
int i;
lnum = n;
len = 2*n - 1;
hufftree = new HuffNode[2*n];
huffCode = new string[lnum+1]; //位置从1开始计算
//huffCode实质是个二维字符数组，第i行表示第i个字符对应的编码

//赫夫曼树初始化 -- 叶子结点部分
for(i=1; i<=n; i++)
{
hufftree[i].weight = wt[i-1]; //填入叶子权值，位置从1开始
hufftree[i].parent = 0;
hufftree[i].Lchild = 0;
hufftree[i].Rchild = 0;
hufftree[i].value = val[i-1];
} //end for

//赫夫曼树初始化 -- 非叶子结点部分
for(i=n+1; i<=len; i++)
{
hufftree[i].weight = 0;
hufftree[i].parent = 0;
hufftree[i].Lchild = 0;
hufftree[i].Rchild = 0;
} //end for

MakeTree();
}

void HuffManTree::MakeTree()
{
int i, s1, s2;
//赫夫曼数构建
for(i=lnum+1; i<=len; i++)
{
SelectMin(i-1, &s1, &s2);
hufftree[s1].parent = i;
hufftree[s2].parent = i;
hufftree[i].Lchild = s1;
hufftree[i].Rchild = s2;
hufftree[i].weight = hufftree[s1].weight + hufftree[s2].weight;
} //end for

}

void HuffManTree::SelectMin(int pos, int *s1, int *s2)
{
int i=1;
int min1=0x3f3f3f3f, min2=0x3f3f3f3f; //置为最大值
while(i<=pos)
{
if(hufftree[i].parent==0 && hufftree[i].weight<min1)
{
min1 = hufftree[i].weight;
*s1 = i;
}
i++;
}

i=1;
while(i<=pos)
{
//求第二小的值
if(hufftree[i].parent==0 && hufftree[i].weight<min2 && i!=*s1)
{
min2 = hufftree[i].weight;
*s2 = i;
}
i++;
}
//cout<<min1<<" "<<min2<<endl;
}

void HuffManTree::Coding()
{
char *cd;
int i, c, f, start;

cd = new char[lnum];
cd[lnum-1] = '\0';
for(i=1; i<=lnum; i++)
{
start = lnum-1;
for(c=i, f=hufftree[i].parent; f!=0; c=f, f=hufftree[f].parent)
{
if(hufftree[f].Lchild == c)
cd[--start] = '0';
else
cd[--start] = '1';
}

//huffCode[i] = new char[lnum-start];    //为第i各字符编码分配空间
huffCode[i].assign(&cd[start]);
//cout<<"test: "<<huffCode[i]<<endl;
}
delete []cd;
}

int HuffManTree::Decode(const string codestr, char txtstr[])
{
int i, j, k;
i = len;
j = 0;
k = 0;

while(j<codestr.length())
{
if(codestr[j]=='0')
{
i = hufftree[i].Lchild;
}
else if(codestr[j]=='1')
{
i = hufftree[i].Rchild;
}

if(hufftree[i].Lchild == 0 && hufftree[i].Rchild==0)
{
txtstr[k] = hufftree[i].value;
k++;
i = len;
}
j++;
}

txtstr[k] = '\0';
if(i==len)
return ok;
else return error;

}

HuffManTree::~HuffManTree()
{
len = 0;
lnum = 0;
delete []hufftree;
delete []huffCode;
}

int main()
{
int t, n,i,j;
int wt[800];
char val[800];
HuffManTree myHuff;
cin>>t;
for(i= 0; i< t; i++)
{
cin>>n;
for(j= 0; j< n; j++)
cin>>wt[j];
for(j=0; j<n; j++)
cin>>val[j];

myHuff.MakeTree(n, wt, val);
myHuff.Coding();
/*for(j= 1; j<= n; j++)
{
cout<<myHuff.hufftree[j].weight<<'-';
cout<<myHuff.huffCode[j]<<endl;
}*/
//myHuff.Destroy();

int k;
string codestr;
char ch[100];
cin>>k;
while(k--)
{
cin>>codestr;
int a = myHuff.Decode(codestr, ch);
if(a==1)
cout<<ch<<endl;
else
cout<<"error"<<endl;

}
}
return 0;
}

• 0
点赞
• 0
评论
• 0
收藏
• 一键三连
• 扫一扫，分享海报

03-16 8063

10-23 1755
10-23 1686
10-23 3075
12-07
06-08 1万+
12-21 1665
05-03 1万+
10-17 754
08-07 2001
10-24 111
08-24 576

1.余额是钱包充值的虚拟货币，按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载，可以购买VIP、C币套餐、付费专栏及课程。