算法分析与设计11(最优二元前缀)

1.问题

问题:给定字符集 C=
在这里插入图片描述
和每个字符的频率在这里插入图片描述
,求关于 C 的 一个最优前缀码。

2.解析

哈夫曼树的基本思想:选择权值小的叶子离根距离远。
第一步:以每个结点作为根,构造只有一个根结点的n棵二叉树,根的权值就是结点的权。
第二步:在所有二叉树中选择根的权值最小的两棵二叉树作为左右子树构造一棵新的二叉树,根的权值等于其左右子树的根的权值之和。
第三步:去掉选中的二叉树、加入新生成的二叉树。
第四步:重复2、3步,直至只剩下一棵树为止。
在这里插入图片描述

3.设计

int Build_Huffman_tree(unsigned int(&freqs)[NUM_CHARS], HuffNode(&Huffman_array)[MAX_SIZE], int n)
{                                                          //n表示freqs数组中实际包含的字符种类数
    char c;
    int k = 0, x1, x2;
    unsigned int m1, m2;

    for (int i = 0; i < NUM_CHARS; i++)//把前n个叶结点的信息输入Huffman_array数组
    {
        if (freqs[i])
        {
            c = i;//还原字符
            Huffman_array[k].data = c;
            Huffman_array[k].freq = freqs[i];
            Huffman_array[k].parent = 0;
            Huffman_array[k].lchild = 0;
            Huffman_array[k].rchild = 0;
            k++;
        }
    }
    for (int i = n; i < 2 * n - 1; i++)//处理剩下n-1个非叶子结点
    {
        Huffman_array[i].data = '#';
        Huffman_array[i].freq = 0;
        Huffman_array[i].parent = 0;
        Huffman_array[i].lchild = 0;
        Huffman_array[i].rchild = 0;
    }
    // 循环构造 Huffman 树
    for (int i = 0; i < n - 1; i++)
    {
        m1 = m2 = MAX_FREQ; // m1、m2中存放两个无父结点且结点权值最小的两个结点
        x1 = x2 = 0;  //x1、x2:构造哈夫曼树不同过程中两个最小权值结点在数组中的序号
        /* 找出所有结点中权值最小、无父结点的两个结点,并合并之为一颗二叉树 */
        for (int j = 0; j < n + i; j++)
        {
            if (Huffman_array[j].freq < m1 && Huffman_array[j].parent == 0)//parent 来控制该点是否被选取过了
            {            //如果当前判断的结点的权值小于最小的m1,则把它赋给m1,同时
                m2 = m1;   //更新m1结点的下标, 保持m1是当前所有判断过的元素中是最小的
                x2 = x1;   //再把m1的信息赋给m2,保持m2是当前所有判断过的元素中是第二小的
                m1 = Huffman_array[j].freq;
                x1 = j;
            }
            else if (Huffman_array[j].freq < m2 && Huffman_array[j].parent == 0)
                //如果当前判断的结点的权值大于等于最小的m1,但是小于m2,
            {            //则只需把它赋给m2,更新m2,保持m2是当前所有判断过的元素中是第二小的
                m2 = Huffman_array[j].freq;
                x2 = j;
            }
        }
        /* 设置找到的两个子结点 x1、x2 的父结点信息 */
        Huffman_array[x1].parent = n + i;
        Huffman_array[x2].parent = n + i;
        Huffman_array[n + i].freq = Huffman_array[x1].freq + Huffman_array[x2].freq;
        Huffman_array[n + i].lchild = x1;
        Huffman_array[n + i].rchild = x2;
    }
    return 0;
}

4.分析

Build_Huffman_tree(freqs, Huffman_array, char_size);

O(nlogn)频率排序;for 循环 O(n)O(nlogn)频率排序;for 循环 O(n),插入操作 O(logn)
算法时间复杂度是 O(n logn)

5.源码

GitHub源码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值