标题：最简哈夫曼树
简介
首先要了解树的概念。树并不是指植物，而是一种数据结构，因为其存放方式颇有点象一棵树有树叉因而称为树。  哈夫曼树最简哈夫曼树是由德国数学家冯 哈夫曼 发现的，此树的特点就是引出的路程最短。它的形状单支形式。
数对于编程具有重大的意义，是某些看似不可能完成或是很难完成的任务较为简单，有条理的完成。
首先要了解树的概念。树并不是指植物，而是一种数据结构，因为其存放方式颇有点象一棵树有树叉因而称为树。
哈夫曼树又称最优二叉树，是一种带权路径长最短的树。树的路径长度是从树根到每一个叶子之间的路径长度之和。节点的带树路径长度为从该节点到树根之间的路径长度与该节点权（比如字符在某串中的使用频率）的乘积。
应用
#include<stdio.h>
最简哈夫曼树
#include<stdlib.h>
#include<string.h>
#include<conio.h>a
#include<graphics.h>
#define MAXVALUE 200 /*权值的最大值*/
#define MAXB99v 30 /*最大的编码位数*/
#define MAXNODE 30 /*初始的最大的结点数*/
struct haffnode
{char data;
int weight;
int flag;
int parent; /*双亲结点的下标*/  哈夫曼树int leftchild; /*左孩子下标*/
int rightchild; /*右孩子下标*/
};
struct haffcode
{int bit[MAXNODE];
int start; /*编码的起始下标*/
char data;
int weight; /*字符权值*/
};
构建
/*函数说明*/
最简哈夫曼树
/************************************************************************/
void pprintf(struct haffcode haffcode[],int n);
/*输出函数*/
void haffmantree(int weight[],int n,struct haffnode hafftree[],char data[]);
/*建立哈夫曼树*/
void haffmancode(struct haffnode hafftree[],int n,struct haffcode haffcode[]);
/*求哈夫曼编码*/
void test(struct haffcode haffcode[],int n);
/*测试函数*/
void end();
/*结束界面函数*/
/************************************************************************/void haffmantree(int weight[],int n,struct haffnode hafftree[],char data[])
/*建立叶结点个数为n，权值数组为weight[]的哈夫曼树*/
{int i,j,m1,m2,x1,x2;
/*哈夫曼树hafftree[]初始化，n个叶结点共有2n-1个结点*/
for(i=0;i<2*n-1;i++)
{if(i<n) {hafftree[i].data=data[i];
hafftree[i].weight=weight[i]; /*叶结点*/
}
else {hafftree[i].weight=0; /*非叶结点*/
hafftree[i].data='\0';
}
hafftree[i].parent=0; /*初始化没有双亲结点*/
hafftree[i].flag=0;
hafftree[i].leftchild=-1;
sp; hafftree[i].rightchild=-1;
}
for(i=0;i<n-1;i++) /*构造哈夫曼树n-1个非叶结点*/
编码
本文描述在网上能够找到的最简单，最快速的哈夫曼编码。该方法不使用任何扩展动态库，比如STL或者组件。只使用简单的C函数，比如：memset，memmove，qsort，malloc，realloc和memcpy。
因此，大家都会发现，理解甚至修改这个编码都是很容易的。
背景
哈夫曼压缩是个无损的压缩算法，一般用来压缩文本和程序文件。哈夫曼压缩属于可变代码长度算法一族。意思是个体符号（例如，文本文件中的字符）用一个特定长度的位序列替代 
  哈夫曼树。因此，在文件中出现频率高的符号，使用短的位序列，而那些很少出现的符号，则用较长的位序列。编码使用
我用简单的C函数写这个编码是为了让它在任何地方使用都会比较方便。你可以将他们放到类中，或者直接使用这个函数。并且我使用了简单的格式，仅仅输入输出缓冲区，而不象其它文章中那样，输入输出文件。
bool CompressHuffman(BYTE *pSrc,int nSrcLen,BYTE *&pDes,int &nDesLen);bool DecompressHuffman(BYTE *pSrc,int nSrcLen,BYTE *&pDes,int &nDesLen);
要点说明 
速度
为了让它（huffman.cpp）快速运行，我花了很长时间。同时，我没有使用任何动态库，比如STL或者MFC。它压缩1M数据少于100ms（P3处理器，主频1G）。
压缩
压缩代码非常简单，首先用ASCⅡ值初始化511个哈夫曼节点：
CHuffmanNode nodes[511];for(int nCount = 0; nCount < 256; nCount++) nodes[nCount].byAscii = nCount；然后，计算在输入缓冲区数据中，每个ASCⅡ码出现的频率：for(nCount = 0; nCount < nSrcLen; nCount++) nodes[pSrc[nCount]].nFrequency++；然后，根据频率进行排序：qsort(nodes,256,sizeof(CHuffmanNode),frequencyCompare）；现在，构造哈夫曼树，获取每个ASCⅡ码对应的位序列：int nNodeCount = GetHuffmanTree(nodes）；构造哈夫曼树非常简单，将所有的节点放到一个队列中，用一个节点替换两个频率最低的节点，新节点的频率就是这两个节点的频率之和。这样，新节点就是两个被替换节点的父节点了。如此循环，直到队列中只剩一个节点（树根）。// parent nodepNode = &nodes[nParentNode++];// pop first childpNode->pLeft = PopNode(pNodes,nBackNode--,false);// pop second childpNode->pRight = PopNode(pNodes,nBackNode--,true);// adjust parent of the two poped nodespNode->pLeft->pParent = pNode->pRight->pParent = pNode;// adjust parent frequencypNode->nFrequency = pNode->pLeft->nFrequency + pNode->pRight->nFrequency；这里我用了一个好的诀窍来避免使用任何队列组件。我先前就直到ASCⅡ码只有256个，但我分配了511个（CHuffmanNode）
两个变量来操作队列索引（int nParentNode = nNodeCount;nBackNode = nNodeCount –1）。
接着，压缩的最后一步是将每个ASCⅡ编码写入输出缓冲区中：int nDesIndex = 0;// loop to write codesfor(nCount = 0; nCount < nSrcLen; nCount++){ *(DWORD*)(pDesPtr+(nDesIndex>>3）） |= nodes[pSrc[nCount]].dwCode << (nDesIndex&7）； nDesIndex += nodes[pSrc[nCount]].nCodeLength;}(nDesIndex>>3）： >>3 以8位为界限右移后到达右边字节的前面 
（nDesIndex&7）： &7 得到最高位. 注意：在压缩缓冲区中，我们必须保存哈夫曼树的节点以及位序列，这样我们才能在解压缩时重新构造哈夫曼树（只需保存ASCⅡ值和对应的位序列）。
解压缩
解压缩比构造哈夫曼树要简单的多，将输入缓冲区中的每个编码用对应的ASCⅡ码逐个替换就可以了。只要记住，这里的输入缓冲区是一个包含每个ASCⅡ值的编码的位流。因此，为了用ASCⅡ值替换编码，我们必须用位流搜索哈夫曼树，直到发现一个叶节点，然后将它的ASCⅡ值添加到输出缓冲区中：
int nDesIndex = 0;DWORD nCode;while(nDesIndex < nDesLen){ nCode = (*(DWORD*)(pSrc+(nSrcIndex>>3）））>>(nSrcIndex&7）； pNode = pRoot; while(pNode->pLeft) { pNode = (nCode&1） pNode->pRight : pNode->pLeft; nCode >>= 1; nSrcIndex++; } pDes[nDesIndex++] = pNode->byAscii;}(nDesIndex>>3）： >>3 以8位为界限右移后到达右边字节的前面 (nDesIndex&7）： &7 得到最高位. [1]