Huffman編碼與譯碼

近期學習數據結構碰到Huffman編碼與譯碼問題,自己動手寫了一些,註釋比較全,OK,下面直接貼代碼。

#include<iostream>

#include<stdlib.h>

#define TElemType char

#define WType int

#define leafNumber 5   //默認權重集合大小

#define totalNumber 9  //樹節點個數=2*leafNumber-1

using namespace std;

 

struct HuffmanNode{     //樹結點的類定義

    TElemType data;     //數據

    WType weight;       //權重

    string code="Huffman編碼:";

    int lchild,rchild,parent;   //指針

};

struct HuffmanTree{     //Huffman樹結構定義

    HuffmanNode elem[totalNumber];      //樹存儲數組(靜態鏈表)

    int currentNumber;      //當前外結點個數

};

 

void CreateHuffmanTree( HuffmanTree& HT ,TElemType Data[], WType w[] , int n ){

    int i,j,p1,p2,min1,min2,maxValue=10000;     //p1記錄最小,p2記錄最小

    for(i=0;i<n;i++)

    {

        HT.elem[i].data=Data[i];

        HT.elem[i].weight=w[i];     //對第i個葉子節點賦權重

    }

 

    for(i=0;i<2*n-1;i++)

        HT.elem[i].parent=HT.elem[i].lchild=HT.elem[i].rchild=-1;     //初始化所有結點的左,右孩子標誌和父標誌爲-1

    for(i=n;i<2*n-1;i++){

        min1=min2=maxValue;

        for(j=0;j<i;j++){          //尋找最小和次小值的根,建樹

            if(HT.elem[j].parent==-1)       //父指針爲空時纔有資格參選

            if(HT.elem[j].weight<min1){     //比原來最小的還要小

                p2=p1;min2=min1;        //原來最小的變爲次小

                p1=j;min1=HT.elem[j].weight;    //記下新的最小

            }

            else if(HT.elem[j].weight<min2)     //否則比原來的次小還要小

            {

                p2=j;min2=HT.elem[j].weight;    //記下新的次小

            }

        }

        HT.elem[i].lchild=p1;       //左最小

        //HT.elem[p1].code=HT.elem[p1].code+"0";

        HT.elem[i].rchild=p2;       //右次小

        //HT.elem[p1].code=HT.elem[p1].code+"1";

        HT.elem[i].weight=HT.elem[p1].weight+HT.elem[p2].weight;

        HT.elem[p1].parent=HT.elem[p2].parent=i;        //鏈接父結點

    }

    HT.currentNumber=2*n-1;

}

 

void Insert( int father , HuffmanTree &HT )

{

    if(HT.elem[father].rchild!=-1||HT.elem[father].lchild!=-1)

    {

        HT.elem[HT.elem[father].lchild].code=HT.elem[father].code+"0";

        HT.elem[HT.elem[father].rchild].code=HT.elem[father].code+"1";

 

        Insert( HT.elem[father].lchild , HT );

        Insert( HT.elem[father].rchild , HT );

    }

}

 

void Code( HuffmanTree &HT )

{

    int i,root;

    for(i=0;i<totalNumber;i++)

    {

        if(HT.elem[i].parent==-1)

            break;

    }

    root=i;

    //cout<<root;   //用作測試看其根節點下標是否正確

    Insert( root , HT );

}

 

/*

void Code(HuffmanTree& HT)

{

    int i;

    for(i=0;i<leafNumber;i++)

    {

        int j=i;

        while(HT.elem[j].parent!=-1){

            if(HT.elem[HT.elem[j].parent].rchild==j)

                HT.elem[j].code="1"+HT.elem[j].code;

            if(HT.elem[HT.elem[j].parent].lchild==j)

                HT.elem[j].code="0"+HT.elem[j].code;

            j=HT.elem[i].parent;

        }

    }

}

*/

void Output( HuffmanTree& HT )      

{

    int i;

    for(i=0;i<leafNumber;i++)

    cout<<HT.elem[i].data<<" "<<"權重:"<<HT.elem[i].weight<<" "<<HT.elem[i].code<<endl;

}

 

void Trans( HuffmanTree &HT )

{

    cout<<"請輸入電文(0,1所組成的字符串):"<<endl;

    char ch[100];

    cin>>ch;

    int i,root;

    for(i=0;i<totalNumber;i++)

    {

        if(HT.elem[i].parent==-1)

            break;

    }

    root=i;

    int father;

    cout<<"譯碼:";

    for(i=0;ch[i]!='\0';)

    {

         father=root;

        while(HT.elem[father].lchild !=-1)

        {

            if(ch[i]=='0')

                father=HT.elem[father].lchild;

            else if(ch[i]=='1')

                father=HT.elem[father].rchild;

           i++;

        }

        cout<<HT.elem[father].data;

    }

}

 

int main()

{

    HuffmanTree HT;

    int n,i;

    cout<<"請輸入葉子結點個數"<<endl;

    cin>>n;

    WType w[n];

    TElemType Data[n];

    cout<<"請輸入結點代號(字符)"<<endl;

    for(i=0;i<n;i++)

        cin>>Data[i];

    cout<<"請輸入結點權重"<<endl;

    for(i=0;i<n;i++)

        cin>>w[i];

    CreateHuffmanTree( HT ,Data, w , n );

    Code( HT ); //編碼

    Output( HT );

    Trans( HT ); //譯碼

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章