现在的位置: 首页 > 综合 > 正文

赫夫曼树

2014年01月20日 ⁄ 综合 ⁄ 共 6401字 ⁄ 字号 评论关闭

#include<iostream.h>
#include<stdio.h>
const int DefaultSize=30;
class code
{
public:
  char keymark;//编码字符
  int key;//权值
};
class element
{
 friend class binTree;
public:
 element():leftchild(NULL),rightchild(NULL),parent(NULL),mark(0){};
    code data;// 保存本结点的使用频度和其它数据。
 int mark;
    element *leftchild,*rightchild,*parent;
};
class binTree//单个元素的二叉树数
{
public:
 binTree(){  root=new element;}
    binTree(binTree &bt1,binTree &bt2)//
    {
       root=new element;
       root->leftchild =bt1.root;
    root->rightchild=bt2.root;
       root->data.key=bt1.root->data.key+bt2.root->data.key;
    bt1.root->parent=bt2.root->parent=root;  /**/
   }
   element *root;
};
class minHeap//最小堆的类声明,也即是排序二叉树(最小为根)
{
public:
 minHeap(){heap=NULL;};
 minHeap(int maxsize);
 void makeMinHeap(binTree a[],int n);
 ~minHeap(){ delete[] heap;}
 int insert(binTree x);//插入堆中
 int removeMin(binTree &x);//删除堆顶的最小元素
 int isEmpty(){ return currentsize==0;};//判断是否为空
 int isFull(){return currentsize==maxheapsize;};//判断是否已满
 //void makeEmpty();//清空堆
private:
 binTree *heap;//存放堆中元素的数组
 int currentsize;//单前元素的个数
 int maxheapsize;//堆中元素的最大个数
 void filterDown(int start,int end);//从i到m自顶向下进行调整为最小堆
 void filterUp(int end);//从i到0自底向上进行调整为最小堆
};
minHeap::minHeap (int maxsize)//构造函数
{     
   maxheapsize=maxsize;
   heap=new binTree[maxheapsize];
   currentsize=0;
}
void  minHeap::makeMinHeap (binTree arr[],int n)

   maxheapsize=n;
   heap =new binTree[maxheapsize];
   for(int i=0;i<n;i++)
   {
    heap[i].root=arr[i].root;
   }
   currentsize=n;
   int currentPos =(currentsize-1)/2;//找最初调整位置:最后的分支结点
   while (currentPos>=0)
   {
       filterDown(currentPos,currentsize-1); //向下调整成最小堆
    currentPos--;//再向前换一个分支结点
   }
}
void  minHeap::filterDown(int start,int end)//指定开始、结尾,向下调整成最小堆
{  
   int i=start;
   int j=2*i+1;//左子女标号,i+1为有子女标号
   binTree temp=heap[i];
   while (j<=end)
   {  
    if (j<end&&heap[j].root->data.key>heap[j+1].root->data.key) j++;//一次比较,让j指向两子女中的最小者
       if (temp.root->data.key<heap[j].root->data.key) break;     //二次比较
       else
    {
     heap[i]=heap[j];
     i =j;
     j = 2*i+1;//并不马上将temp放入下层
    }  // while end
       heap[i]=temp;
   }
};
void minHeap::filterUp(int start)//指定开始向上调整成最小堆
{
 int j=start;
 int i=(j-1)/2;
 binTree temp=heap[j];
 while(j>0)
 {
  if(heap[i].root->data.key<=temp.root->data.key) break;
  else
  {
   heap[j]=heap[i];
   j=i;
   i=(i-1)/2;
  }
  heap[j]=temp;
 }
}
int minHeap::insert(binTree x)//插入一棵二叉树
{
 if(currentsize==maxheapsize)
 {
  cout<<"heap is full!"<<endl;
  return 0;
 }
 heap[currentsize]=x;
 filterUp(currentsize);//插入后,要调整
 currentsize++;
 return 1;
}
int minHeap::removeMin(binTree &x)//删除最小元素
{
 if(!currentsize)
 {
  cout<<"Heap is empty!"<<endl;
  return 0;
 }
 x=heap[0];
 heap[0]=heap[currentsize-1];//把最后的放到最前面来
 currentsize--;
 filterDown(0,currentsize-1);//然后调整
}
binTree * HuffmanTree ( code *fr,int n)//构造huffman树
{
    binTree *newtree=NULL;
    binTree first, second;
    minHeap  hp;
    if(n>DefaultSize)
 {
  cerr<<"Size n"<<n<<"exceed the Boundary of Array"<<endl;
  return NULL;
 }
    binTree Node[DefaultSize];
    for(int i=0;i<n;i++)
 {
   Node[i].root->data=fr[i];
         Node[i].root->leftchild=Node[i].root->rightchild=NULL;
 }
    hp.makeMinHeap(Node,n);// 建立具有 n 个结点最小化堆。数组名为Node。
    for (i=0; i<n-1; i++ )
    {
  
      hp.removeMin(first); //从森林中找出根结点最小的两棵数
   hp.removeMin(second);//合并成一棵新树,然后把两棵树从森林中去掉
      newtree=new binTree(first,second);
   hp.insert (*newtree); //把新树插入森林中
  
    }return newtree; 
}
 

 

