1. 程式人生 > >DS二叉樹--赫夫曼樹的構建與編碼

DS二叉樹--赫夫曼樹的構建與編碼

題目描述 給定n個權值,根據這些權值構造huffman樹,並進行huffman編碼

參考課本演算法,注意陣列訪問是從位置1開始

要求:赫夫曼的構建中,預設左孩子權值不大於右孩子權值

輸入 第一行輸入t,表示有t個測試例項 第二行先輸入n,表示第1個例項有n個權值,接著輸入n個權值,權值全是小於1萬的正整數 依此類推

輸出 逐行輸出每個權值對應的編碼,格式如下:權值-編碼
即每行先輸出1個權值,再輸出一個短劃線,再輸出對應編碼,接著下一行輸入下一個權值和編碼。 以此類推

樣例輸入
1 5 15 4 4 3 2
樣例輸出
15-1
4-010
4-011
3-001
2-000

思路

#include<iostream>
#include<string>
#include<cstring>
using namespace std;
 
const int maxW= 9999;
 
class HuffNode{
    public:
        int weight;
        int parent;
        int leftChild;
        int rightChild;
};
 
class HuffMan{
    private:
        void MakeTree(){
            for(int i= lnum+ 1; i<= len; i++){
                int s1, s2;
                SelectMin(i- 1, &s1, &s2);
                //cout<<s1<<s2<<"bbbbbbbbbbb"<<endl;
                //cout<<huffTree[s1].weight<<' '<<huffTree[s2].weight<<endl;
                huffTree[s1].parent= huffTree[s2].parent= i;
                huffTree[i].leftChild= s1;
                huffTree[i].rightChild= s2;
                huffTree[i].weight= huffTree[s1].weight+ huffTree[s2].weight;
            }
        }
        void SelectMin(int pos, int *s1, int *s2){
            int w1, w2, i;
            w1= w2= maxW;
            *s1= *s2= 0;
             
            for(i= 1; i<= pos ; i++){
                if(w1> huffTree[i].weight&&!huffTree[i].parent){
                     
                    w2= w1;
                    *s2= *s1;
                     
                    w1= huffTree[i].weight;
                    *s1= i;
                     
                }
                else if(w2> huffTree[i].weight&&!huffTree[i].parent){
                    w2= huffTree[i].weight;
                    *s2= i;
                }
            }
        }
         
    public:
        int len;
        int lnum;
        HuffNode *huffTree;
        string *huffCode;
        void MakeTree(int n, int wt[]){
            int i;
            lnum= n;
            len= 2*n- 1;
            huffTree = new HuffNode[2*n];
            huffCode= new string[lnum+ 1];
             
            for(i= 1; i<= n; i++)
               huffTree[i].weight= wt[i- 1];
             
            for(i= 1; i<= len; i++){
                if(i> n)
                 huffTree[i].weight= 0;
                 huffTree[i].parent= 0;
                 huffTree[i].leftChild= 0;
                 huffTree[i].rightChild= 0;
            }
            MakeTree();
        }
        void Coding(){
            char *cd;
            int i, c, f, start;
             
            cd= new char[lnum];
            cd[lnum- 1]= '\0';
            for(i= 1; i<= lnum; i++){
                start= lnum- 1;
                 
                for(c= i, f= huffTree[i].parent; f!= 0; c= f, f= huffTree[f].parent)
                   if(huffTree[f].leftChild== c){
                    cd[--start]= '0';
                    //cout<<cd[start];
                   } 
                   else{
                    cd[--start]= '1';
                   //   cout<<cd[start];
                   }
                      
                      
                //cout<<"aaaaaaaa"<<endl;
                 
                huffCode[i].assign(&cd[start]);
                //cout<<huffCode[i]<<&cd[start]<<endl;
            }
             
            delete []cd;
        }
        void Destroy(){
            len= 0;
            lnum= 0;
            delete []huffTree;
            delete []huffCode;
        }
};
 
int main(){
    int t, n,i,j;
    int wt[800];
    HuffMan myHuff;
    cin>>t;
    for(i= 0; i< t; i++){
        cin>>n;
        for(j= 0; j< n; j++)
           cin>>wt[j];
         
        myHuff.MakeTree(n, wt);
        myHuff.Coding();
        for(j= 1; j<= n; j++){
            cout<<myHuff.huffTree[j].weight<<'-';
            cout<<myHuff.huffCode[j]<<endl;
        }
        myHuff.Destroy();
    }
    return 0;
}