赫夫曼编码

构造过程:
1.给定一组带权值的节点:

2 .生成赫夫曼树:
赫夫曼编码_第1张图片

3.根据“左0右1”的约定生成编码表
实现:

/*************************************************
赫夫曼编码
by Rowandjj
2014/6/2
*************************************************/
#include<iostream>
using namespace std;

#define UINT_MAX 0xffffffff

typedef struct _HUFFMANTREE_//赫夫曼树
{
    unsigned int weight;
    unsigned int lChild;
    unsigned int rChild;
    unsigned int parent;
}HuffmanTree,*pHuffmanTree;

typedef char** HuffmanCode;//动态分配数组存储赫夫曼编码表

void SelectNode(pHuffmanTree &pHuffmanTreeTemp,int i,int *m,int *n);
int GetNode(pHuffmanTree &pHuffmanTreeTemp,int i);
void HuffmanCoding(pHuffmanTree &pHuffmanTreeTemp,int *p,HuffmanCode &hc,int n);//n为叶子节点数,p为权值数组
//----------------------------------


int main()
{
    pHuffmanTree pHuffmanTreeTemp;
    HuffmanCode hc;
    int num;
    cout<<"输入叶子节点个数:"<<endl;
    cin>>num;
    int *p = (int*)malloc(sizeof(int)*num);
    for(int i = 0; i < num; i++)
    {
        cout<<"输入节点权值:"<<endl;
        cin>>*(p+i);
    }
    HuffmanCoding(pHuffmanTreeTemp,p,hc,num);
    
    cout<<"----------------------"<<endl;
    cout<<"打印赫夫曼码表:"<<endl;
    for(i = 1; i <= num; i++)//
    {
        cout<<hc[i]<<endl;
    }


    cout<<"----------------------"<<endl;
    cout<<"打印赫夫曼树:"<<endl;
    for(i = 1; i <= 2*num-1; i++)
    {
        cout<<pHuffmanTreeTemp[i].weight<<" ";
    }
    cout<<endl;
    return 0;
}

void HuffmanCoding(pHuffmanTree &pHuffmanTreeTemp,int *p,HuffmanCode &hc,int n)
{
    if(n <= 1)
    {
        return;
    }
    //总节点数
    int m = 2*n - 1;
    pHuffmanTreeTemp = (pHuffmanTree)malloc(sizeof(HuffmanTree)*(m+1));
    for(int i = 1; i <= n; i++)//赋有效值(带权值的节点)
    {
        pHuffmanTreeTemp[i].weight = *p;
        pHuffmanTreeTemp[i].parent = 0;
        pHuffmanTreeTemp[i].lChild = 0;
        pHuffmanTreeTemp[i].rChild = 0;
        p++;
    }
    
    for(; i <= m; i++)//后面的节点全部初始化为0
    {
        pHuffmanTreeTemp[i].weight = 0;
        pHuffmanTreeTemp[i].parent = 0;
        pHuffmanTreeTemp[i].lChild = 0;
        pHuffmanTreeTemp[i].rChild = 0;
    }
    //建立赫夫曼树
    int s1,s2;
    for(i = n+1;i <= m; i++)
    {
        SelectNode(pHuffmanTreeTemp,i-1,&s1,&s2);
        pHuffmanTreeTemp[s1].parent = pHuffmanTreeTemp[s2].parent = i;
        pHuffmanTreeTemp[i].lChild = s1;//索引小的作为左子树
        pHuffmanTreeTemp[i].rChild = s2;
        pHuffmanTreeTemp[i].weight = pHuffmanTreeTemp[s1].weight + pHuffmanTreeTemp[s2].weight;
    }
    
    
    //赫夫曼编码
    hc = (HuffmanCode)malloc(sizeof(char*)*(n+1));
    char* cd = (char*)malloc(sizeof(char)*n);
    cd[n-1] = '\0';
    int start,c,f;
    for(i = 1; i <= n; i++)//求每个带权节点的赫夫曼编码
    {
        start = n-1;
        //从叶子到根逆向求编码
        for(c = i,f = pHuffmanTreeTemp[c].parent;f != 0;c = f,f = pHuffmanTreeTemp[f].parent)
        {
            if(pHuffmanTreeTemp[f].lChild == c)//左0右1
            {
                cd[--start] = '0';
            }else
            {
                cd[--start] = '1';
            }
        }
        hc[i] = (char*)malloc(sizeof(char)*(n-start));
        strcpy(hc[i],&cd[start]);//从cd将编码串复制到赫夫曼表中
    }
    free(cd);
    
}

void SelectNode(pHuffmanTree &pHuffmanTreeTemp,int i,int *m,int *n)
{
    *m = GetNode(pHuffmanTreeTemp,i);
    *n = GetNode(pHuffmanTreeTemp,i);

    int temp;
    if(*m > *n)
    {
        temp = *m;
        *m = *n;
        *n = temp;
    }
}

int GetNode(pHuffmanTree &pHuffmanTreeTemp,int i)
{
    int j;
    int min = UINT_MAX;
    int flag = 0;
    for(j = 1;j <= i; j++)
    {
        if(pHuffmanTreeTemp[j].weight < min && pHuffmanTreeTemp[j].parent == 0)
        {
            min = pHuffmanTreeTemp[j].weight;
            flag = j;
        }
    }
    pHuffmanTreeTemp[flag].parent = 1;
    return flag;
}

测试:
赫夫曼编码_第2张图片





你可能感兴趣的:(赫夫曼编码)