Huffman树的构造及编码

来源:互联网 发布:男人射精前的样子知乎 编辑:程序博客网 时间:2024/05/29 10:52

Node.h:

<span style="font-size:12px;">#include <iostream>#include <string>using namespace std;//结点结构体定义struct Node{    double weight;                        //权值    char ch;                              //外结点名    string code;                          //编码    Node* lchild,*rchild,*parent;    Node(double _weight=0,char _ch='*',string _code="")                          //构造函数    :weight(_weight),ch(_ch),code(_code),lchild(NULL),rchild(NULL),parent(NULL){}    //运算符重载    bool operator<(Node &N){return weight<N.weight;}    bool operator<=(Node &N){return weight<=N.weight;}    bool operator>(Node &N){return weight>N.weight;}    bool operator>=(Node &N){return weight>=N.weight;}};</span>
Huffman.h:

<span style="font-size:12px;">#include <iostream>#include "Node.h"using namespace std;class HuffmanTree{private:    Node *root;                               //根结点    void destroy(Node *subtree);              //删除树    void PreOrder(Node *subtree);             //前序遍历    void InOrder(Node *subtree);              //中序遍历    void LevelOrder(Node *subtree);           //按层遍历    void PostOrder(Node *subtree);            //后序遍历    void HuffmanCode(Node *&subtree);         //对已创建好的Huffman树进行编码public:    HuffmanTree(int A[],char B[],int n);      //构造函数    ~HuffmanTree(){destroy(root);}            //析构函数    void PreOrder(){cout<<"前序遍历: ";PreOrder(root);cout<<endl;}    void InOrder(){cout<<"中序遍历: ";InOrder(root);cout<<endl;}    void PostOrder(){cout<<"后序遍历:";PostOrder(root);cout<<endl;}    void LevelOrder(){cout<<"按层遍历: ";LevelOrder(root);cout<<endl;}    void MergeTree(Node *&t1,Node *&t2,Node *&parent);                            //合并子树    void HuffmanCode(){cout<<"编码结果: "<<endl;HuffmanCode(root);cout<<endl;} //调用编码函数};</span>

MinHeap.h:

<span style="font-size:12px;">//最小堆,存放森林#include "Node.h"#define DefaultSize 50template <class T>class MinHeap{private:    T *heap;    int currentSize;    void SiftUp(int start);    void SiftDown(int start,int over);public:    MinHeap():currentSize(0){ heap=new T[DefaultSize];}    ~MinHeap(){currentSize=0;}    bool Insert(const T &x);    bool RemoveMin(T &x);    bool IsEmpty(){return (currentSize==0)?true:false;}};template <class T>bool MinHeap<T>::Insert(const T &x){     heap[currentSize]=x;     SiftUp(currentSize);     currentSize++;     return true;}template <class T>void MinHeap<T>::SiftUp(int start){    int j=start,i=(j-1)/2;    T t;    while(i>=0)    {        if(heap[j]>=heap[i])  break;        else        {            t=heap[j];            heap[j]=heap[i];            heap[i]=t;            j=i;i=(j-1)/2;        }    }}template <class T>void MinHeap<T>::SiftDown(int start,int over){    T t;    int i=start,j=2*i+1;    while(j<=over)    {        if(j<over&&heap[j+1]<heap[j]) j++;        if(heap[j]>=heap[i]) break;        else        {            t=heap[j];            heap[j]=heap[i];            heap[i]=t;            i=j;j=2*i+1;        }    }}template <class T>bool MinHeap<T>::RemoveMin(T &x){    if(!IsEmpty())    {        x=heap[0];        heap[0]=heap[currentSize-1];        currentSize--;        SiftDown(0,currentSize-1);        return true;    }    else return false;}</span>
Queue.h:

<span style="font-size:12px;">template <class T>struct QNode{    T data;    QNode *next;    QNode():next(NULL){}    QNode(T _data):data(_data),next(NULL){}};template <class T>class Queue{private:    QNode<T> *front_,*rear;public:    Queue():front_(NULL),rear(NULL){}    bool EnQueue(const T &x);    bool DeQueue(T &x);    T getFront();    T getRear();    int getSize();    bool IsEmpty();};template <class T>bool Queue<T>::EnQueue(const T &x){   if(front_==NULL)   {       rear=front_=new QNode<T>(x);       return true;   }   else{    rear->next=new QNode<T>(x);    if(rear->next==NULL) return false;    rear=rear->next;   }   return true;}template <class T>bool Queue<T>::DeQueue(T &x){    if(IsEmpty()) return false;    else    {       QNode<T> *p=front_;       x=front_->data;       front_=front_->next;       delete p;       return true;    }}template <class T>T Queue<T>::getFront(){   return front_->data;}template <class T>T Queue<T>::getRear(){    return rear->data;}template <class T>int Queue<T>::getSize(){    if(front_==NULL) return 0;    if(front_==rear&&front_!=NULL) return 1;    int n=2;    QNode<T> *current=front_;    while(current->next!=rear)    {        n++;        current=current->next;    }    return n;}template <class T>bool Queue<T>::IsEmpty(){    if(front_==NULL)        return true;    return false;}</span>

Huffman.cpp:

<span style="font-size:12px;">#include <iostream>#include <iomanip>#include <string>#include "Queue.h"#include "MinHeap.h"#include "Huffman.h"using namespace std;//构造函数HuffmanTree::HuffmanTree(int A[],char B[],int n) //A为外结点权重,B为外结点名数组{    int i;    MinHeap<Node > mh;                           //使用最小堆存放森林    Node *parent,*first,*second,*temp;    for(i=0;i<n;i++)                             //森林各棵树初始化    {        temp=new Node(A[i],B[i]);        mh.Insert(*temp);                        //插入到最小堆中    }    for(i=0;i<n-1;i++)                           //循环n-1趟,形成huffman树    {        first=new Node;        second=new Node;        parent=new Node;        mh.RemoveMin(*first);                    //选出根的权值最小的树        mh.RemoveMin(*second);                   //选出根的权值次小的树        MergeTree(first,second,parent);          //合并 将first和second权值相加赋给parent结点        mh.Insert(*parent);                      //将合并后得到的根结点插入到最小堆中    }    root=parent;                                 //将建成的Huffman树根结点赋给root}//合并,将两个树根结点相加赋给parent结点,链接根结点与子女void HuffmanTree::MergeTree(Node *&t1,Node *&t2,Node *&parent){    parent->weight=t1->weight+t2->weight;    parent->lchild=t1;    parent->rchild=t2;    t1->parent=t2->parent=parent;}//删除以subtree为根结点的子树void HuffmanTree::destroy(Node *subtree){    if(subtree!=NULL)    {        destroy(subtree->lchild);        destroy(subtree->rchild);        delete subtree;    }}//前序遍历void HuffmanTree::PreOrder(Node *subtree){    if(subtree!=NULL)    {        cout<<left<<setw(4)<<subtree->weight;        PreOrder(subtree->lchild);        PreOrder(subtree->rchild);    }}//中序遍历void HuffmanTree::InOrder(Node *subtree){    if(subtree!=NULL)    {         InOrder(subtree->lchild);         cout<<left<<setw(4)<<subtree->weight;         InOrder(subtree->rchild);    }}//后序遍历void HuffmanTree::PostOrder(Node *subtree){    if(subtree!=NULL)    {         PostOrder(subtree->lchild);         PostOrder(subtree->rchild);         cout<<left<<setw(4)<<subtree->weight;    }}//按层遍历void HuffmanTree::LevelOrder(Node *subtree){    Queue<Node*> q;    Node *temp;    q.EnQueue(subtree);    while(!q.IsEmpty())    {        q.DeQueue(temp);        cout<<left<<setw(4)<<temp->weight;        if(temp->lchild!=NULL) q.EnQueue(temp->lchild);        if(temp->rchild!=NULL) q.EnQueue(temp->rchild);    }}//将Huffman树进行编码void HuffmanTree::HuffmanCode(Node *&subtree){     Queue<Node*> q;     Node *temp;     q.EnQueue(subtree);     while(!q.IsEmpty())     {         q.DeQueue(temp);         Node *l=temp->lchild,*r=temp->rchild;         if(l==NULL&&r==NULL)                                //左右子树都为空,到达外结点,输出外结点编码            {                cout<<left<<temp->ch<<" :  "<<temp->code<<endl;                continue;            }         if(l!=NULL){l->code=temp->code+"0";q.EnQueue(l);}    //左子树不为空,左子树根结点编码+0         if(r!=NULL){r->code=temp->code+"1";q.EnQueue(r);}    //右子树不为空,右子树根结点编码+1     }}</span>
main.cpp:

<span style="font-size:12px;">#include <iostream>#include "Huffman.h"#define Max 100using namespace std;int main(){    int A[Max],n,i;    char B[Max];    cout<<"请输入要创建的霍夫曼树的外结点个数: ";    cin>>n;    cout<<"请输入每个结点名: ";    for(i=0;i<n;i++)        cin>>B[i];    cout<<"请输入每个结点权重: ";    for(i=0;i<n;i++)        cin>>A[i];    HuffmanTree h(A,B,n);    h.HuffmanCode();    cout<<"遍历创建的Huffman树:"<<endl;    h.LevelOrder();    h.PreOrder();    return 0;}</span>


0 0
原创粉丝点击