《考研-数据结构-哈弗曼树-假设某通信报文的字符集由..》

题目描述

假设某通信报文的字符集由A,B,C,D,E,F这6个字符组成,它们在报文中出现的频度(频度均为整数值)。
(1)构造一棵哈弗曼树,依次给出各字符编码结果。
(2)给字符串进行编码。
(3)给编码串进行译码。

规定:
构建哈弗曼树时:左子树根结点权值小于等于右子树根结点权值。
生成编码时:左分支标0,右分支标1。

输入
第一行:依次输入6个整数,依次代表A,B,C,D,E,F的频度,用空格隔开。
第二行:待编码的字符串
第三行:待译码的编码串
输出
前6行依次输出各个字符及其对应编码,格式为【字符:编码】(冒号均为英文符号)
第7行:编码串
第8行:译码串
样例输入 Copy
3 4 10 8 6 5
BEE
0010000100111101
样例输出 Copy
A:000
B:001
C:10
D:01
E:111
F:110
001111111
BADBED

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct hafutree
{
   char ch;
   int  parent;
   int  weight;
   int  lchild;
   int  rchild;
}hafutree;
///初始化哈夫曼树
hafutree **inithafutree(int wet[])
{
  hafutree **head;
  char a='A';
  head=(hafutree **)malloc(sizeof(hafutree *)*12);
  for(int i=1;i<=6;i++,a++)
  {
    head[i]=(hafutree *)malloc(sizeof(hafutree));
    head[i]->ch=a;
    head[i]->weight=wet[i-1];
    head[i]->parent=0;
    head[i]->lchild=0;
    head[i]->rchild=0;
  }
  for(int i=7;i<12;i++)
  {
    head[i]=(hafutree *)malloc(sizeof(hafutree));
    head[i]->ch='#';
    head[i]->weight=0;
    head[i]->parent=0;
    head[i]->lchild=0;
    head[i]->rchild=0;
  }
  return head;
}
///创建好哈夫曼树
void create_hafutree(hafutree **head)
{  
	int m,n;//m第一个最小,n第二个最小
	int k=6;//记录下一次比较位置
	while(k<11)
   {
      for(int j=1;j<=k;j++)
        {
       if(head[j]->parent==0)
       	{
       	m=j;
       	break;
       	}
       }
    for(int i=1;i<=k;i++)
    { 
      if(head[m]->weight>=head[i]->weight&&head[i]->parent==0)
      {
        m=i;
      }
    }
    for(int j=1;j<=k;j++)
      {
      	if(head[j]->parent==0&&m!=j)
      	{
      		n=j;
      		break;
      	}
      }			
    for(int i=1;i<=k;i++)
    { 
      if(i==m)
      {
      	continue;
      }
      if(head[n]->weight>=head[i]->weight&&head[i]->parent==0)
      {
        n=i;
      }
    }
    head[++k]->weight=head[m]->weight+head[n]->weight;
    head[k]->lchild=m;
    head[k]->rchild=n;
    head[m]->parent=k;
    head[n]->parent=k;
  }
  /*getchar();
  printf("完成哈夫曼树\n");
  for(int i=1;i<12;i++)
   {
     //printf("%d",head[i]->weight);
      printf("%d-节点值%c-",i,head[i]->ch);
       printf("父亲%d-",head[i]->parent);
        printf("左孩子%d-",head[i]->lchild);
         printf("右孩子%d-\n",head[i]->rchild);
   }
  getchar();*/
}
进行哈夫曼编码
void makecode(hafutree **head,char **ch)
{
   char a[6];
   int start;
   int p;
   int k;
   for(int i=1;i<=6;i++)
   {
      start=5;
      a[start]='\0';
      p=head[i]->parent;//p表示双亲
      k=i;//k记录顺序
      while(p)
      {
        if(head[p]->lchild==k)
        {
          a[--start]='0';
        }
        else if(head[p]->rchild==k)
        {
        a[--start]='1';
        }
        k=p;//k记录找到孩子的双亲
        p=head[p]->parent;
     }
     ch[i]=(char *)malloc(sizeof(char)*(6-start));
     strcpy(ch[i],&a[start]);
   }
   return ;
}
///进行哈夫曼译码
char *translatecode(hafutree **head,char hafu_number[])
{
  int k=0;//记录边缘后位置 
  int m,x,n;
  char *tr;
  tr=(char *)malloc(sizeof(char)*20);
  x=0;
  for(int i=k;hafu_number[i]!='\0';)
   { 
     m=11;
     n=i;
     while(head[m]->lchild&&head[m]->rchild)
    {
     if(hafu_number[n]=='0')
     {
        m=head[m]->lchild;
     }
     else if(hafu_number[n]=='1')
     {
        m=head[m]->rchild;
     }
     n++;
     i++; 
   }
   tr[x++]=head[m]->ch;
   tr[x]='\0';
  }
  return tr;
}
int main()
{
  char hafuch[20];//待编译码
  char hafu_number[30];//待解译码
  char hafuch_num[30]="";
	hafutree **head;
  int wet[6];//权值
  int j;
  char *tr;
  tr=(char *)malloc(sizeof(char)*20);
	for(int i=0;i<6;i++)
	{
		scanf("%d",&wet[i]);
	}
	getchar();
  gets(hafuch);
  gets(hafu_number);
	head=inithafutree(wet);
	create_hafutree(head);
	char **ch;
	ch=(char **)malloc(sizeof(char *)*7);
  makecode(head,ch);
  for(int i=0;hafuch[i]!='\0';i++)
  { 
    j=1;
    while(j<=6)
    { 
      if(head[j]->ch==hafuch[i])
      { 
        strcat(hafuch_num,ch[j]);
        break;
      }
      j++;
    }
  }
  for(int i=1;i<=6;i++)
  {
    printf("%c:%s\n",head[i]->ch,ch[i]);
  }
  puts(hafuch_num);
  tr=translatecode(head,hafu_number);
  puts(tr);
  
}
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值