#include<iostream.h>
#include"huffman.h"
class huffcode//存放字符及相应的编码
{
public:
 char keyc;
 char hufc[30];
}; 
huffcode * coding(binTree *tree,int L)//编码程序
{
 huffcode *hc=new huffcode[L];
    element *current=tree->root;
 element *currentFront=current;//currentFront用于指向当前结点的父母
 int j=0;
 for(int i=0;i<L;i++)
 { 
    j=0;
    currentFront=current=tree->root;
       while(1)
    { 
     if(current->leftchild->mark==0)//mark等于0说明当前结点的左子树的叶子还没有扫描完,继续扫描
     {
    //cout<<"current->data.key="<<current->data.key<<endl;
    hc[i].hufc[j]='0';//记下路径,往左为0,往右为1
    j++;
    if(current->leftchild->leftchild==NULL)
    { 
                 hc[i].hufc[j]='/0';
     hc[i].keyc=current->leftchild->data.keymark;
                 current->leftchild->mark=1;
     break; 
    }
    currentFront=current;
    current=current->leftchild;
     }
      if(current->leftchild->mark==1)//mark等于0说明当前结点的左子树的叶子已经扫描完,扫描右子树
    {  
      //cout<<"current->data.key="<<current->data.key<<endl;
      hc[i].hufc[j]='1';//记下路径,往左为0,往右为1
      j++;
      if(current->rightchild->leftchild==NULL)
      {
                 hc[i].hufc[j]='/0';   
     hc[i].keyc=current->rightchild->data.keymark;
                 current->rightchild->mark=1;
     current->mark=1;
                 while((currentFront->leftchild->mark==1)&&(currentFront->rightchild->mark==1))//扫描完当前结点的右子树,需要往上标记mark
     {
       currentFront->mark=1;
       if(currentFront==tree->root) break;
       if(currentFront->parent->parent!=NULL)
       {
        //cout<<currentFront->data.key<<endl;
        currentFront=currentFront->parent;
       }
       else
        break;
     }/**/ 
     break;
      }
               currentFront=current;//指向当前结点的父母
      current=current->rightchild;
    }
    }
 }
 return hc;
}
void decode(binTree *tree,char c[])//解码程序
{
 element *current=tree->root;
 for(int i=0;i<strlen(c);i++)
 {
      
  if(c[i]=='0')  current=current->leftchild;//如果是0,指向左子女
  else
  {
       if(c[i]=='1')  current=current->rightchild;//如果是1,指向左子女
    else
   cout<<"你输入的报文有误!报文必须由二进制位组成!";//不能出现0,1以外的字符,否则警告
  }
  if(current->leftchild==NULL)//到达叶子,则译出一个字符
  {
    cout<<current->data.keymark;
    current=tree->root;
  }
 }
}

 

 

#include<string.h>
#include"coding_decode.h"
const charSize=1000;
void main()
{
 char c[30];
 cout<<"请输入编码报文中可能出现的字符,以对其生成编码(出现频率最高的在前面)"<<endl;
    //cout<<"请输入编码报文中可能出现的字符以及该字符出现频率权值,以对其生成编码"<<endl;
 gets(c);
 int L=strlen(c);
 code *cipher=new code[L];
 for(int i=0;i<L;i++)
 {
  cipher[i].key=L-i-1;
  cipher[i].keymark=c[i];
 }
    binTree *NewTree=HuffmanTree(cipher,L);
 huffcode *hf=coding(NewTree,L); 
 cout<<"编码字符"<<'/t'<<"对应编码"<<endl;
 for(i=0;i<L;i++)
 {
  cout<<"    "<<hf[i].keyc<<'/t'<<'/t'<<hf[i].hufc<<endl;
 }
 int r;
 cout<<endl<<"对报文Huffman编码,请输入'1'"<<endl
  <<"对报文Huffman解码,输入'2'"<<endl<<"退出,输入'0':";
 cin>>r;
 while(r)
 {
  if(r==1)
  {
         cout<<"请输入要编码的报文内容:"<<endl;
         char ch[charSize];
            gets(ch);
         int mark=0;
   cout<<"该报文的编码是:";
         for(i=0;i<strlen(ch);i++)
   {
          for(int j=0;j<L;j++)
    {
             if(ch[i]==hf[j].keyc)
     {
            cout<<hf[j].hufc;
             mark=1;
     }
    }
      if(mark==0) cout<<"你输入的报文内容中有非编码的字符!";
   }
  }
    if(r==2)
    {
       cout<<"请输入要解码的报文:"<<endl;
       char chr[charSize];
       gets(chr);
    cout<<"该报文经解码后是:";
       decode(NewTree,chr);
    }
      cout<<endl<<"对报文进行Huffman编码,请输入'1'"<<endl
    <<"对报文进行Huffman解码,输入'2'"<<endl<<"退出,输入'0':";
    cin>>r;
 }
}

抱歉!评论已关闭.