#include<iostream>
#include<string.h>
#include<stdlib.h>
using namespace std;
typedef char** HuffmanCode;
typedef struct
{
int s1 = 0;
int s2 = 0;
}Num;//返回两个最小数的结构体
//哈夫曼树的结构
typedef struct {
int weight = NULL;//权值
char data = NULL;//结点信息
int parent = 0, lchild = 0, rchild = 0;//双亲,左孩子,右孩子
int sum = 1;//节点数量
}HTNode, * HuffmanTree;
//哈夫曼树的结构
Num Select(HuffmanTree HT, int range)//选择两个权值最小的节点
{
Num n;
while (!n.s1 || !n.s2)
{
Num min;
for (int i = 1; i <= range; i++)//选择第一个没有双亲的节点
{
if (HT[i].parent == 0)
{
min.s1 = HT[i].weight;
min.s2 = i;
break;
}
}
for (int i = 1; i <= range; i++)
{
if (HT[i].weight < min.s1 && HT[i].parent == 0)
{
min.s1 = HT[i].weight;//记录值
min.s2 = i;
}
}
HT[min.s2].parent = 1;
if (!n.s1) {
n.s1 = min.s2; }//先将权值最小的节点的序号付给n.s1
else {
n.s2 = min.s2; }
}
return n;
}
//构造哈夫曼树
void CreateHumanTree(HuffmanTree& HT, int n)
{
if (n <= 1) return;
int m = 2 * n - 1;
HT = new HTNode[m + 1];
for (int i = 1; i <= m; i++)//下标从1开始,初始化
{
HT->sum++;
HT[i].parent = 0;
HT[i].lchild = 0;
HT[i].rchild = 0;
}
cout << "输入各节点的权值和结点信息:";
for (int i = 1; i <= n; i++)
{
cin >> HT[i].weight >> HT[i].data;
}
for (int i = n + 1; i <= m; i++)
{
int s1, s2;
Num n = Select(HT, i - 1);
s1 = n.s1; s2 = n.s2;
HT[s1].parent = i; HT[s2].parent = i;
HT[i].lchild = s1; HT[i].rchild = s2;
HT[i].weight = HT[s1].weight + HT[s2].weight;
}
}
//构造哈夫曼树
//构造哈夫曼编码
void CreateHuffmanCode(HuffmanTree HT, HuffmanCode& HC, int n)
{
HC = new char* [n + 1];//为HC分配n+1个空间
for (int i = 1; i <= n; i++)
{
char *cd = new char[n];
cd[n - 1] = '\0';
int start = n - 1;
int c = i;
int f = HT[i].parent;
while (f)
{
--start;
if (HT[f].lchild == c)
{
cd[start] = '0'; }
else if (HT[f].rchild == c)
{
cd[start] = '1'; }
c = f; f = HT[f].parent;
}
HC[i] = new char[n - start];
strcpy_s(HC[i], n-start,&cd[start]);
delete []cd;
}
}//5 a 29 b 7 c 8 d 14 e 23 f 3 g 11 h
//构造哈夫曼编码
//构造哈夫曼编码
void Transcode(HuffmanTree HT, string s)
{
int len = s.length();//字符串的长度
for (int i = 0; i < len; i++)
{
int j = HT->sum - 1;//哈夫曼树的根节点
while (HT[j].lchild && HT[j].rchild)
{
if (s[i] == '0')//指向左子树
{
j = HT[j].lchild;
}
else//指向右子树
{
j = HT[j].rchild;
}
i++;
}
i--;//退一格
cout << HT[j].data;//输出
}
}
//求哈夫曼树的带权路径长度
int WPL(HuffmanTree HT)
{
int sum = 0;//带权路径长度
for (int i = 1; i <= HT->sum / 2; i++)//从第一个节点开始寻找根节点,找到路径长度
{
int j = 0;
int i_ = i;
while (HT[i_].parent)
{
i_ = HT[i_].parent;
j++;//路径长度
}
sum += j * HT[i].weight;
}
return sum;
}
//求哈夫曼树的带权路径长度
int main()
{
HuffmanTree T;
HuffmanCode HC;
int n;
string s;
cout << "您要输入节点的个数:";
cin >> n;
CreateHumanTree(T,n);
cout << "最短路径长度:" << WPL(T) << endl;
CreateHuffmanCode(T, HC, n);
for (int i = 1; i <= n; i++)
{
cout << T[i].data << ":" << HC[i] << endl;
}
cout << "您要翻译的编码:";
cin >> s;
Transcode(T, s);
return 0;
}
Encoding and decoding using Huffman tree
Guess you like
Origin blog.csdn.net/m0_43456002/article/details/104302085
Recommended
Ranking