已知在一段报文中有a、b、c、d、e、f六个字符,每个字符出现
的频率依次为a:45,b:13,c:12,d:16,e:9,f:5。要求对每个
字符进行编码要求所发出的报文总长度最短,并求该报文的平均码长。
(一)针对案例中的问题,寻找解决方法并进行理论解决。
1.利用哈夫曼编码对六个字符根据权重建立哈夫曼树。
3.对哈夫曼树进行编码。
4.根据哈夫曼树得出每个字符的哈夫曼编码。
(二)针对案例中的问题,将理论过程转化为代码程序,利用计算机解决
该类问题。
1.在第一步的基础上,运用C语言,将第一步哈夫曼编码的过程转化
为代码程序解决。
2.输入需要编码的字符个数及每个字符的权重,利用程序得出每个字符的哈夫
曼编码。
**
#include <stdio.h>
#include <stdlib.h>
struct queue{
int head;
int tail;
int data[1000];
};
struct stack{
int top;
int data[10];
};
int main()
{
int i,t;
struct queue q1,q2;
struct stack s;
int book[10];
q1.head=1;q1.tail=1;
q2.head=1;q2.tail=1;
s.top=0;
for(i=1;i<=9;i++)
book[i]=0;
for(i=1;i<=6;i++){
scanf("%d",&q1.data[q1.tail]);
q1.tail++;
}
for(i=1;i<=6;i++){
scanf("%d",&q2.data[q2.tail]);
q2.tail++;
}
while(q1.head<q1.tail&&q2.head<q2.tail)
{
t=q1.data[q1.head];
if(book[t]==0){
q1.head++;//q1出牌,即出队列,头指针+1
s.top++;//桌面上的牌为栈,仅有头指针操作
s.data[s.top]=t;
book[t]=1;
}
else{
q1.head++;
q1.data[q1.tail]=t;
q1.tail++;
while(s.data[s.top]!=t)
{
book[s.data[s.top]]=0;
q1.data[q1.tail]=s.data[s.top];
q1.tail++;
s.top--;
}
}
t=q2.data[q2.head];
if(book[t]==0)
{
q2.head++;
s.top++;
s.data[s.top]=t;
book[t]=1;
}
else
{
q2.head++;
q2.data[q2.tail]=t;
q2.tail++;
while(s.data[s.top]!=t)
{
q2.data[q2.tail]=s.data[s.top];
book[s.data[s.top]]=0;
q2.tail++;
s.top--;
}
}
}
if(q2.head==q2.tail)
{
printf("q1 win\n");
for(i=q1.head;i<q1.tail;i++)//tail始终指向结尾的下一个位置
printf("%d ",q1.data[i]);
}
else
{
printf("q2 win\n");
for(i=q2.head;i<q2.tail;i++)
printf("%d ",q2.data[i]);
}
return 0;
}
根据字符出现的频率建立哈夫曼树。首先将这些字符作为叶子节点,在每个节点上标记该字符的频率,将所有节点按其频率值从小到大排序,选取频率最小的两个节点建立一个新的节点,其频率值为这两个节点的频率之和,并将这个新的节点插入原先的序列中。重复这个过程,直到序列中只包含一个节点为止,此节点即为根节点,哈夫曼树建立完成。
对哈夫曼树进行编码。从根节点开始,往左走为 0,往右走为 1。对于每个字符,将其在树中走到的路径上的数字记录下来,例如从根节点到字符 a 所在的节点路径为左-右-左,则该字符的编码为 010。
根据哈夫曼树得出每个字符的哈夫曼编码。将每个字符在哈夫曼树上的路径记录在代码中,可以使用字符串或数组表示编码,例如字符 a 的编码为 "010" 或 {0,1,0}。
对于给定的报文,根据每个字符的频率和哈夫曼编码进行编码。将每个字符替换为其对应的哈夫曼编码,并将所有替换后的编码拼接在一起即可得到报文的完整编码。
计算平均码长。平均码长的计算公式为:∑(每个字符的频率 × 对应的编码长度)。将每个字符的频率和对应的编码长度代入公式中进行计算即可得出平均码长。
#include <stdio.h>
#include <string.h>
#define MAX_CHAR_NUM 6
struct Node {
char c;
int freq;
char code[MAX_CHAR_NUM];
struct Node* left;
struct Node* right;
};
void sort_node_list(struct Node** node_list, int len) {
// 冒泡排序
for (int i = 0; i < len - 1; ++i) {
for (int j = 0; j < len - i - 1; ++j) {
if (node_list[j]->freq > node_list[j + 1]->freq) {
struct Node* tmp = node_list[j];
node_list[j] = node_list[j + 1];
node_list[j + 1] = tmp;
}
}
}
}
struct Node* create_node_list() {
struct Node* node_list[MAX_CHAR_NUM];
int freq[] = {45, 13, 12, 16, 9, 5};
for (int i = 0; i < MAX_CHAR_NUM; ++i) {
char c = 'a' + i;
struct Node* node = (struct Node*)malloc(sizeof(struct Node));
node->c = c;
node->freq = freq[i];
node->left = node->right = NULL;
node_list[i] = node;
}
return node_list[0];
}
struct Node* create_huffman_tree() {
struct Node* node_list = create_node_list();
int len = MAX_CHAR_NUM;
while (len > 1) {
struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
new_node->freq = node_list[0]->freq + node_list[1]->freq;
new_node->left = node_list[0];
new_node->right = node_list[1];
for (int i = 2; i < len; ++i) {
node_list[i - 2] = node_list[i];
}
node_list[len - 2] = new_node;
--len;
sort_node_list(node_list, len);
}
return node_list[0];
}
void assign_codes(struct Node* node, char* code, int depth) {
if (!node->left && !node->right) {
strncpy(node->code, code, MAX_CHAR_NUM);
return;
}
code[depth] = '0';
assign_codes(node->left, code, depth + 1);
code[depth] = '1';
assign_codes(node->right, code, depth + 1);
code[depth] = '\0';
}
void print_codes(struct Node* root, FILE* fp) {
if (root->left) {
fprintf(fp, "%c ", root->c);
fprintf(fp, "%s\n", root->code);
print_codes(root->left, fp);
print_codes(root->right, fp);
}
}
void encode(char* text, int len, FILE* fp) {
char code[MAX_CHAR_NUM];
char code_buffer[MAX_CHAR_NUM * len];
memset(code_buffer, 0, MAX_CHAR_NUM * len);
for (int i = 0; i < len; ++i) {
char c = text[i];
struct Node* node = huffman_tree;
while (node && node->c != c) {
if (text[i] < node->c) {
node = node->left;
} else {
node = node->right;
}
}
strncat(code_buffer, node->code, MAX_CHAR_NUM);
}
fprintf(fp, "%s\n", code_buffer);
}
int main() {
struct Node* huffman_tree = create_huffman_tree();
char code[MAX_CHAR_NUM] = {0};
assign_codes(huffman_tree, code, 0);
FILE* fp = fopen("huffman_codes.txt", "w");
print_codes(huffman_tree, fp);
fclose(fp);
char text[] = "aabcbd";
encode(text, strlen(text), fp);
return 0;
}