数据结构学习第6篇 - 哈夫曼编码问题 编码和解码

哈夫曼编码问题

利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。根据哈夫曼编码的原理,根据用户输入的一段文本,请编程实现的哈夫曼编码的编码与解码过程,并给出该段文本的编码结果与解码结果。

注意:1.测试文本可以预先存储在文件中

      2.叶结点的权重直接从文本中统计得出



#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>

#define MAXVALUE 10000                            //定义最大权值
#define MAXLEAF 30                                //定义哈夫曼树中叶子结点个数
#define MAXNODE MAXLEAF*2-1                        //定义哈夫曼总结点数
#define MAXSIZE 256

int n;
char str[MAXLEAF];

typedef struct
{
    int weight;
    int parent;
    int rchild;
    int lchild;    
}HNodeType;

typedef struct
{
    char data;
    int weight;
}HDatatype;

typedef struct
{
    HDatatype data[MAXSIZE];
    int number;
}HNodeNum;

/*
    找到各个字符的权重并排序
*/
void Find_Weight(HNodeNum ** pHn,char val[])
{
    int i,j;
    HDatatype t;
    *pHn = (HNodeNum* )malloc(sizeof(HNodeNum));
    (*pHn)->number = 0;
    for(i=0;i<MAXSIZE;i++)                            //初始化存放数据所对应的权重
    {
        ((*pHn)->data[i]).weight = 0;
    }
    
    for(i=0;val[i]!='\0';i++)                        //存放数据并计算各种字符的权重
    {
        for(j=0;j<(*pHn)->number;j++)
        {
            if(((*pHn)->data[j]).data == val[i])
            {
                ((*pHn)->data[j]).weight ++;
                break;
            }
        }
        if(j>=(*pHn)->number)
        {
            ((*pHn)->data[j]).data = val[i];
            ((*pHn)->data[j]).weight = 1;
            (*pHn)->number ++;
        }
    }
    
    //冒泡法排序
    for(i=0;i<(*pHn)->number-1;i++)
    {
        for(j=0;j<(*pHn)->number-1-i;j++)
        {
            if(((*pHn)->data[j]).weight >((*pHn)->data[j+1]).weight)
            {
                t = (*pHn)->data[j];
                (*pHn)->data[j] = (*pHn)->data[j+1];
                (*pHn)->data[j+1] = t;
            }
        }        
    }
    
    for(i = 0; i <(*pHn)->number; i++)                        //输出各种字符和其所对应的权重
    {
        printf("%c %d\n",((*pHn)->data[i]).data, ((*pHn)->data[i]).weight);
    }

}

HNodeNum * HuffmanTree(HNodeType HuffNode[])
{
    /*哈夫曼树的构造算法*/
    int i, j, m1, m2, x1, x2;
    HNodeNum * pHn = NULL;
    printf("输入字符串:\n");
    gets(str);
    Find_Weight(&pHn, str);
    n = pHn->number;                                //得到叶子结点个数

    for(i = 0; i < 2 * n - 1; i++)                    //数组Huffman[]初始化
    {
        HuffNode[i].weight = 0;
        HuffNode[i].parent = -1;
        HuffNode[i].lchild = -1;
        HuffNode[i].rchild = -1;
    }
    
    for(i = 0; i < n; i++)                            //把构造哈夫曼树的权重放到静态
    {
        HuffNode[i].weight = (pHn->data[i]).weight;    
    }
    
    for(i = 0; i < n-1; i++)
    {
        m1 = m2 = MAXVALUE;
        x1 = x2 = 0;
        for(j = 0; j < n+i; j++)
        {
            if(HuffNode[j].weight < m1 && HuffNode[j].parent == -1)
            {
                m2 = m1;
                x2 = x1;
                m1 = HuffNode[j].weight;
                x1 = j;
            }
        
            else if(HuffNode[j].weight < m2 && HuffNode[j].parent == -1)
            {
                m2 = HuffNode[j].weight;
                x2 = j;
            }
        }
        HuffNode[x1].parent = n + i;
        HuffNode[x2].parent = n + i;
        HuffNode[n+i].weight = HuffNode[x1].weight + HuffNode[x2].weight;
        HuffNode[n+i].lchild = x1;
        HuffNode[n+i].rchild = x2;
    
    }
    return pHn;
}

/*
    定义哈夫曼编码的长度
*/

#define MAXBIT 100                                           //定义哈夫曼编码的最大长度
#define MAXSTR 1000                                         //定义字符串转化为哈夫曼编码的最大长度
typedef struct
{
    int bit[MAXBIT];
    int start;
}HCodeType;

void HuffmanCode()
{
    /*生成哈夫曼编码*/
    HNodeType HuffNode[MAXNODE];
    HCodeType HuffCode[MAXLEAF], cd;
    int HuffStr[MAXSTR];
    HNodeNum * pHn = NULL;
    int i, j, k, c, p, l = 0;
    pHn = HuffmanTree(HuffNode);                            //建立哈夫曼树
    for(i = 0; i < n; i++)                                    //求每个叶子结点的哈夫曼编码
    {
        cd.start = n - 1;
        c = i;
        p = HuffNode[c].parent;    
                
        while(p != -1)                                        //由叶结点向上直到树根
        {
            
            if(HuffNode[p].lchild == c)
            {
                cd.bit[cd.start] = 0;
            }
        
            else
            {
                cd.bit[cd.start] = 1;
            }
            
            cd.start = cd.start - 1;
            c = p;
            p = HuffNode[c].parent;
        
        }
        
        for(j = cd.start + 1; j < n; j++)            //保存求出的每个叶子结点的哈夫曼编码和编码的起始位
        {
            HuffCode[i].bit[j] = cd.bit[j];
        }
        HuffCode[i].start = cd.start;

        
    }
    for(i = 0; i < n; i++)                            //输出各种字符对应的哈夫曼编码
    {
        printf("%c--",(pHn->data[i]).data);
        for(j = HuffCode[i].start + 1; j < n; j++)
        {
            printf("%d",HuffCode[i].bit[j]);    
        }    
        printf("\n");
    }    
    
    printf("转码为:");
    //把字符串转化为haffman编码
    for(i = 0; str[i]!='\0'; i++)
    {
        for(j = 0; j < n; j++)
        {
            if(str[i] == (pHn->data[j]).data)
            {
                for(k = HuffCode[j].start + 1; k < n; k++)
                {
                    HuffStr[l] = HuffCode[j].bit[k];
                    printf("%d",HuffStr[l]);
                    l++;    
                }    
            }    
        }    
    }
    printf("\n");

    //解码
    printf("解码为:");
    c = 2 * n - 2;
    for(i = 0; i < l; i++)
    {
        if(HuffStr[i] == 0)
        {
            c = HuffNode[c].lchild;
        }
        if(HuffStr[i] == 1)
        {
            c = HuffNode[c].rchild;
        }
        if(HuffNode[c].lchild == -1 && HuffNode[c].rchild == -1)
        {
            printf("%c",(pHn->data[c]).data);
            c = 2 * n - 2;    
        }
    }
    printf("\n");
}
int main()
{
    HuffmanCode();    
}

猜你喜欢

转载自blog.csdn.net/guanshanyue96/article/details/89007859