找了一圈发现网上大部分赫夫曼树都是顺序存储,记录一下使用指针的赫夫曼树。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAXSIZE 1000
typedef struct huffNode
{
char data;
int weight;
struct huffNode *lch,*rch,*parent;
}huffNode,*huffTree;
typedef struct
{
huffTree tree;
char **list;
}realTree;//这个结构体不重要,为了方便一点而已
void pre(huffTree H);//遍历
char **init(huffTree *H);//初始化,该函数结束之后H是树,返回值是根据树建立的码表
void sort(huffTree node[],int num);//init的辅助子函数
char *get(huffTree H,huffTree *tempUse,int position);//init的辅助子函数,返回树中某个字符的码表
void code(realTree T);//赫夫曼编码函数
void print(char *lineList);//code的辅助子函数,打印某个字符的码
void encode(realTree T);//赫夫曼译码函数
int main()
{
realTree t1;
t1.list=init(&t1.tree);
encode(t1);
return 0;
}
void pre(huffTree H)
{
if(H!=NULL)
{
printf("%c",H->data);
pre(H->lch);
pre(H->rch);
}
}
char **init(huffTree *H)
{
int i,j;
//得到字符集字符数量
int num;
printf("Enter character number>");
scanf("%d",&num);
getchar();//去除换行符
//输入每个字符及其权值
char ch[num];
int weight[num];
printf("Enter each character and weight>\n");
for(i=0;i<num;i++)
{
scanf("%c",&ch[i]);
scanf("%d",&weight[i]);
getchar();
}
//建立每个节点
huffTree node[num];
huffTree tempUse[num];//这一步用不到,下面"给每个字符编码"环节用
for(i=0;i<num;i++)
{
node[i]=(huffTree)malloc(sizeof(huffNode));
node[i]->data=ch[i];
node[i]->weight=weight[i];
//左右孩子还是初始化一下好,防止要使用
node[i]->lch=NULL;
node[i]->rch=NULL;
tempUse[i]=node[i];
}
//建立整棵树
huffTree UP;
for(i=num;i>1;i--)
{
sort(node,i);
UP=(huffTree)malloc(sizeof(huffNode));
UP->data=0;
UP->weight=node[i-2]->weight+node[i-1]->weight;
UP->lch=node[i-2];
UP->rch=node[i-1];
node[i-2]->parent=UP;//反正下个循环也会sort到合适的地方
node[i-1]->parent=UP;
node[i-2]=UP;
node[i-1]=NULL;//这个指针不再使用,防止意外置为空
}
UP->data=num;
(*H)=UP;
//给每个字符编码
char **list=(char**)malloc(sizeof(char*)*num);
char temp;
int length;
for(i=0;i<num;i++)
{
list[i]=get(UP,tempUse,i);
length=strlen(list[i]);
for(j=1;j<=length/2;j++)
{
temp=list[i][j];
list[i][j]=list[i][length-j];
list[i][length-j]=temp;
}
}
return list;
}
void sort(huffTree node[],int num)
{
huffTree temp;
for(int i=0;i<=num-2;i++)
for(int j=i+1;j<=num-1;j++)
{
if(node[i]->weight<node[j]->weight)
{
temp=node[i];
node[i]=node[j];
node[j]=temp;
}
}
}
char *get(huffTree H,huffTree *tempUse,int position)
{
int order;//计数器
int length=H->data+1;
char *ret=(char*)malloc(sizeof(char)*length);
ret[0]=tempUse[position]->data;
for(order=1;order<length;order++)ret[order]=0;
huffNode *ptr=tempUse[position];//可以用huffTree,为了表明是个指针用了huffNode*
huffNode *pre=ptr;
order=1;
while(ptr!=H)
{
ptr=ptr->parent;
if(ptr->lch==pre)ret[order]='0';
else ret[order]='1';
pre=ptr;
order++;
}
return ret;
}
void code(realTree T)
{
char str[MAXSIZE];
printf("Enter coding string>");
scanf("%s",str);
int i,j;
int stringLen=strlen(str);
int listLen=T.tree->data;
printf("Huffcode>\n");
for(i=0;i<stringLen;i++)
{
for(j=0;j<listLen;j++)
{
if(T.list[j][0]==str[i])
{
print(T.list[j]);
}
}
}
}
void print(char *lineList)//这个函数其实没那么必要,只是为了code函数里结构清晰一些
{
int length=strlen(lineList);
for(int i=1;i<length;i++)
{
printf("%c",lineList[i]);
}
}
void encode(realTree T)
{
char code[MAXSIZE];
printf("Enter code>");
scanf("%s",code);
huffNode *ptr=T.tree;
for(int i=0;code[i]!=0;i++)
{
if(code[i]=='0')ptr=ptr->lch;
else ptr=ptr->rch;
if(ptr!=T.tree&&ptr->data!=0)
{
printf("%c",ptr->data);
ptr=T.tree;
}
}
}
/*
5
a 5
b 4
c 4
d 2
e 1
//下面的根据运行的函数输入
aedcbadbecbea//函数code
0011111010010011001111100111100//函数encode
*/