哈弗曼树建立与哈弗曼编码

#include<iostream>

#define LEN sizeof(HaffmanNode)
#define MAXSIZE 100
#define MAX 9999

using namespace std;

typedef struct{
  int value;
  int lChild,rChild,parent;
}HaffmanNode,Haffman[MAXSIZE];

typedef struct{
  char name;
  int w;
  char code[MAXSIZE];
}HaffmanCode[MAXSIZE];

//全局变量
Haffman h;
HaffmanCode hc;

//筛选出值最小的两个结点,s1,s2存储其结点的索引位置
void Select(Haffman h,int index,int *s1,int *s2)
{
  *s1=0;*s2=0;
  for(int i=1;i<=index;i++)
  {
   //筛选出无双亲结点,且权值最小的两个结点
    if(h[i].parent==0)
    {
      if(h[i].value<=h[*s1].value)
      {  
         *s2=*s1;
         *s1=i;
      }
      else if(h[i].value<h[*s2].value)
      {
         *s2=i;
       }
     }
  }
}

//创建哈弗曼树及每个叶结点的哈弗曼编码
void CreateHaffmanTree(Haffman h,HaffmanCode hc,int n)
{
  int s1,s2;
  h[0].value=MAX;
  for(int i=1;i<=n;i++)
  {
     h[i].lChild=h[i].rChild=h[i].parent=0;
     h[i].value=hc[i].w;
  }
  for(i=n+1;i<=2*n-1;i++)
  {
      h[i].lChild=h[i].rChild=h[i].parent=h[i].value=0;
   }

  //构建叶子结点外的其他结点
  for(i=n+1;i<=2*n-1;i++)
  { 
     Select(h,i-1,&s1,&s2);
     h[i].lChild=s1;h[i].rChild=s2;
     h[i].value=h[s1].value+h[s2].value;
     h[s1].parent=i;h[s2].parent=i;
  }
}

//求每个叶结点的哈弗曼编码
void CreateHaffmanCode(Haffman h,HaffmanCode hc,int n)
{
  int Stack[MAXSIZE],top=-1;
  char flag[MAXSIZE],j;         
  HaffmanNode th;
  for(int i=1;i<=n;i++)
  {
     th=h[i];int c=i;j=0;
     while(th.parent!=0)
     {
      Stack[++top]=th.parent;
      if(h[Stack[top]].lChild==c)
      {
        flag[top]='L';c=th.parent;
      }
      else if(h[Stack[top]].rChild==c)
      {
        flag[top]='R';c=th.parent;
      }
      th=h[Stack[top]];
   }
   while(top!=-1)
   {
     if(flag[top]=='L')
       hc[i].code[j++]='0';
     else
       hc[i].code[j++]='1';
     top--;
    }
    hc[i].code[j]='\0';
  }
}

//求叶结点的所在层的深度
int Depth(Haffman h,HaffmanNode hd)
{
  int count=0;
  HaffmanNode temp;
  temp=hd;
  while(temp.parent!=0)
  {
     temp=h[temp.parent];
     count++;
  }
  return count;
}

//打印叶结点的哈弗曼编码值,以及二叉树的带权路径长度
void PrintHaffmanCode(Haffman h,HaffmanCode hc,int n)
{
  int weight,sum=0;
  for(int i=1;i<=n;i++)
  {
     weight=Depth(h,h[i])*h[i].value;
     cout<<"结点名称:"<<hc[i].name<<",结点的哈弗曼编码值:"<<hc[i].code<<"\n";
     sum+=weight;
  }
  cout<<"带权路径长度为:"<<sum<<"\n";
}

int main()
{
  int n;
  char cmd;
  do{
     cout<<"输入叶子结点数目\n";
     cin>>n;
     cout<<"输入叶子结点名称和每个叶子结点的权值\n";
     for(int i=1;i<=n;i++)
    {
      cin>>hc[i].name>>hc[i].w;
     }
     CreateHaffmanTree(h,hc,n);
     CreateHaffmanCode(h,hc,n);
     PrintHaffmanCode(h,hc,n);
     cout<<"继续吗y/Y\n";
     cin>>cmd;
  }while(cmd=='y'||cmd=='Y');
  return 0;
}

 

    原文作者:哈夫曼树
    原文地址: https://blog.csdn.net/iteye_16572/article/details/81888714
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