哈夫曼编码的贪心算法 二叉树结构表示
实验内容:
[参考数据类型或变量]
typedef ElemType char;
typedef struct node{
int w;
int flag;
ElemType c;
struct node *plink,*llink,*rlink;
char code[m];
}Node;
Node *num[n], *root;
[参考子程序接口与功能描述]
void SetTree( NODE *root )
功能: 从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树
void EnCode( Node *p )
功能: 利用已建好的哈夫曼树,对输入的正文进行编码
void DeCode( void )
功能: 利用已建好的哈夫曼树,将输入的代码进行译码
程序源代码
#include<bits/stdc++.h>
#define maxn 20 //最大结点数目
#define inf 0xfffffff //无穷大
typedef struct node {
double w; //权值
int flag;
int c;
struct node *plink,*llink,*rlink;
char code[maxn];
int codelen;
node(){ //初始化节点
flag=0;
llink=NULL;
plink=NULL;
rlink=NULL;
codelen=0;
}
}node;
node *num[2*maxn-1];//指针数组
int n;
void SetTree(node *&root){//从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树
scanf("%d",&n);
for(int i = 0; i < n;i++){
num[i] = new node();
num[i]->c = i;
scanf("%lf",&num[i]->w); //输入权重
}
int m = n;
double min1 , min2;
int pos1 = 0, pos2 = 0;
for(int i = 0; i < m-1;i++){
//找到最小两个节点
min1 = inf; min2 = inf;
for(int j = 0; j < n; j++){
if(num[j]->flag == 0 ){
if(num[j]->w < min1){
min2 = min1;
min1 = num[j]->w;
pos2 = pos1;
pos1 = j;
}
else if(num[j]->w < min2){
min2 = num[j]->w;
pos2 = j;
}
}
}
//结点合并
num[pos1]->flag = 1;
num[pos2]->flag = 1;
num[n] = new node();
num[n]->c = -1;
num[n]->w = num[pos1]->w + num[pos2]->w;
num[n]->llink = num[pos1] ;
num[n]->rlink = num[pos2];
num[pos1]->plink = num[n];
num[pos2]->plink = num[n];
n++;
}
root = num[n-1];
n = m;
}
void Encode(node *&root,int deep, char code[]){//利用已建好的哈夫曼树,对输入的正文进行编码
if(root->c != -1){
for(int i = 0; i < deep;i++){
root->code[i] = code[i];
}
root->codelen = deep;
return;
}
code[deep] = '0'; //左节点编码0
Encode(root->llink,deep+1,code);
code[deep] = '1';//右节点编码 1
Encode(root->rlink,deep+1,code);
}
void DeCode(node *&root, char code[] ){ //利用已建好的哈夫曼树,将输入的代码进行译码
node *p = root;
int len = strlen(code);
int ans[maxn],anslen = 0;
for(int i = 0; i < len ; i++){
if(code[i] == '0'){
p = p->llink;
}
else p = p->rlink;
if(p->c != -1){
ans[anslen++] = p->c;
p = root;
}
if(p->llink == NULL || p->rlink == NULL){
printf("输入的数据不在哈夫曼树中\n");
return;
}
}
printf("输入的译码为:");
for(int i = 0; i < anslen; i++){
printf("%d",ans[i]);
}
printf("\n");
}
void print(){
for(int i= 0; i < n; i++){
printf("%.2f: ",num[i]->w);
for(int j = 0; j < num[i]->codelen;j++){
printf("%c",num[i]->code[j]);
}
printf("\n");
}
}
int main(){
node *root = NULL;
root = new node();
SetTree(root);
char code[maxn*maxn];
Encode(root,0,code);
print();
printf("按上述规则输入代码:\n");
scanf("%s",code);
DeCode(root,code);
return 0;
}