哈夫曼树编码:从根节点开始,按左子树为'0',右子树为'1'编码,最后找到叶子节点的编码
#include <stdio.h> #include <malloc.h> #include <conio.h> #include <string.h> #include <iostream> using namespace std; #define MAX_LENGTH 100//叶子节点的最大数量 typedef char **HuffmanCode; typedef struct HTNode{ unsigned int weight;//该节点所占的权重 unsigned int parent,lchild,rchild;// 该节点的父节点,左孩子,右孩子 HTNode(unsigned int a,unsigned int b,unsigned int c,unsigned int d){ weight=a,parent=b,lchild=c,rchild=d; } }HTNode,*HuffmanTree; void Select(HuffmanTree HT,int i,int &s1,int &s2){//把没有父节点的所有节点中最小的两个值赋值给s1,s2 int j,k = 1; while(HT[k].parent) //找最小的父节点为0,即没有父节点的点 k++; s1 = k; for(j = 1;j <= i;j++) if(!HT[j].parent && HT[j].weight<HT[s1].weight)//找父节点为0的所有节点中的最小值,赋给s1 s1 = j; k = 1; while(HT[k].parent || k==s1)//找最小的父节点为0,即没有父节点的点,且不等于s1 k++; s2 = k; for(j = 1;j <= i;j++) if(!HT[j].parent && HT[j].weight<HT[s2].weight && j!=s1)//找父节点为0的所有节点中的不为s1的最小值,赋给s2 s2 = j; } void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w,int n){//创建哈夫曼树 if(n<=1) return;//只有一个节点,直接作为根节点返回,其他情况直接返回 int m,i,s1,s2,start,c,f; HuffmanTree p; m = 2*n-1;//哈夫曼树的总节点数量 for(p = HT+1,i=1;i<=n;i++,p++,w++){//给前n个节点赋值 *p=HTNode(*w,0,0,0); cout<<endl<<"HT["<<i<<"].weight="<<p->weight<<" ";//输出每个节点的权值 } for(;i<=m;i++,p++) *p=HTNode(0,0,0,0);//给后面m-n个节点赋值 cout<<endl<<endl<<"HuffmanTree is created in following order :"; for(i = n+1;i<=m;i++){ Select(HT,i-1,s1,s2);//每次选择节点中最小的两个节点作为新树的左子树,右子树; // 把s1,s2作为节点i的左子树,右子树, HT[s1].parent = i,HT[s2].parent = i;//给s1,s2的父节点赋值 HT[i].weight=HT[s1].weight+HT[s2].weight;//计算节点i的权重 cout<<endl<<"HT["<<s1<<"] and HT[" <<s2<<"] create"; cout<<" HT["<<i<<"], weight="<<HT[i].weight; } //从叶子结点到根结点逆向求每个字符的哈夫曼编码 HC = (HuffmanCode)malloc((n+1)*sizeof(char *));//为数组HC开辟空间 char cd[MAX_LENGTH]; cd[n-1]=0;//编码结束符'\0'的ascii码为0 cout<<endl<<endl<<"HuffmanTree Code is as follows :"<<endl; for(i=1;i<=n;i++){//逐个字符求哈夫曼编码 start = n-1;//指向编码结束的位置 //每个节点的左子树编码为'0',右子树编码为'1', 按从根节点往下的顺序构造出叶子节点的编码 for(c=i,f=HT[i].parent;f;c=f,f=HT[f].parent)//从叶子节点一直找到根节点 if(HT[f].lchild==c) cd[--start]='0';//若为左子树,编码位置编为'0' else cd[--start]='1';//若为右子树,编码位置编为'1' HC[i]=(char *)malloc((n-start)*sizeof(char));//为第i个字符编码分配空间,n-start为第i个字符的编码长。 strcpy(HC[i],&cd[start]);//从cd复制编码(串)到HC printf("\nHT[%d] node 's Huffman code is: %s",i,HC[i]); } } int main() { HuffmanTree HT; HuffmanCode HC; int n,i; int *w,W[MAX_LENGTH];//W保存叶子节点的权值 cout<<endl<<endl<<"HuffmanCoding.cpp"; cout<<endl<<"============="<<endl; cout<<endl<<"Please input the number of the element of HuffmanTree (eg.5):"; cin>>n;//输入叶子节点的数量 for(i = 0;i < n;i++){ cout<<"Please input the weight of the "<<i+1<<"th element (eg.8):"; cin>>W[i];//输入每个叶子节点的权值 } w = W; HuffmanCoding(HT,HC,w,n);//创建n个叶子节点构成的哈夫曼树 cout<<endl<<endl<<"...OK!...";//创建成功 getch(); return 0; }
文章来源: 哈夫曼树的创建及编码