哈夫曼树编码C语言实现

实现哈夫曼树编码的算法可分为两大部分:

(1)构造哈夫曼树;

(2)在哈夫曼树上求叶结点的编码;

哈夫曼树构造算法:

(1)由给定的n个权值构造n棵只有一个叶结点的二叉树,从而得到一个二叉树的集合F={T1,T2,,...,TN}

(2)在F中选取根结点的权值最小和次小的两棵二叉树作为左,右子树构造一棵新的二叉树,这棵二叉树根结点的权值为其左右子树权值之和

(3)在集合F中删除作为左右子树的两棵二叉树,并将新建立的二叉树加入到集合F中

(4)重复(2)(3)直到F中只剩下最后一棵所需的二叉树,就是哈夫曼树

在哈夫曼树上求叶结点的编码算法:

在已建立的哈夫曼树中,从叶结点开始,沿结点的双亲链回退到根结点,每回退一步,就走过了哈夫曼树的一个分支,从而得到一位哈夫曼的值

规定哈夫曼树中的左分支代表0,右分支代表1

举例:

A:5 B:29 C:7 D:8 E:14 F:23 G:3 H:11

哈夫曼树:

哈夫曼树的存储:

weight         parent   Lchild    Rchild

 

58-1-1
2913-1-1
79-1-1
89-1-1
1411-1-1
2312-1-1
38-1-1
1110-1-1
81006
151123
191278
291349
4214510
5814111
100-11213

源代码:

 


#include<stdio.h>
#define n 8                                        //叶子结点数目
#define m (2*n-1)                                  //总结点数目,可证明
#define MAXVALUE 10000                             //最大权值
#define MAXBIT 20                                  //哈夫曼编码最大长度
typedef struct                                     
{
    char ch;
    int weight;                                    
    int parent;                                    
    int Lchild, Rchild;
}Htreetype;
typedef struct
{
    int bit[n];                                   //位串
    int start;                                    //编码在位串中的起始位置
    char ch;       
}Hcodetype;
void select(Htreetype t[], int k, int *p1, int *p2)  //选择权值最小的结点
{
    *p1 = *p2 = 0;
    int small1, small2;
    small1 = small2 = MAXVALUE;
    int i;
    for (i = 0; i < k; i++)
    {
        if (t[i].parent == -1)
        {
            if (t[i].weight < small1)
            {
                small2 = small1;
                small1 = t[i].weight;
                *p2 = *p1;
                *p1 = i;
            }
            else if (t[i].weight < small2)
            {
                small2 = t[i].weight;
                *p2 = i;
            }
        }
    }
}
void HuffmanTree(Htreetype t[])                  //构造哈夫曼树
{
    int i, j, p1, p2, f;
    p1 = p2 = 0;
    char c;
    for (i = 0; i < m; i++)                       //初始化
    {
        t[i].weight = 0;
        t[i].Lchild = -1;
        t[i].parent = -1;
        t[i].Rchild = -1;
    }
    printf("共有%d个字符\n", n);
    for (i = 0; i < n; i++)                            //输入字符和对应的权值
    {
        printf("请输入第%d个字符和权值','分隔", i + 1);
        scanf("%c,%d", &c,&f);
        getchar();
        t[i].ch = c;
        t[i].weight = f;
    }
    for (i = n; i < m; i++)                            //构造哈夫曼树
    {
        select(t, i, &p1, &p2);
        t[p1].parent = i;
        t[p2].parent = i;
        t[i].Lchild = p1;
        t[i].Rchild = p2;
        t[i].weight = t[p1].weight + t[p2].weight;
    }
}
void HuffmanCode(Hcodetype code[],Htreetype t[])                                   //哈夫曼编码
{
    int i, c, p;
    Hcodetype cd;      //缓冲变量,暂时存储
    HuffmanTree(t);
    for (i = 0; i < n; i++)
    {
        cd.start = n;
        cd.ch = t[i].ch;
        c = i;               //从叶子结点向上
        p = t[i].parent;     //t[p]是t[i]的双亲
        while (p != -1)
        {
            cd.start--;
            if (t[p].Lchild == c)
                cd.bit[cd.start] = '0';        //左子树编为0
            else
                cd.bit[cd.start] = '1';        //右子树编为1
            c = p;                             //移动
            p = t[c].parent;
        }
        code[i] = cd;                         //第i+1个字符的编码存入code
    }
}
void show(Htreetype t[], Hcodetype code[])
{
    int i, j;
    for (i = 0; i<n; i++)
    {
        printf("%c: ", code[i].ch);
        for (j = code[i].start; j<n; j++)
            printf("%c ", code[i].bit[j]);
        printf("\n");
    }
}
void Print()
{
    printf("戴尔XPS-15\n");
    
}
int main()
{
    Htreetype t[m];
    Hcodetype code[n];
    HuffmanCode(code, t);
    show(t,code);
    return 0;
}


运行结果:

 

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页