Huffman编码的实现

Huffman树,是一类带权路径长度最短的树。
从树中一个节点到另一个节点之间的分支构成这二个节点之间的路径,路径上的分支数目称为路径的长度。
树的路径长度是从树根到每一个节点之间的路径长度之和。

 

// ----------Huffman----------------
#include  < iostream >
#include 
< cstring >
#include 
< cstdlib >
using   namespace  std;

// =========Huffman节点================
typedef  struct
ExpandedBlockStart.gifContractedBlock.gif
{
    unsigned 
int weight;//权值
    unsigned int Parent,LChild,RChild;
}
HTNode, * HuffmanTree;
// --------------------------------
typedef  char   ** HuffmanCode;

const   int  MAX_SIZE  =   100 ;

// 查询此e字符是否已出现
int  search( char  difchar[],  int  n,  char  e)
ExpandedBlockStart.gifContractedBlock.gif
{
    
for(int i = 1; i <= n; i++)
        
if(difchar[i] == e)
            
return i;
    
return -1;
}


// 计算相应字符出现的频率
int  stat( char  data[], char  difchar[], int  w[])
ExpandedBlockStart.gifContractedBlock.gif
{
    
int n = 0, i, len = strlen(data);
    
int xx;
    
for(i = 0; i < len; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        xx 
= search(difchar, n, data[i]);
        
if(xx == -1)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            difchar[
++n] = data[i];
            w[n] 
= 0;
        }

        
else
            w[xx]
++;
    }

    
return n;
}


int  GetMin(HuffmanTree t, int  i)
ExpandedBlockStart.gifContractedBlock.gif
{//返回i个结点中权值最小的且没有父节点的节点序号
    int j=1,flag,k;
    
while(t[j].Parent!=0)
        j
++;
    flag
=j;k=t[j].weight;//flag为t中第一个没有父节点的节点序号
    for(j++;j<=i;j++)
        
if(t[j].weight<k&&t[j].Parent==0)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{    k=t[j].weight;    
                flag
=j;
        }

    t[flag].Parent
=1;
    
return flag;
}


void  select(HuffmanTree t, int  i, int   & s1, int   & s2)
ExpandedBlockStart.gifContractedBlock.gif
{//在i个节点中选择2个权值最小的树的根节点序号
    int j;
    s1
=GetMin(t,i);
    s2
=GetMin(t,i);
    
if(t[s1].weight>t[s2].weight)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        j
=s1;
        s1
=s2;
        s2
=j;
    }

}


void  HuffmanCoding(HuffmanTree  & HT,HuffmanCode  & HC, int   * w, int  n)
ExpandedBlockStart.gifContractedBlock.gif
{
    
//w存放n个字符的权值,构造Huffman树HT,并求出n个字符的Huffman编码HC
    int s1,s2,start,m,i;
    unsigned c,f;
    
char *cd;
    HuffmanTree p;
    
if(n<=1)return;
    m
=2*n-1;//节点的总数
    HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));//节点0空 
    for(p=HT+1,i=1;i<=n;i++,p++,w++)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        p
->weight=*w;
        (
*p).Parent=(*p).LChild=(*p).RChild=0;
    }

    
for(;i<=m;i++,p++)
        (
*p).Parent=0;
    
for(i=n+1;i<=m;i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        select(HT,i
-1,s1,s2);//寻找权值最小的二棵子树
        HT[s1].Parent=HT[s2].Parent=i;
        HT[i].LChild
=s1;
        HT[i].RChild
=s2;
        HT[i].weight
=HT[s1].weight+HT[s2].weight;
    }

    HC
=(HuffmanCode)malloc((n+1)*sizeof(char*));
    cd
=(char*)malloc(n*sizeof(char));
    cd[n
-1]='\0';
    
for(i=1;i<=n;i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        start
=n-1;
        
for(c=i,f=HT[i].Parent;f!=0;c=f,f=HT[f].Parent)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
if(HT[f].LChild==c)
                cd[
--start]='0';
            
else
                cd[
--start]='1';
        }

        HC[i]
=(char*)malloc((n-start)*sizeof(char));
        strcpy(HC[i],
&cd[start]);

    }

    free(cd);
}


int  main()
ExpandedBlockStart.gifContractedBlock.gif
{//主函数
    HuffmanTree HT;
    HuffmanCode HC;
    
int n = 0,i;//n表示输入文字中不同字符的个数
    char data[MAX_SIZE];
    
char difchar[MAX_SIZE];
    
int w[MAX_SIZE];
    cout
<<"=====-请输入预编码的文字-====="<<endl;
    cout
<<"仅限英文字符,输入Ctrl+Z结束输入"<<endl;
    
while(cin.getline(data,MAX_SIZE,'\n'))
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        n 
= stat(data, difchar,w);
        HuffmanCoding(HT,HC,w
+1,n);
        cout
<<"=============字符与相应编码为============="<<endl;
        
for(i=1;i<=n;i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            cout
<<difchar[i]<<":";
            puts(HC[i]);
        }

        cout
<<endl<<"===============编码文字==============="<<endl;
        
for(i = 0; i < strlen(data);i++)
            cout
<<HC[search(difchar,n,data[i])];
        cout
<<endl<<endl;
        system(
"PAUSE");
        cout
<<"=====-请输入预编码的文字-====="<<endl;
        cout
<<"仅限英文字符,输入Ctrl+Z结束输入"<<endl;
    }

    
return 0;
}



 

转载于:https://www.cnblogs.com/Xredman/archive/2009/03/10/1407989.html

你可能感兴趣的:(Huffman编码的实现)