霍夫曼编码算法的实现
从键盘输入字符序列及对应的权重,输出霍夫编码
分析:
- 构造树结点,输入带编码字符及对应的权值;
- 在树结点中选择parent = 0, 且权值最小的两个结点
- 构造Huffman树并求出编码
代码:
#include "pch.h"
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define N 10 //树中叶子结点的最大数目
#define M (2*N-1)//树中结点的最大数目
typedef struct Node
{
int weight;//权重
int parent, lchild, rchild;//左右孩子及双亲
} HTNode;
typedef struct
{
char data;// 字符
int weight; //权重
char code[N];//编码
}HTCode;
void Init(HTCode * ht, int *n)
//初始化,从键盘读入n个字符及权值
{
int i;
printf("请输入带编码字符的个数:\n");
scanf_s("%d",&(*n));
rewind(stdin);
printf("请输入带编码的字符:\n");
for (i = 0; i < (*n); i++)
{
scanf_s("%c", &(ht[i].data));
}
rewind(stdin);
printf("请输入带编码字符的权值:\n");
for (i = 0; i < (*n); i++)
{
scanf_s("%d", &(ht[i].weight));
}
rewind(stdin);//清空缓冲区
}
void Select(HTNode *ht, int *s1, int *s2, int k)
/*从ht[0,1,2,...,k]结点中选择权值最小且parent=0的两个结点*/
{
int i;
for (i = 0; i < k; i++)
{
if (ht[i].parent == 0)
break;
}
(*s1) = i;//找到第一个parent为零的点
for (i = (*s1)+1; i < k; i++)
{
if (ht[i].parent == 0 && ht[i].weight < ht[(*s1)].weight)
{
(*s1) = i;
}
}
for (i = 0; i < k; i++)
{
if (ht[i].parent == 0 && i != (*s1))
break;
}
(*s2) = i;
for (i = (*s2) + 1; i < k; i++)
{
if (ht[i].parent == 0 && i != (*s1) && ht[i].weight < ht[(*s2)].weight)
(*s2) = i;
}
}
void HuffmanCoding(HTNode *ht, HTCode *hc, int n)
/*构建霍夫曼树,并进行霍夫曼编码*/
{
int s1, s2;
int c, f;
int Num_TreeNode = 2 * n - 1;// 总的结点数目
int i;
char code[N];
int start;
/*构建霍夫曼树*/
for (i = 0; i < Num_TreeNode; i++)
{
if(i<n)//前n个叶子结点
ht[i].weight = hc[i].weight;
ht[i].parent = 0;
ht[i].rchild = ht[i].lchild = 0;
}
for (i = n; i < Num_TreeNode; i++)
{
Select(ht, &s1, &s2, i );//从前n个结点中选择两个权值最小的结点
ht[s1].parent =i;
ht[s2].parent = i;
ht[i].lchild = s1;
ht[i].rchild = s2;
ht[i].parent = 0;
ht[i].weight = ht[s1].weight + ht[s2].weight;
}
/*进行霍夫编码,从叶子结点到根结点*/
code[n] = '\0';
for (i = 0; i < n; i++)
{
start = n ;
for (c = i, f = ht[i].parent; f; c = f, f = ht[c].parent)//沿着叶子向根走
{
if (c == ht[f].lchild)
code[--start] = '0';
else
code[--start] = '1';
}
strcpy_s(hc[i].code, &code[start]);
}
}
int main()
{
HTNode ht[M+1];
HTCode hc[N+1];
int n;// 叶子结点个数
Init(hc, &n);//初始化
HuffmanCoding(ht, hc, n);
int i;
for (i = 0; i < n; i++)
{
printf("%c-----%s\n", hc[i].data, hc[i].code);
}
return 0;
}
程序运行截图: