huffman树和huffman编码

//huffman树和huffman编码


#include <stdlib.h>
#include <iostream.h>
#include <stdio.h>
#include <string.h>

#define  OVERFLOW -1

typedef struct
{  
  char letter;
  int weight;
  int parent;
  int lchild;
  int rchild;
}HTNode,*HuffmanTree;

typedef char * *HuffmanCode;

void Select(HuffmanTree &HT,int i,int &s1,int &s2)
{
 /*选择森林中,根结点的权值最小和次小的两个树,
 *将其根结点的下标号记入s1和s2中
 */
 int j, k;
 for(k = 1; k < i; k++)
 {
  if(HT[k].parent != NULL)
   continue;
  s1 = k;/*init the number*/
  break;
 }
 for(j = 1; j < i; j++)
 {
  if(HT[j].parent != NULL)
   continue;
  if(HT[j].weight < HT[s1].weight)
   s1 = j;
 }
 for(k = 1; k <= i; k++)
 {
  if(HT[k].parent != NULL || k == s1)
   continue;
  s2 = k;
  break;
 }

 for(j = 1; j < i; j++)
 {
  if(HT[j].parent != NULL)
   continue;
  if(HT[j].weight <= HT[s2].weight && j != s1)
   s2 = j;
 } 

}


void  HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,char *zi,int *w,int n)
{
 HuffmanTree p;

 int m,i,s1,s2,f,c;
 int Istart = 1;
 char *cd;
 if(n <= 1)
  return;
 m = 2*n-1;
 if(!(HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode))))
  exit(OVERFLOW);
 for(p=HT+1,i=1;i<=n;++i,++zi,++p,++w)
 {
 /*生成独立的森林*/
  p->parent = NULL;
  p->letter = *zi;
  p->lchild = NULL;
  p->rchild = NULL;
  p->weight = *w;
 }

 for(;i<=m;++i,++p)
 {
  (*p).weight=0;
  (*p).parent=0;
  (*p).lchild=0;
  (*p).rchild=0;
 }

 for(i=n+1;i<=m;++i)
 {
  Select(HT,i-1,s1,s2);
  HT[s1].parent=i;
  HT[s2].parent=i;
  HT[i].lchild=s1;
  HT[i].rchild=s2;
  HT[i].weight=HT[s1].weight+HT[s2].weight;
 }
 HC=(HuffmanCode)malloc((n+1)*sizeof(char *));
 cd=(char*)malloc(n*sizeof(char));/*临时的code存储*/
 cd[n-1]='/0';
 for(i=1;i<=n;++i)
 {
   Istart = n - 1;
  /*按已生成的哈夫曼树,得到各个字符的哈夫曼编码
  */
 
   for(c = i, f = HT[i].parent; f != 0; c = f, f = HT[f].parent)
    if(HT[f].lchild == c)
     cd[--Istart] = '0';
    else
     cd[--Istart] = '1';
   HC[i] = (char *)malloc((n - Istart) * sizeof(char));
   strcpy(HC[i], &cd[Istart]);
   
 }
  free(cd);
 }
void main()
{
 HuffmanTree HT;
 HuffmanCode HC;
 int i,j,yu;
 char zi[9]={'A','B','C','D','E','F','G','H'};
 int w[100];
 char z;
 char c[100];
 z='A';
 cout<<endl;
 for(i=0;i<=7;i++)
 {
  cout<<"please input the weight for "<<z<<":";
  cin>>w[i];
  z++;
 }
 HuffmanCoding(HT,HC,zi,w,8);
 cout<<endl;
 cout<<"char          weight         huffmancode    "<<endl;
 for(i=1;i<=8;i++)
  cout<<HT[i].letter<<"  "<<HT[i].weight<<"  "<<HC[i]<<endl;
 cout<<"please input the text:";
 cin>>c;
 cout<<"The  code   is:";
 
 for(i=0; i < strlen(c);  i++)
  /*根据字符的哈夫曼编码,将输入的文本(变量c表示的)翻译成电码。 
  */
  cout<<HC[(c[i] - 'A' + 1)];

       cout<<endl;
       cout<<"Enter the code:";
       cin>>c;
       j=strlen(c);
       yu=15;
       i=1;
       cout<<"The text is:";
       while(i <= j)
       {
        while(HT[yu].lchild != 0)/*因为是完全二叉树*/
        {
   if(c[i-1] == '0')
   {
   /*用哈夫曼树,将输入的电码(变量c表示的)翻译成文本,
   说明:变量名c在程序中    
   */
    yu = HT[yu].lchild;
    i++;
    continue;
   }
   if(c[i-1]== '1')
   {
    yu=HT[yu].rchild;
    i++;
    continue;
   }
  }
  /*显示由部分电码译码得到的字符,并准备对后面的电码进行译码*/
        cout<<HT[yu].letter;
        yu = 15;
 }
       cout<<endl;
}


//没有出错处理

输入示例:

please input the weight for A:12   
please input the weight for B:234 
please input the weight for C:6     
please input the weight for D:23   
please input the weight for E:26   
please input the weight for F:267 
please input the weight for G:23  
please input the weight for H:67  

char          weight         huffmancode
A               12              0001
B               234             01
C               6               0000
D               23              1000
E               26              001
F               267             11
G               23              1001
H               67              101
please input the text:ABCDEFG
The  code   is:00010100001000001111001
Enter the code:00010100001000001111001
The text is:ABCDEFG
Press any key to continue

数据结构关于二叉的建立遍历以及应用二叉进行编解码 实验要求 必做部分 1. 小明会按照前序的方式输入一棵二叉。例如,输入$ACG##H##D##BE#I##F##的话,代表了下面这棵: 2. 请分别按照前序、中序、后序输出这棵。 选做部分 背景 在影视剧中,我们经常会看到二战期间情报人员使用电报哒哒哒地发送信息,发送电报所使用的编码叫做摩尔斯电码(或者叫做摩斯密码)。甚至在现代,SOS仍然是国际通用的求救信号之一,其“三短、三长、三短”同样是摩斯密码的编码方式。 摩斯密码使用若干个“点”和“划”来表示一个字母,字母和字母之间使用短暂的停顿来表示。例如,一种常见的编码方式为: 字母 摩斯密码 字母 摩斯密码 A .- E . B -... F ..-. C -.-. G --. D -.. H .... 实际上,一个摩斯密码本可以使用一棵二叉存储: 上图表示,从根节点start开始,遇到一个点(Dot)就访问它的左子节点,遇到一个划(Dash)就访问它的右子节点。例如,三个点...代表了S,三个划---代表了O。所以SOS的摩斯密码是... --- ...(中间用空格隔开,表示短暂的停顿)。再比如,爱疯手机有一种来电铃声的节奏为“哇哇哇 哇-哇- 哇哇哇”,这其实表示的是…… 现在,小明想在课上偷偷跟你传纸条,但又不想被其他同学看到内容。因此他跟你约定,每次给你传纸条时都使用摩斯密码来编写。至于密码本,当然不能使用国际通用的,他会在课前告诉你密码本的内容。然而小明发现,每次写纸条、读纸条都不是很方便,所以他想让你做个程序来自动编码/解码你们的摩斯密码。 题目要求 首先,小明输入的那棵二叉,代表了你们在这堂课上要使用的摩斯密码本。例如,输入$ACG##H##D##BE#I##F##的话,代表了下面这棵: 第一个字母$是什么并不重要,因为它只是代表了根节点,而根节点在我们的摩斯电码中并不代表一个字符,仅仅代表“start”。 读入密码本后,请记得按照前序、中序、后序输出这棵。 然后,小明会输入一个数,代表接下来输入的是明文还是摩斯电码。输入0表示接下来他会输入明文,输入1表示接下来输入的是摩斯电码,输入-1程序退出。 1. 如果输入的是0,代表接下来要输入的是明文。程序接受一个字符串,根据字符串中每一个字母输出对应的摩斯电码,用空格隔开。例如如果小明输入“BED”,则程序应该输出“-空格-.空格.-”。如果遇到密码本中没有的字符,则输出“输入有误”。 2. 如果输入的是1,则表示接下来要输入摩斯电码。小明首先会输入一个数字N,代表有几个电码的输入,例如输入4代表之后会输入4个电码(即这个单词有四个字母)。随后输入空格分割的电码,例如, .. . -- -. 程序需要根据摩斯电码解读出明文单词并输出,例如上面的电码表示“CAFE”。如果遇到密码本中没有的编码,则输出“输入有误”。 输入输出样例 必做部分: 请输入二叉: $ACG##H##D##BE#I##F## 前序遍历:$ACGHDBEIF 中序遍历:GCHAD$EIBF 后序遍历:GHCDAIEFB$ 选做部分: 请选择(0为明文,1为电码,-1退出):0 请输入明文:BED 摩斯电码为:- -. .- 请选择(0为明文,1为电码,-1退出):1 请输入电码个数:4 请输入电码:.. . -- -. 明文为:CAFE 请选择(0为明文,1为电码,-1退出):-1 // 程序结束
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值