/*第五次作业:
假设在某段传输的报文中包涵12种字符,这十二种字符出现的频率分别为
0.1,0.02,0.07,0.06,0.12,0.23,0.09,0.4,0.21,0.13,0.21,0.32 .
请先构造哈夫曼树,然后实现该12个字符的哈夫曼编码。
将频数转换为整数(即,叶子结点的权值):10, 2, 7, 6, 12, 23, 9, 40, 21, 13, 21, 32 .
*/
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
using namespace std;
#define max 100
//define node of huffman node
struct HTNode
{
int m_parent;
int m_lchild;
int m_rchild;
int m_weight;
};
//define huffman tree
struct HTree//顺序表来定义
{
HTNode* m_Htree;
int m_length;
};
//init function
void initHTree(HTree& HT, int num)//num为叶子节点个数
{
int totalNode = 2 * num - 1;//totalNode为总节点个数
HT.m_Htree = new HTNode[totalNode];
if (!HT.m_Htree)
{
cout << "init fail" << endl;
}
HT.m_length = 0;
int i;
for (i = 0; i < num; i++)//遍历初始化
{
HT.m_Htree[i].m_parent = -1;
HT.m_Htree[i].m_lchild = -1;
HT.m_Htree[i].m_rchild = -1;
cout << "pls input the weight of " << i << endl;
int weight;
cin >> weight;
HT.m_Htree[i].m_weight = weight;
HT.m_length++;
}
for (; i < totalNode; i++)
{
HT.m_Htree[i].m_parent = -1;
HT.m_Htree[i].m_lchild = -1;
HT.m_Htree[i].m_rchild = -1;
HT.m_Htree[i].m_weight = 9999;//权值初始化,先给个大值
HT.m_length++;
}
cout << "init success" << endl;
}
//find two min node function
void findTwoMinNodeOfTree(HTree& HT, int pos, int& min1, int& min2)
{
int i = 0;
int m1, m2;//接受最小权值的位置
int minweight;//当前根结点的最小权值
//find min1
while (HT.m_Htree[i].m_parent != -1)
{
i++;
}
minweight = HT.m_Htree[i].m_weight;//将找到的第一个根结点赋给minweight
m1 = i;
for (; i < pos; i++)
{
if (HT.m_Htree[i].m_weight < minweight && HT.m_Htree[i].m_parent == -1)
{
minweight = HT.m_Htree[i].m_weight;
m1 = i;
}
}
HT.m_Htree[m1].m_parent = 1;//change the node state to not root
min1 = m1;
//find min2
i = 0;
while (HT.m_Htree[i].m_parent != -1)
{
i++;
}
minweight = HT.m_Htree[i].m_weight;
m2 = i;
for (; i < pos; i++)
{
if (HT.m_Htree[i].m_weight < minweight && HT.m_Htree[i].m_parent == -1)
{
minweight = HT.m_Htree[i].m_weight;
m2 = i;
}
}
HT.m_Htree[m2].m_parent = 1;//change the node state to not root
min2 = m2;
}
//function of createHtree
void createHuffmanTree(HTree& HT, int num)
{
if (!HT.m_Htree)
{
cout << "the tree is not exist" << endl;
}
int i, min1, min2;
for (i = num; i < HT.m_length; i++)
{
findTwoMinNodeOfTree(HT, i, min1, min2);
HT.m_Htree[min1].m_parent = i;
HT.m_Htree[min2].m_parent = i;
HT.m_Htree[i].m_lchild = min1;
HT.m_Htree[i].m_rchild = min2;
HT.m_Htree[i].m_weight = HT.m_Htree[min1].m_weight + HT.m_Htree[min2].m_weight;
}
}
//function of huffman coding 哈夫曼树编码
void HuffmanCoding(HTree& HT, char**& HC)
{
int numOfCode = (HT.m_length + 1) / 2;
HC = new char* [numOfCode];//array of char array,每一个编码都是一个字符数组
if (!HC)
{
cout << "huffmancode mem fail" << endl;
}
char* code = new char[numOfCode];//字符数组不能直接赋值,只能拷贝
if (!code)//判断空间是否给我们
{
cout << "code mem fail" << endl;
}
int cur = HT.m_length - 1;//pos in array
int codelen = 0;
//visit state : 0:not visit ; 1:lchild visited ; 2:all visited
int i;
for (i = 0; i < HT.m_length; i++)
{
HT.m_Htree[i].m_weight = 0; //初始化所有的结点权值为0
}
while (cur != -1) //判断该节点的左右儿子是否为-1,即叶节点,此时该编码结束
{
if (HT.m_Htree[cur].m_weight == 0)//从头节点开始遍历
{
HT.m_Htree[cur].m_weight = 1;//表示访问过,变flag
if (HT.m_Htree[cur].m_lchild != -1)//判断是不是叶节点
{
code[codelen++] = '0';
cur = HT.m_Htree[cur].m_lchild;//让它沿着左儿子方向走
}
else
{//已经为叶结点时
code[codelen] = '\0';//终止符
HC[cur] = new char[codelen + 1];//申请一个空间
if (!HC[cur])//判断地址给没给我们
{
cout << "code mem fail" << endl;
}
strcpy(HC[cur], code);//拷贝
}
}
else if (HT.m_Htree[cur].m_weight == 1)//右侧
{
HT.m_Htree[cur].m_weight = 2;
if (HT.m_Htree[cur].m_rchild != -1)//判断右儿子是否到叶结点
{
code[codelen++] = '1';
cur = HT.m_Htree[cur].m_rchild;
}
}
else//其他情况时
{
HT.m_Htree[cur].m_weight = 0;
cur = HT.m_Htree[cur].m_parent;
--codelen;
}
}
delete[]code;
}
//show code
void showHuddmanCode(char**& HC, int numOfCode)
{
for (int j = 0; j < numOfCode; j++)
{
cout << "the code is " << HC[j] << endl;
}
}
//list the huffmantree
void showTree(HTree& HT)
{
if (HT.m_Htree != NULL)
{
cout << "show the node of huffmantree" << endl;
for (int i = 0; i < HT.m_length; i++)
{
cout << HT.m_Htree[i].m_parent <<" "
<< HT.m_Htree[i].m_lchild <<" "
<< HT.m_Htree[i].m_rchild <<" "
<< HT.m_Htree[i].m_weight << endl;
}
}
}
//test
void test()
{
cout << "pls input the num of leaf node" << endl;
int num;
cin >> num;
HTree mytree;
initHTree(mytree, num);
int pos, min1, min2;
pos = mytree.m_length;
findTwoMinNodeOfTree(mytree, pos, min1, min2);
cout << "min1= " << min1 << endl;
cout << "min2= " << min2 << endl;
showTree(mytree);
}
void test01()
{
cout << "pls input the num of leaf node" << endl;
int num;
cin >> num;
HTree mytree;
initHTree(mytree, num);
createHuffmanTree(mytree, num);
showTree(mytree);
cout << "***************************" << endl;
char** hcode;
HuffmanCoding(mytree, hcode);
cout << "***************************" << endl;
showHuddmanCode(hcode, num);
}
int main()
{
test01();
//test();
system("pause");
return 0;
}
11-21
1768
12-05
3万+
01-26
6253
05-01
2万+
03-06
307