哈夫曼树:给定n个权值作为n个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,则称该二叉树为哈夫曼树,也被称为最优二叉树。
哈夫曼编码:对于任意一棵二叉树来说,把二叉树上的所有分支都进行编号,将所有左分支都标记为0,所有右分支都标记为1。
#include<iostream>
#include<queue>
using namespace std;
const int n = 8;//leaf
const int m = n * 2;//node
typedef unsigned int WeigthType;
typedef unsigned int NodeType;
typedef struct
{
WeigthType weigth;
NodeType parent, leftchild, rightchild;
}HTNode;
typedef HTNode HuffManTree[m];
typedef struct
{
char ch;
char code[n + 1];
}HuffCodeNode;
typedef HuffCodeNode HuffCoding[n + 1];
void printHuffManTree(HuffManTree hft)
{
for (int i = 1; i < m; ++i)
{
printf("index %3d weigth %3d parent %3d Lchild %3d Rchild %3d\n",
i, hft[i].weigth, hft[i].parent, hft[i].leftchild, hft[i].rightchild);
}
printf("\n");
}
void InitHuffManTree(HuffManTree hft, WeigthType w[])
{
//printf("HuffManTree:size %d\n", sizeof(HuffManTree)); 256
//printf("hft: size %d\n", sizeof(hft)); 4
//printf("w: size %d\n", sizeof(w)); 4
memset(hft, 0, sizeof(HuffManTree));
for (int i = 0; i < n; ++i)
{
hft[i + 1].weigth = w[i];
}
}
struct IndexWeigth
{
int index;
WeigthType weigth;
operator WeigthType() const { return weigth; };
};
void CreateHuffManTree(HuffManTree hft)
{
priority_queue<IndexWeigth, vector<IndexWeigth>, std::greater<IndexWeigth>> qu;
for (int i = 1; i <= n; ++i)
{
qu.push(IndexWeigth{ i, hft[i].weigth });
}
int k = n + 1;
while (!qu.empty())
{
if (qu.empty()) break;
IndexWeigth left = qu.top(); qu.pop();
if (qu.empty()) break;
IndexWeigth right = qu.top(); qu.pop();
hft[k].weigth = left.weigth + right.weigth;
hft[k].leftchild = left.index;
hft[k].rightchild = right.index;
hft[left.index].parent = k;
hft[right.index].parent = k;
qu.push(IndexWeigth{ k,hft[k].weigth });
k += 1;
}
}
void printHuffManCode(HuffCoding hc)
{
for (int i = 1; i <= n; ++i)
{
printf("data: %c => code: %s\n", hc[i].ch, hc[i].code);
}
printf("\n");
}
void InitHuffManCode(HuffCoding hc, const char* ch)
{
memset(hc, 0, sizeof(HuffCoding));
for (int i = 1; i <= n; ++i)
{
hc[i].ch = ch[i - 1];
hc[i].code[0] = '\0';
}
}
void CreateHuffManCode(HuffManTree hft, HuffCoding hc)
{
char code[n + 1] = { 0 };
for (int i = 1; i <= n; ++i)
{
int k = n;
code[k] = '\0';
int c = i;
int pa = hft[c].parent;
while (pa != 0)
{
code[--k] = hft[pa].leftchild == c ? '0' : '1';
c = pa;
pa = hft[c].parent;
}
strcpy_s(hc[i].code, n, &code[k]);
}
}
int main()
{
WeigthType w[n] = { 5,29,7,8,14,23,3,11 };
char ch[n+1] = {"ABCDEFGH"};
HuffManTree hft = { 0 };
HuffCoding hc = { 0 };
InitHuffManTree(hft, w);
InitHuffManCode(hc, ch);
printHuffManTree(hft);
printHuffManCode(hc);
CreateHuffManTree(hft);
CreateHuffManCode(hft, hc);
printHuffManTree(hft);
printHuffManCode(hc);
return 0;
}