哈夫曼树编码C语言实现

xiaoxiao2021-02-28  50

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

(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-12913-1-179-1-189-1-11411-1-12312-1-138-1-11110-1-18100615112319127829134942145105814111100-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; }

运行结果:

 

转载请注明原文地址: https://www.6miu.com/read-44896.html

最新回复(0)