哈夫曼编码的原理看
百度百科
先生成一个哈夫曼树,参考
哈夫曼树c语言实现
生成接近等长码
须要注意的是,为了缩短码长方差,且编出的码更接近于等长码,排序的时候,第一优先级为概率大小,第二优先级为左节点是否为空
int cmp(left a, left b)
{
if (a.data == b.data)
{
if (a.left != NULL)
{
return 1;
}
if (b.left != NULL)
{
return 0;
}
}
else
return a.data > b.data ? 1 : 0;
}
用dfs读取哈夫曼编码
读取哈夫曼编码的时候,从树的根部开始读,能往左走,就读入一个‘1’,能往右走就读入一个‘0’,遇上左节点为空,说明已经读取了一个编码,同时,我们读到的这个节点的概率就是这个编码对应的概率。
void print_treef(left* root,int n,int *now,int len)//就是dfs,
//函数中参数的含义依次为当前节点,编码总数(实际没有用),当前读取的编码编号,深度。
{
int t = 0;
if (root->left != NULL)
{
sprintf(temp+len, "%d", 1);
print_treef(root->left, n,now,len+1);
t = 1;
}
if (root->right != NULL)
{
sprintf(temp + len, "%d", 0);//相当于temp[len]=‘0’;
print_treef(root->right, n,now,len+1);
t = 1;
}
if (t == 0)
{
sprintf(ans[*now].code, "%s", temp);
ans[*now].p = root->data;
// ans[*now].code[len]= '\0';
*now += 1;
}
}
源代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct hahahacode
{
double p;
char code[10];
}Code;
Code ans[10];
typedef struct hahahahahaha
{
struct hahahahahaha* father;
struct hahahahahaha* left;
struct hahahahahaha* right;
double data;
}left;
left* creat_left()
{
left* s = (left*)malloc(sizeof(left));
s->father = NULL;
s->left = NULL;
s->right = NULL;
return s;
}
int cmp(left a, left b)
{
if (a.data == b.data)
{
if (a.left != NULL)
{
return 1;
}
if (b.left != NULL)
{
return 0;
}
}
else
return a.data > b.data ? 1 : 0;
}
void sortans(int n)
{
int i = 0, j = 0, t;
Code tt;
for (i = 0; i < n - 1; i++)
{
for (j = 0; j < n - 1-i; j++)
{
if (ans[j].p == ans[j + 1].p)
{
if (strcmp(ans[j].code, ans[j + 1].code) >= 0)
{
tt = ans[j], ans[j] = ans[j + 1]; ans[j + 1] = tt;
}
}
else if (ans[j].p<ans[j+1].p)
{
tt = ans[j], ans[j] = ans[j + 1]; ans[j + 1] = tt;
}
}
}// 蹩脚插排
}
void sort(left* a[], int n)
{
int i = 0, j = 0, t;
left* tt;
for (i = 0; i < n - 1; i++)
{
for (j = 0; j < n - 1-i; j++)
{
if (cmp(*a[j], *a[j + 1]))
{
tt = a[j], a[j] = a[j + 1]; a[j + 1] = tt;
}
}
}// 蹩脚插排
}
left* built_tree(double* a, int n)
{
int i = 0;
left* b[205];
while (i < n)
{
left* s = creat_left();
s->data = a[i];
b[i] = s;//printf("%d ", b[i]->data);
i++;
}
int j = 0;
while (j < 150)
{
b[i + j] = creat_left();
j++;
}
i = n / 2 - 1;
sort(b, n);
//printf("%d", b[0]->data);
left* s = NULL;
while (n > 1)
{
double dad = b[0]->data + b[1]->data;
s = creat_left();
s->data = dad;
b[0]->father = s;
b[1]->father = s;
s->left = b[0];
s->right = b[1];
b[0] = s;
b[1] = b[n - 1];
n--;
sort(b, n);
}
return s;
}
void print_tree(left* root, int deep)
{
int i = 0;
while (i < deep)
{
printf("-");
i++;
}
printf("%.2f\n", root->data);
if (root->left != NULL)
{
print_tree(root->left, deep * 2);
}
if (root->right != NULL)
{
print_tree(root->right, deep * 2);
}
}
char temp[100];
void print_treef(left* root,int n,int *now,int len)
{
int t = 0;
if (root->left != NULL)
{
sprintf(temp+len, "%d", 1);
print_treef(root->left, n,now,len+1);
t = 1;
}
if (root->right != NULL)
{
sprintf(temp + len, "%d", 0);
print_treef(root->right, n,now,len+1);
t = 1;
}
if (t == 0)
{
sprintf(ans[*now].code, "%s", temp);
ans[*now].p = root->data;
// ans[*now].code[len]= '\0';
*now += 1;
}
}
int main()
{
double a[10] = {0.4,0.1,0.2,0.2,0.1};
left* root = built_tree(a, 5);
int len = 0;
printf("树\n");
print_tree(root, 1);
printf("编码\n");
print_treef(root, 1,&len,0);
sortans(5);
for (int i = 0; i < 5; i++)
{
printf("u%d: p=%.2f ", i + 1,ans[i].p);
printf("%s\n", ans[i].code);
}
}