#include "stdafx.h"
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
typedef struct HTNode* PtrToHTNode;
typedef char** HuffmanCodes;
typedef char* HuffmanCode;
struct HTNode
{
int weight;
PtrToHTNode lchild, rchild, parent;
};
struct HuffmanTree
{
PtrToHTNode root=NULL;
vector<PtrToHTNode>nodes;
};
void initHTNode(PtrToHTNode &h, int x);
void initHuffmanTree(HuffmanTree &hftree, int n);
void selectMin(HuffmanTree &hftree, int i, int &s1, int &s2);
void createHuffmanTree(HuffmanTree& hftree, HuffmanCodes& codes, int& n);
void levelOrderTraversal(HuffmanTree hftree);
void _levelOrderTraversal(PtrToHTNode p);
void reverseCharArray(char* c, int n);
HuffmanCode getHuffmanCode(HuffmanTree hftree, int i, int n);
HuffmanCodes getHuffmanCodes(HuffmanTree hftree, int num_of_leaves);
int decode(HuffmanTree hftree, HuffmanCode hcode);
int main()
{
HuffmanTree h;
HuffmanCodes codes;
int n;//叶子个数
createHuffmanTree(h,codes,n);
printf("层序遍历此哈夫曼树:");
levelOrderTraversal(h);
printf("\n");
for (int i = 0; i < n; i++)
{
printf("%d : %s\n",h.nodes[i]->weight,codes[i]);
}
printf("输入编码:");
HuffmanCode code=new char[n+1];
scanf("%s", code);
printf("编码 %s 对应的元素为: %d \n", code, decode(h,code));
return 0;
}
void initHTNode(PtrToHTNode &h,int x)
{
h = new HTNode();
h->weight = x;
h->parent = h->lchild = h->rchild = NULL;
}
void initHuffmanTree(HuffmanTree &hftree, int n)
{
PtrToHTNode h=NULL;
int tmp_weight;
for (int i = 0; i < n; i++)
{
printf("第%d个结点的权值:", i + 1);
scanf("%d", &tmp_weight);
initHTNode(h, tmp_weight);
hftree.nodes.push_back(h);
}
}
void selectMin(HuffmanTree &hftree,int i,int &s1, int &s2)
{
//在hftree.nodes[0...i]中选择权值最小两个结点, s1是最小权值结点序号,s2是次小权值结点序号
int index = 0;
while (hftree.nodes[index]->parent) index++;//找到vector中第一个根结点
s1 = index;
for (int j = 0; j < i; j++)
{
PtrToHTNode current_node = hftree.nodes[j];
int current_weight = current_node->weight;
if (!current_node->parent&¤t_weight <= hftree.nodes[s1]->weight)s1 = j;
}
index = 0;
while (hftree.nodes[index]->parent || index == s1)index++;
s2 = index;
for (int j = 0; j < i; j++)
{
PtrToHTNode current_node = hftree.nodes[j];
int current_weight = current_node->weight;
if (!current_node->parent&¤t_weight <= hftree.nodes[s2]->weight&&j!=s1)s2 = j;
}
}
void createHuffmanTree(HuffmanTree &hftree,HuffmanCodes& codes,int& n)
{
int s1,s2;
scanf("%d", &n);
initHuffmanTree(hftree,n);
PtrToHTNode h=NULL;
for (int i = n; i < 2*n - 1; i++)
{
selectMin(hftree, i, s1, s2);
initHTNode(h,hftree.nodes[s1]->weight+hftree.nodes[s2]->weight);
h->lchild = hftree.nodes[s1];
h->rchild = hftree.nodes[s2];
hftree.nodes[s1]->parent = hftree.nodes[s2]->parent = h;
hftree.nodes.push_back(h);
}
hftree.root = hftree.nodes[2*n - 2];
codes = getHuffmanCodes(hftree, n);
}
void levelOrderTraversal(HuffmanTree hftree)
{
_levelOrderTraversal(hftree.root);
}
void _levelOrderTraversal(PtrToHTNode p)
{
queue<PtrToHTNode>myqueue;
if (!p)return;
myqueue.push(p);
printf("%d ", p->weight);
while (!myqueue.empty())
{
PtrToHTNode p = myqueue.front();
myqueue.pop();
if (p->lchild)
{
myqueue.push(p->lchild);
printf("%d ", p->lchild->weight);
}
if (p->rchild)
{
myqueue.push(p->rchild);
printf("%d ", p->rchild->weight);
}
}
}
HuffmanCode getHuffmanCode(HuffmanTree hftree, int i,int n)
{
//返回第i片叶子的哈夫曼编码(字符数组形式)
PtrToHTNode p = hftree.nodes[i];
int max_height = n - 1,count=0;
char* res=new char[max_height];
while (p->parent)
{
PtrToHTNode parent = p->parent;
if (parent->lchild == p)res[count++] = '0';
else res[count++] = '1';
p = parent;
}
reverseCharArray(res, count);
res[count] = '\0';
return res;
}
HuffmanCodes getHuffmanCodes(HuffmanTree hftree, int num_of_leaves)
{
HuffmanCodes res = new HuffmanCode[num_of_leaves];
for (int j = 0; j < num_of_leaves; j++)
{
HuffmanCode code = getHuffmanCode(hftree, j, num_of_leaves);
res[j] = code;
}
return res;
}
void reverseCharArray(char* c, int n)
{
int mid = n / 2;
for (int i = 0; i < mid; i++)
{
char tmp = c[i];
c[i] = c[n - 1 - i];
c[n - 1 - i] = tmp;
}
}
int decode(HuffmanTree hftree, HuffmanCode hcode)
{
//n为编码长度
PtrToHTNode p1 = hftree.root;
for (int i = 0;hcode[i]!='\0'; i++)
{
if (hcode[i] == '0')p1 = p1->lchild;
else p1 = p1->rchild;
}
return p1->weight;
}
运行效果: