哈夫曼树的应用

文章详细介绍了如何基于字符出现的概率构建哈夫曼树,并生成相应的哈夫曼编码。提供了C语言实现代码,展示了从计算字符概率到构造哈夫曼树,再到获取编码的完整过程。同时,分析了算法的时间复杂度和空间复杂度,均为O(nlogn)。
摘要由CSDN通过智能技术生成

要传输一则报文内容如下:
“AAAAAAAAAAAAAAABBBBBBBBBCCCCCCCCDDDDDDDDDDDDEEEEEEEEEEFFFFF”
在这段报文中,各个字母出现的次数如下:

请为这段古诗设计哈夫曼编码,要求如下:

  • Ø请计算出每个字符出现的概率,并以概率为权重来构造哈夫曼树。
  • Ø根据设计的哈夫曼树得到每个字符的哈夫曼编码。
  • Ø请将上述设计哈夫曼编码的过程,用代码来实现,并输出各个字母的哈夫曼编码。
  • Ø请分析算法的效率,如时间复杂度和空间复杂度等。
  1. 计算每个字符出现的概率:
    A出现的次数为15,概率为15/59=0.254;
    B出现的次数为9,概率为10/59=0.153;
    C出现的次数为8,概率为8/59=0.136;
    D出现的次数为12,概率为12/59=0.203;
    E出现的次数为10,概率为10/59=0.169;
    F出现的次数为5,概率为5/59=0.085。

    2. 构造哈夫曼树:
    将每个字符作为一个单独的叶子节点,按照概率从小到大依次构造哈夫曼树,具体过程如下:
    1. 首先将概率最小的两个节点合并,构造出新节点,该节点的权值为两个子节点的权值之和,新节点的左右子节点分别为原来的两个节点;
    2. 对于新构造出的节点,将其删去,重复步骤1,直到只剩下一个节点,该节点就是哈夫曼树的根节点。

    构造好的哈夫曼树如下图所示:
    • 选择权重最小的两个编码 分别是F:5/59 和 C:8/59 并计算其权重的和为 13/59 
    • 再次选择权重最小的两个编码 分别是B:9/59 和 E:10/59 并计算其权重的和为 19/59 
    • 再次选择权重最小的两个编码 分别是D:12/59 和 M1:13/59 并计算其权重的和为 25/59 
    • 再次选择权重最小的两个编码 分别是A:15/59 和 M2:19/59 并计算其权重的和为 34/59 
    • 再次选择权重最小的两个编码 分别是M3:25/59 和 M4:34/59 并计算其权重的和为 1 是该哈夫曼树的根节点。



3. 得到每个字符的哈夫曼编码:
对于哈夫曼树中的每个叶子节点,由根节点走到该节点的路径即为该节点对应字符的哈夫曼编码,从左往右为0,从右往左为1。如下表所示:

| 字符 | 概率 | 哈夫曼编码 |
|------|------|-----------|
|  A   | 0.254|    10     |
|  B   | 0.153|    110    |
|  C   | 0.136|    011      |
|  D   | 0.203|     00       |
|  E   | 0.169|    111     |
|  F   | 0.085|    010     |

4.代码:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#define MAXN 100 // 最大字符数

#define MAXCODE 20 // 最大编码长度

typedef struct  // 节点类型

{

    char ch; // 字符

    double freq; // 字符出现的概率

    char code[MAXCODE]; // 字符对应的哈夫曼编码

    int parent; // 父节点位置

    int left; // 左子树位置

    int right; // 右子树位置

} HuffNode, *HuffTree;

void huffman(int n, HuffTree H) // 构造哈夫曼树

{

    double min1, min2; // 记录两个最小概率

    int x, y; // 两个最小概率对应的节点位置

    for (int i = 0; i < 2 * n - 1; i++)

    {

        H[i].parent = H[i].left = H[i].right = -1;

        H[i].code[0] = '\0';

    }

    for (int i = 0; i < n - 1; i++)

    {

        x = y = -1;

        min1 = min2 = 1.0;

        for (int j = 0; j < n + i; j++)

        {

            if (H[j].parent == -1 && H[j].freq < min1)

            {

                min2 = min1;

                min1 = H[j].freq;

                y = x;

                x = j;

            }

            else if (H[j].parent == -1 && H[j].freq < min2)

            {

                min2 = H[j].freq;

                y = j;

            }

        }

        H[x].parent = n + i;

        H[y].parent = n + i;

        H[n + i].freq = min1 + min2;

        H[n + i].left = x;

        H[n + i].right = y;

    }

}

void getHuffCode(int n, HuffTree H) // 获取哈夫曼编码

{

    char code[MAXCODE];

    int start, c, p;

    code[n - 1] = '\0';

    for (int i = 0; i < n; i++)

    {

        start = n - 1;

        c = i;

        p = H[i].parent;

        while (p != -1)

        {

            if (H[p].left == c)

            {

                code[--start] = '0';

            }

            else

            {

                code[--start] = '1';

            }

            c = p;

            p = H[p].parent;

        }

        strcpy(H[i].code, &code[start]);

    }

}

int main()

{

    char str[MAXN];

    scanf("%s", str);

    int num[MAXN] = {0};

    int n = strlen(str), count = 0;

    for (int i = 0; i < n; i++)

    {

        num[str[i] - 'A']++;

    }

    for (int i = 0; i < MAXN; i++)

    {

        if (num[i] > 0)

        {

            count++;

        }

    }

    HuffTree H = (HuffNode*)malloc(sizeof(HuffNode) * (2 * count - 1));

    int j = 0;

    for (int i = 0; i < MAXN; i++)

    {

        if (num[i] > 0)

        {

            H[j].ch = i + 'A';

            H[j].freq = (double)num[i] / n;

            j++;

        }

    }

    huffman(count, H);

    getHuffCode(count, H);

    for (int i = 0; i < count; i++)

    {

        printf("%c: %s", H[i].ch, H[i].code);

    }

    free(H);

    return 0;

}

运行截图:


5. 算法效率分析:
- 时间复杂度:构造哈夫曼树的时间复杂度为O(nlogn),其中n为叶子节点的个数,获取哈夫曼编码的时间复杂度为O(n),因此总的时间复杂度为O(nlogn)。
- 空间复杂度:构造哈夫曼树的空间复杂度为O(n),其中n为叶子节点的个数,获取哈夫曼编码的空间复杂度为O(nlogn),因此总的空间复杂度为O(nlogn)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值