#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>
#define MAXSIZE 30
typedef struct
{
char data;
float weight;
int parent;
int lchild;
int rchild;
}HTNode;
typedef struct
{
char bits[10];
int start;
}HCode;
void CreateHT(HTNode ht[30], int n)
{
int i, k, lnode, rnode;
int m = 2 * n - 1;
float min1, min2;
for (i = 0; i < m; i++)//对每个结点进行初始化
{
ht[i].parent = -1; ht[i].lchild = -1;
ht[i].rchild = -1; ht[i].weight = 0;
}
for (i = 0; i < n; i++)
{//输入前n个结点的字符和权值
printf("输入第%d个字符和其权值,空格隔开\n", i + 1);
getchar();
scanf("%c %f", &ht[i].data, &ht[i].weight);
}
for (i = n; i < m; i++)
{//构造哈夫曼树
min1 = min2 = 32767;
lnode = rnode = -1;//lnode保存左子树的下标
for (k = 0; k <= i - 1; k++)
{//在[0..i-1]中选择parent为-1且weight最小的两个结点
if (ht[k].parent == -1)
{
if (ht[k].weight < min1)
{
min2 = min1;
min1 = ht[k].weight;
rnode = lnode;
lnode = k;
}
else if (ht[k].weight < min2)
{
min2 = ht[k].weight;
rnode = k;
}
}
}
ht[lnode].parent = i; ht[rnode].parent = i;
ht[i].weight = ht[lnode].weight + ht[rnode].weight;
ht[i].lchild = lnode; ht[i].rchild = rnode;
}
}
void HuffmanCode(HTNode ht[], HCode hcd[], int n)//求编码
{
int i, p, c;
HCode temp;//保存当前结点的信息
for (i = 0; i < n; i++)
{
temp.start = n;//
c = i;
p = ht[i].parent;
while (p != -1)
{
temp.start--;
if (ht[p].lchild == c)
temp.bits[temp.start] = '0';
else
temp.bits[temp.start] = '1';
c = p;
p = ht[p].parent;
}
hcd[i] = temp;
}
}
void DeCode(HTNode ht[], int n)//译码
{
int i,m, j = 0,x=0;
char b[MAXSIZE],B[MAXSIZE];
m = 2*n - 1;
i = m - 1; //从根结点开始往下搜索
printf("输入发送的编码(以'2'为结束标志):");
fflush(stdin);//清理缓冲区
gets(b);
while (b[j] != '2')
{
if (b[j] == '0')
i = ht[i].lchild; //走向左孩子
else
i = ht[i].rchild; //走向右孩子
if (ht[i].lchild == -1) //ht[i]是叶结点
{
B[x] = ht[i].data;
B[x+1] = '\0';
x++;
i = m - 1;
}
j++;
}
if (ht[i].lchild == -1 || i == m - 1)
{
printf("译码后的字符为:");
printf("%s", B);
}
else
{
printf("输入电文有误,请检查");
}
}//decode
int TreeDeep(HTNode ht[], int m)//求哈夫曼树的深度
{
int deep = 0;
if (m != -1)
{
int LeafDeep = TreeDeep(ht, ht[m].lchild);
int RightDeep = TreeDeep(ht, ht[m].rchild);
deep = LeafDeep > RightDeep ? LeafDeep + 1 : RightDeep + 1;
}
return deep;
}
void PrintTree(HTNode ht[], int m, int depth)//横向打印哈夫曼树
{
int i;
if (m != -1)
{
PrintTree(ht, ht[m].rchild, depth + 1);
for (i = 0; i < depth; i++)printf(" ");
if (ht[m].data != -52)printf(" -%c\n ", ht[m].data);
else printf(" -%3.1f-▏\n", ht[m].weight);
PrintTree(ht, ht[m].lchild, depth + 1);
}
}
int main()
{
int n, m, i, j, deep, cord;
HTNode ht[MAXSIZE];
HCode hcd[15];
int ret = MessageBox(NULL,
TEXT("\t★哈夫曼编/译码器★\n*******************************************\n*主要功能: 打印哈夫曼树 编码 译码*\n*******************************************\n*小组成*********************************\n\t 是否开始"),
TEXT("★哈夫曼编/译码器★"), MB_YESNO);
if (ret == IDYES)
{
do
{
printf("\n\n①.创建哈夫曼树\n");
printf("②.横向打印哈夫曼树\n");
printf("③.输出编码\n");
printf("④.读入电文,进行译码\n");
printf("⑤.退出\n");
scanf("%d", &cord);
switch (cord)
{
case 1:
{ printf("输入字符个数\n");
scanf("%d", &n);
CreateHT(ht, n);
m = 2 * n - 1;
}break;
case 2:
{
deep = TreeDeep(ht, m - 1);
PrintTree(ht, m - 1, deep);
}break;
case 3:
{
HuffmanCode(ht, hcd, n);
for (i = 0; i < n; i++)
{
printf(" %c ", ht[i].data);
for (j = hcd[i].start; j < n; j++)
printf("%c", hcd[i].bits[j]);
printf("\n");
}
}break;
case 4:DeCode(ht, n); break;
case 5:exit(0); break;
}
} while (cord < 5);
}
else
{
exit(0);
}
return 0;
}
哈夫曼编码横向打印
最新推荐文章于 2023-07-31 00:46:34 发布