哈夫曼编码
等长编码:占的位置一样
变长编码(不等长编码):经常使用的编码比较短,不常用的比较短
最优:总长度最短
最优的要求:占用空间尽可能短,不占用多余空间,且不能有二义性
这里给出哈夫曼二叉树的实现:
HuffmanTree.h:
#pragma oncetemplate <typename T>
class HuffmanTree {
public:HuffmanTree(int nCount, T* InData, int* InWeight);
private:typedef struct _HuffNode {T tValue;int weight;int n_lChild;int n_rChild;int n_Father;}Tree, *pTree;pTree m_pTreeRoot;int nTreeCount;
public:void show();void HuffmanCode(char** &InHuffmanCode,int nCount);
private:void select(int nCount, int* SmallValueA_Index, int* SmallValueB_Index);
};template<typename T>
inline HuffmanTree<T>::HuffmanTree(int nCount, T * InData, int* InWeight)
{nTreeCount = 2 * nCount;m_pTreeRoot = (pTree)calloc(nTreeCount + 1, sizeof(Tree));for (size_t i = 1; i <= nCount; i++) {m_pTreeRoot[i].tValue = InData[i-1];m_pTreeRoot[i].weight = InWeight[i-1];}for (size_t i = nCount + 1; i < nTreeCount; i++) {int SmallValueA_Index;int SmallValueB_Index;select(i - 1, &SmallValueA_Index, &SmallValueB_Index);m_pTreeRoot[SmallValueA_Index].n_Father = i;m_pTreeRoot[SmallValueB_Index].n_Father = i;m_pTreeRoot[i].n_lChild = SmallValueA_Index;m_pTreeRoot[i].n_rChild = SmallValueB_Index;m_pTreeRoot[i].weight = m_pTreeRoot[SmallValueA_Index].weight + m_pTreeRoot[SmallValueB_Index].weight;m_pTreeRoot[i].tValue = '0';}}template<typename T>
inline void HuffmanTree<T>::show()
{std::cout << "Index" << " " << "Value" << " " << "weight" << " " << "ParentIndex" << " " << "lChild" << " " << "rChild" << " " << std::endl;for (size_t i = 1; i < nTreeCount; i++) {printf("%-5.0d %-5c %-6d %-11d %-6d %-6d\r\n", i, m_pTreeRoot[i].tValue, m_pTreeRoot[i].weight, m_pTreeRoot[i].n_Father, m_pTreeRoot[i].n_lChild, m_pTreeRoot[i].n_rChild); }
}template<typename T>
inline void HuffmanTree<T>::HuffmanCode(char **& InHuffmanCode, int nCount)
{InHuffmanCode = (char**)malloc(sizeof(char*)*(nCount + 1));char* code = (char*)malloc(nCount);code[nCount-1] = '\0';for (size_t i = 1; i <= nCount; i++) {int cha = i;int parent = m_pTreeRoot[i].n_Father;int start = nCount - 1;while (parent) {if (m_pTreeRoot[parent].n_lChild == cha) {code[--start] = '0';}else {code[--start] = '1';}cha = parent;parent = m_pTreeRoot[parent].n_Father;}InHuffmanCode[i] = (char*)malloc(nCount - start);strcpy(InHuffmanCode[i], &code[start]);}
}template<typename T>
inline void HuffmanTree<T>::select(int nCount, int * SmallValueA_Index, int * SmallValueB_Index)
{int nMin;for (size_t i = 1; i < nCount; i++) {if (m_pTreeRoot[i].n_Father == 0) {nMin = i;break;}}for (size_t i = nMin + 1; i <= nCount; i++) {if (m_pTreeRoot[i].n_Father == 0 && m_pTreeRoot[i].weight < m_pTreeRoot[nMin].weight) {nMin = i;}}*SmallValueA_Index = nMin;for (size_t i = 1; i <= nCount; i++){if (m_pTreeRoot[i].n_Father == 0 && i != *SmallValueA_Index){nMin = i;break;}}for (size_t i = nMin + 1; i <= nCount; i++){if (m_pTreeRoot[i].n_Father == 0 && m_pTreeRoot[i].weight < m_pTreeRoot[nMin].weight && i != *SmallValueA_Index){nMin = i;}}*SmallValueB_Index = nMin;
}
测试数据(主函数):
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include "HuffmanTree.h"int main() {char a[] = { 'A','B','C','D','E','F' };int b[] = { 5,32,18,7,25,13 };HuffmanTree<char> arr(6, a, b);arr.show();char** HuffmanCode = nullptr;arr.HuffmanCode(HuffmanCode,6);std::cout << "编码值:" << std::endl;for (size_t i = 1; i <= 6; i++){printf(" %c: %s\n",a[i-1],HuffmanCode[i]);}return 0;
}
运行结果截图:
如果发现文章中有错误,还请大家指出来,我会非常虚心地学习,我们一起进步!!!