是在学习数据结构(严蔚敏版)书中哈夫曼树及其应用后对书中伪代码的实现和完善,采用哈夫曼静态编码的方式,经过对数据进行两遍扫描,第一次统计出现的字符频次,进而构造哈夫曼树,第二遍扫描数据根据获得的哈夫曼树对数据进行编码。算法
对于其中的加密编码只是简单的将用户输入的密码用特殊的标识位拼接成字符串加入须要统计的数据,能够在拥有哈夫曼编码表以及加密后的文本状况下进行解密数据结构
给定n个权值做为n个叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。学习
假设有n个权值,则构造出的哈夫曼树有n个叶子结点。 n个权值分别设为 w一、w二、…、wn,则哈夫曼树的构造规则为: (1)
将w一、w二、…,wn当作是有n 棵树的森林(每棵树仅有一个结点); (2)
在森林中选出两个根结点的权值最小的树合并,做为一棵新树的左、右子树,且新树的根结点权值为其左、右子树根结点权值之和;
(3)从森林中删除选取的两棵树,并将新树加入森林; (4)重复(2)、(3)步,直到森林中只剩一棵树为止,该树即为所求得的哈夫曼树编码
在构造哈夫曼树时首先选择权小的,这样保证权大的离根较近,这种生成算法是一种典型的贪心法。加密
为了使压缩后的数据文件尽量短,可采用不定长编码。而为了在对压缩文件进行解码时不产生二义性,确保正确解码应该采用前缀编码的形式(即要求一个字符的编码不能是另外一个字符编码的前缀)。而哈夫曼编码是最优前缀编码。code
例如:有一个数据序列ABACCDAA则编码为A(0),B(10),C(110),(D111),压缩后为010011011011100。字符串
//哈夫曼树存储表示 typedef struct { int weight; //节点的权值 int parent,lchild,rchild; //节点的双亲,左孩子,右孩子的下标 } HTNode,*HuffmanTree; //存储数据扫瞄统计结果 typedef struct { char* data; int* num; int length; } TNode; //存储文件读入哈夫曼编码结果 typedef struct { char *data; char** HM; } Code; //存储哈夫曼编码结果 typedef char** HuffmanCode; //选取节点构造哈夫曼树 void Select(HuffmanTree &HT,int m,int& s1,int& s2) { int k,j,n,min=32767; for(k=1; k<=m; k++) { if(HT[k].parent==0) if(HT[k].weight<=min) { j=k; min=HT[k].weight; } } s1=j; HT[j].parent=1; min=32767; for(k=1; k<=m; k++) { if(HT[k].parent==0) if(HT[k].weight<=min) { n=k; min=HT[k].weight; } } s2=n; } //构造哈夫曼树 void CreateHuffmanTree (HuffmanTree &HT,TNode T,int length) { int m,i,s1,s2; //初始化 if(length<=1) return; m=2*length-1; HT=new HTNode[m+1]; for(i=1; i<=m; ++i) { HT[i].parent=0; HT[i].lchild=0; HT[i].rchild=0; } for(i=1; i<=length; ++i) HT[i].weight=T.num[i-1]; //经过n-1次的选择,删除,合并来建立哈夫曼树 for(i=length+1; i<=m; i++) { Select(HT,i-1,s1,s2); HT[s1].parent=i; HT[s2].parent=i; HT[i].lchild=s1; HT[i].rchild=s2; HT[i].weight=HT[s1].weight+HT[s2].weight; } } //从叶子到根逆向求每一个字符的哈夫曼编码,存储在编码表HC中 void CreatHuffmanCode (HuffmanTree HT,HuffmanCode &HC,int n) { int i,f,c,start; HC=new char*[n+1]; char* cd=new char[n]; cd[n-1]='\0'; for(i=1; i<=n; i++) { start=n-1; c=i; f=HT[i].parent; while(f!=0) { --start; if(HT[f].lchild==c) cd[start]='0'; else cd[start]='1'; c=f; f=HT[f].parent; } HC[i]=new char[n-start]; strcpy(HC[i],&cd[start]); } delete cd; }
有兴趣能够下载源码查看https://pan.baidu.com/s/1skAP5lrget
参考 数据结构:C语言版/严蔚敏,李冬梅,吴伟民编源码