哈夫曼编码方法:
1、统计字符集中每个字符在电文中出现的平均概率(概率越大,要求编码越短)。
2、利用哈夫曼树的特点:权越大的叶子离根越近;将每个字符的概率值作为权值,构造哈夫曼树。则概率越大的结点,路径越短。
3、在哈夫曼树的每个分支上标上0或1,结点的左分支标0,右分支标1,把从根到每个叶子的路径上的标号连接起来,作为该叶子代表的字符的编码。
哈夫曼解码方法:
根据编码规则在哈夫曼树中寻找叶子结点。
代码实现:
类型定义以及宏定义:
#define ArraySize 8
typedef struct HuffmanEnCode
{
int uncode;
int start;
char code[ArraySize];
} HuffmanEnCode; // 哈夫曼编码结果数组类型定义
typedef struct HuffmanDecode
{
char code[ArraySize];
int uncode;
} HuffmanDeCode; // 哈夫曼解码结果数组类型定义
主函数:
int main()
{
//------------------------------创建哈夫曼树----------------------------------//
int WeightArray[ArraySize] = {7, 19, 2, 6, 32, 3, 21, 10}; // 权重数组
HuffmanTreeNode HTree[2 * ArraySize]; // 创建哈夫曼树的存储结构体数组
InitHuffmanTree(HTree, 2 * ArraySize); // 初始化结构体数组
CreateHuffmanTree(WeightArray, ArraySize, HTree); // 创建哈夫曼树
Print(HTree, 2 * ArraySize); // 打印结果
printf("\n");
//------------------------------哈夫曼编码----------------------------------//
HuffmanEnCode HC[ArraySize + 1]; // 哈夫曼编码结果数组
GenerateHuffmanCode(HTree, HC); // 哈夫曼编码
Show1(HC); // 编码结果显示
printf("\n");
//------------------------------哈夫曼解码----------------------------------//
HuffmanDeCode HDC[ArraySize + 1]; // 哈夫曼解码结果数组
Huffman_Decoding(HTree, HC, HDC); // 哈夫曼解码
Show2(HDC); // 解码结果显示
printf("\n");
return 0;
}
创建哈夫曼树的内容:https://blog.csdn.net/m0_69251699/article/details/130670917
所创建的哈夫曼树的示意图:
哈夫曼编码函数:
void GenerateHuffmanCode(HuffmanTreeNode *Tree, HuffmanEnCode *HC)
{
int Parent, Child, i, j;
for (i = 1; i <= ArraySize; i++)
{
HC[i].uncode = Tree[i].weight;
HC[i].code[ArraySize - 1] = '\0';
j = ArraySize - 2;
Parent = Tree[i].parent;
Child = i;
while (Parent != 0)
{
if (Tree[Parent].left == Child)
{
HC[i].code[j] = '0';
}
else
{
HC[i].code[j] = '1';
}
Child = Parent;
Parent = Tree[Parent].parent;
j--;
}
HC[i].start = j + 1;
}
}
哈夫曼编码结果显示函数:
void Show1(HuffmanEnCode *HC)
{
printf("uncode\t\tcode\n");
for (int i = 1; i <= ArraySize; i++)
{
printf("%d\t\t%s\n", HC[i].uncode, HC[i].code + HC[i].start);
}
}
哈夫曼解码函数:
void Huffman_Decoding(HuffmanTreeNode *Tree, HuffmanEnCode *HC, HuffmanDeCode *HDC)
{
int i, j, point;
for (i = 1; i <= ArraySize; i++)
{
strcpy(HDC[i].code, HC[i].code + HC[i].start);
j = 0;
point = RootNode(Tree);
while (HDC[i].code[j] != '\0')
{
if (HDC[i].code[j] == '0')
{
point = Tree[point].left;
}
else
{
point = Tree[point].right;
}
j++;
}
HDC[i].uncode = Tree[point].weight;
}
}
根结点寻找函数:
int RootNode(HuffmanTreeNode *Tree)
{
for (int i = 1; i < 2 * ArraySize; i++)
{
if (Tree[i].parent == 0)
{
return i;
}
}
}
哈夫曼解码结果显示函数:
void Show2(HuffmanDeCode *HDC)
{
printf("code\t\tuncode\n");
for (int i = 1; i <= ArraySize; i++)
{
printf("%s\t\t%d\n", HDC[i].code, HDC[i].uncode);
}
}
程序运行结果:
哈夫曼树创建结果:
哈夫曼编码结果:
哈夫曼解码结果: