您的位置:首页 > 其它

建立哈夫曼树,求哈夫曼编码

2012-10-21 12:10 471 查看
/*建立哈夫曼树,就是每次从所有节点中选取两个权值最小且没有父亲的节点
*然后用这两个节点作为新节点的两个子树,新节点的权值等于两子树之和
*重复这个操作直到所有总节点数等于2*n-1
*
*/
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

typedef struct node{
int weight;
int parent,lchild,rchild;
}HTNode,*HaffmanTree;

typedef char **HaffmanCode;

void select(HaffmanTree T, int n, int *s1, int *s2);    //选取haffmanTree中权重最小的两个节点位置
void haffmanCoding(HaffmanTree *T, HaffmanCode *HC, int *w, int n); //建立haffmantree,求haffmancode

void select(HaffmanTree T, int n, int *s1, int *s2){
int min=32767,nmin=32767;
int vmin=0,vnmin=0;
for(int i=0; i<n; i++){
if(T[i].parent!=0) continue;
if(min>T[i].weight){
min = T[i].weight;
vmin = i;
}else if(nmin>T[i].weight){
nmin = T[i].weight;
vnmin = i;
}
}

*s1 = vmin,*s2 = vnmin;
}

void haffmanCoding(HaffmanTree *T, HaffmanCode *HC, int *w, int n){ //w存放n个字符的权值
if(n<=1) return;

int i, s1, s2;
int m = 2*n-1;

*T = (HaffmanTree)malloc(sizeof(HTNode) * m);

HaffmanTree p = *T;
for(i=0; i<n; i++,p++,w++) *p = {*w,0,0,0};    //为前n个节点的weight赋值
for(;i<m;i++,p++) *p = {0,0,0,0};   //将n~2*n-1的节点初始化
for(i=n; i<m; i++){
select(*T,i,&s1,&s2);   //悬着parent为0且weight最小的两个节点
(*T)[s1].parent = i; (*T)[s2].parent = i;
(*T)[i].lchild = s1; (*T)[i].rchild = s2;
(*T)[i].weight = (*T)[s1].weight+(*T)[s2].weight;
}

//从叶子到根逆向求haffmancode
*HC = (HaffmanCode)malloc(sizeof(char *) * n);  //非配n个字符编码的头指针向量
char *code = (char *)malloc(sizeof(char)*n);    //非配临时存储编码的空间
code[n-1] = '\0';

int current,currentp;
for(i=0; i<n; i++){
int start = n-1;
for(current =i,currentp=(*T)[i].parent; currentp!=0; current=currentp,currentp=(*T)[currentp].parent){
if((*T)[currentp].lchild==current) code[--start] = '0';
else code[--start] = '1';
}
(*HC)[i] = (char *)malloc(sizeof(char) * (n-start));    //为第i个字符编码分配空间
strcpy((*HC)[i], &code[start]);     //将编码复制到HC
}
free(code); //释放工作空间
}

int main(){
int w[5] = {4,6,8,1,3};
HaffmanTree HT;
HaffmanCode HC;
haffmanCoding(&HT, &HC, w, 5);
for(int i=0; i<9; i++){
printf("%d\t",HT[i].weight);
}
printf("\n");
for(int i=0; i<5; i++)    printf("%s\n",HC[i]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: