//哈夫曼树顺序存储结构 --- 一维结构数组
struct HTNode {
double weight;//权值
int parent;//父结点下标
int lch, rch;//左右子结点下标
string text;//字符
string huffmanCode;//二进制哈夫曼编码值
};
//构造哈夫曼树
void creatHuffmanTree(HTNode** pHuffmanTree,int NODE_NUM)
{
//NODE_NUM 结点数量
//8个结点的权值为7,19,2,6,32,3,21,10
//n个结点构造完成的哈夫曼树会有(2n-1)个结点
//构造哈夫曼树 (n个结点要合并n-1次)
for (int i = 0; i < NODE_NUM - 1;++i) {
//找到权值最小的两个结点序号
int minWeightIndex1 = -1, minWeightIndex2 = -1;
for (int j = 0; j < NODE_NUM + i;++j) {
if((*pHuffmanTree)[j].parent!=-1) continue;
if (minWeightIndex2 == -1 || (*pHuffmanTree)[j].weight < (*pHuffmanTree)[minWeightIndex2].weight) {
minWeightIndex2 = j;
//把序号为minWeightIndex1和minWeightIndex2的结点按权值从小到大排序
if (minWeightIndex1== -1 || (*pHuffmanTree)[minWeightIndex1].weight > (*pHuffmanTree)[minWeightIndex2].weight) {
int tmp = minWeightIndex1;
minWeightIndex1 = minWeightIndex2;
minWeightIndex2 = tmp;
}
}
}
if (minWeightIndex1 == -1 || minWeightIndex2 == -1) continue;
//把权值最小的两个结点作为左右子树合并成一棵树,新结点权值为左右子树的根结点权值之和。
(*pHuffmanTree)[NODE_NUM + i].weight = (*pHuffmanTree)[minWeightIndex1].weight + (*pHuffmanTree)[minWeightIndex2].weight;
(*pHuffmanTree)[NODE_NUM + i].lch = minWeightIndex1;
(*pHuffmanTree)[NODE_NUM + i].rch = minWeightIndex2;
(*pHuffmanTree)[minWeightIndex1].parent = NODE_NUM + i;
(*pHuffmanTree)[minWeightIndex2].parent = NODE_NUM + i;
}
cout << "after construct:" << endl;
for (int i = 0; i < 2 * NODE_NUM - 1; ++i) {
cout << (*pHuffmanTree)[i].weight << " " << (*pHuffmanTree)[i].parent << " "
<< (*pHuffmanTree)[i].lch << " " << (*pHuffmanTree)[i].rch << " "
<< (*pHuffmanTree)[i].text << " " << (*pHuffmanTree)[i].huffmanCode << endl;
}
}
void test15() {
HTNode* pHuffmanTree = NULL;
//###8个结点的权值为7,19,2,6,32,3,21,10
//###构造完成的哈夫曼树会有15(2n-1)个结点
int NODE_NUM = 8;//结点数量
//设置初始结点的值
pHuffmanTree = new HTNode[2 * NODE_NUM - 1];
for (int i = 0; i < 2 * NODE_NUM - 1; ++i) {
pHuffmanTree[i].weight = -1;
pHuffmanTree[i].parent = -1;
pHuffmanTree[i].lch = -1;
pHuffmanTree[i].rch = -1;
}
pHuffmanTree[0].weight = 7; pHuffmanTree[1].weight = 19; pHuffmanTree[2].weight = 2;
pHuffmanTree[3].weight = 6; pHuffmanTree[4].weight = 32; pHuffmanTree[5].weight = 3;
pHuffmanTree[6].weight = 21; pHuffmanTree[7].weight = 10;
cout << "before construct:" << endl;
for (int i = 0; i < 2 * NODE_NUM - 1; ++i) {
cout << pHuffmanTree[i].weight << " " << pHuffmanTree[i].parent << " "
<< pHuffmanTree[i].lch << " " << pHuffmanTree[i].rch << endl;
}
creatHuffmanTree(&pHuffmanTree, NODE_NUM);
}
//获取哈夫曼编码
void getHuffmanCode(HTNode** pHuffmanTree,int NODE_NUM) {
for (int i = 0; i < NODE_NUM; ++i) {
HTNode node = (*pHuffmanTree)[i];
int nodeId = i;
while (node.parent != -1) {
if ((*pHuffmanTree)[node.parent].lch == nodeId) //每经过一条左分支添加一个0
{
(*pHuffmanTree)[i].huffmanCode = string("0") + (*pHuffmanTree)[i].huffmanCode;
}
else //每经过一条右分支添加一个1
{
(*pHuffmanTree)[i].huffmanCode = string("1") + (*pHuffmanTree)[i].huffmanCode;
}
nodeId = node.parent;
node = (*pHuffmanTree)[node.parent];
}
}
}
void test16() {
HTNode* pHuffmanTree = NULL;
//###8个结点的权值为7,19,2,6,32,3,21,10
//###构造完成的哈夫曼树会有15(2n-1)个结点
int NODE_NUM = 27;//结点数量
//设置初始结点的值
pHuffmanTree = new HTNode[2 * NODE_NUM - 1];
for (int i = 0; i < 2 * NODE_NUM - 1; ++i) {
pHuffmanTree[i].weight = -1;
pHuffmanTree[i].parent = -1;
pHuffmanTree[i].lch = -1;
pHuffmanTree[i].rch = -1;
}
pHuffmanTree[0] = { 0.26,-1,-1,-1," ","" };
pHuffmanTree[1] = { 0.13,-1,-1,-1,"e","" };pHuffmanTree[2] = { 0.09,-1,-1,-1,"t","" };
pHuffmanTree[3] = { 0.08,-1,-1,-1,"a","" };pHuffmanTree[4] = { 0.075,-1,-1,-1,"o","" };
pHuffmanTree[5] = { 0.07,-1,-1,-1,"i","" };pHuffmanTree[6] = { 0.067,-1,-1,-1,"n","" };
pHuffmanTree[7] = { 0.064,-1,-1,-1,"s","" };pHuffmanTree[8] = { 0.061,-1,-1,-1,"h","" };
pHuffmanTree[9] = { 0.06,-1,-1,-1,"r","" };pHuffmanTree[10] = { 0.042,-1,-1,-1,"d","" };
pHuffmanTree[11] = { 0.04,-1,-1,-1,"l","" };pHuffmanTree[12] = { 0.03,-1,-1,-1,"c","" };
pHuffmanTree[13] = { 0.029,-1,-1,-1,"u","" };pHuffmanTree[14] = { 0.025,-1,-1,-1,"m","" };
pHuffmanTree[15] = { 0.024,-1,-1,-1,"w","" };pHuffmanTree[16] = { 0.023,-1,-1,-1,"f","" };
pHuffmanTree[17] = { 0.022,-1,-1,-1,"g","" };pHuffmanTree[18] = { 0.0215,-1,-1,-1,"y","" };
pHuffmanTree[19] = { 0.021,-1,-1,-1,"p","" };pHuffmanTree[20] = { 0.018,-1,-1,-1,"b","" };
pHuffmanTree[21] = { 0.01,-1,-1,-1,"v","" };pHuffmanTree[22] = { 0.009,-1,-1,-1,"k","" };
pHuffmanTree[23] = { 0.0021,-1,-1,-1,"j","" };pHuffmanTree[24] = { 0.002,-1,-1,-1,"x","" };
pHuffmanTree[25] = { 0.0012,-1,-1,-1,"q","" };pHuffmanTree[26] = { 0.001,-1,-1,-1,"z","" };
cout << "before construct:" << endl;
for (int i = 0; i < 2 * NODE_NUM - 1; ++i) {
cout << pHuffmanTree[i].weight << " " << pHuffmanTree[i].parent << " "
<< pHuffmanTree[i].lch << " " << pHuffmanTree[i].rch << " "
<< pHuffmanTree[i].text << " " << pHuffmanTree[i].huffmanCode << endl;
}
creatHuffmanTree(&pHuffmanTree, NODE_NUM);
getHuffmanCode(&pHuffmanTree, NODE_NUM);
cout << "get code:" << endl;
for (int i = 0; i < 2 * NODE_NUM - 1; ++i) {
cout << "index:" << i << " " << "parent:" << pHuffmanTree[i].parent << " "
<< "leftChild:" << pHuffmanTree[i].lch << " " << "rightChild:" << pHuffmanTree[i].rch << " "
<< pHuffmanTree[i].text << " " << pHuffmanTree[i].huffmanCode << endl;
}
//对文本进行转码
//string text = "my name is zyb!";
string text = "The goal of early calculating machines was to simplify difficult sums.But with the help of new "
"technology, electronic chips replaced tubes and a revolution of artificial intelligence has arisen.From then on, "
"the appearance of computers totally changed our lives.They can not only download information from the wet when "
"connected by the network or mobile phone signals, but also solve different types of logical problems."
"With operators as their coaches, they can even control rockets to explore the moon and instruct androids with "
"the human race’s characters to mop floors and watch over your naughty niece.Anyhow, computers are so helpful "
"that they do bring happiness.";
int textSize = text.size();//test
string huffmanText;//得到编码后的文本
for (auto ch : text) {
string str(1,ch);
int find = 0;
for (int i = 0; i < NODE_NUM; ++i) {
if (pHuffmanTree[i].text == str) {
huffmanText = huffmanText + pHuffmanTree[i].huffmanCode;
find = 1;
break;
}
}
if (find == 0) {
huffmanText = huffmanText + str;
}
}
int huffmanTextSize = huffmanText.size();
cout << huffmanText << endl;
//对哈夫曼编码文本进行解码
//哈夫曼二叉树的根结点为数组的最后一个结点
string decodingText;//得到解码后的文本
for (int i = 0; i < huffmanText.size(); ++i) {
if (huffmanText[i] != '0' && huffmanText[i] != '1') {
decodingText = decodingText + huffmanText[i];
continue;
}
HTNode node= pHuffmanTree[2 * NODE_NUM - 2];
int index = -1;
while (node.lch !=-1) //如果当前结点不是叶子结点(哈夫曼二叉树中只有度为0或2的结点)
{
if (huffmanText[i] == '0') {
node = pHuffmanTree[node.lch];
}
else if (huffmanText[i] == '1') {
node = pHuffmanTree[node.rch];
}
i++;
}
decodingText = decodingText + node.text;
--i;
}
cout << decodingText << endl;
}
哈夫曼二叉树编码
于 2022-06-27 16:26:16 首次发布