数据结构-----Huffman树

本文介绍了哈夫曼树的基本概念,包括最优二叉树的定义、路径与路径长度、结点的权与带权路径长度。重点讲述了如何构建哈夫曼树,包括从权值为根的二叉树森林开始,通过小堆逐步合并成哈夫曼树的过程,以及需要注意的比较器定义。此外,还提到了树的析构函数以确保内存安全,并给出了整体的代码实现,包括利用库中的优先级队列和自定义堆的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、基本概念
1、哈夫曼树(Huffman tree),又名最优树,指给定n个权值作为n的叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。若将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。
2、路径与路径长度
在一棵树中,从一个结点往下可以达到的孩子或孙子结点之间的通路,称为路径。通路中分支的数目称为路径长度。
若规定根结点的层数为1,则从根结点到第L层结点的路径长度为L-1。
3、结点的权与带权路径长度
带权结点:位于一棵树的叶子结点处。
若将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。
结点的带权路径长度为:从根结点到该结点之间的路径长度与该结点的权的乘积。
4、树的带权路径长度
树的带权路径长度规定为所有叶子结点的带权路径长度之和,记为WPL。
二、Huffman树的构造
1、创建以权值为根的二叉树森林
2、创建Huffman树—–>小堆
(1)取权值最小的树,作为left,并且从堆中将此元素删除
(2)再一次取权值最小的树,作为right,并且从堆中将此元素删除
(3)以left与right的权值创建新的结点parent,并让其parent的left指向left,parent的 right指向right,成功指向完成之后,并将其加入到二叉树森林中。
注意:需要判断堆中元素的个数,且不能利用堆中的比较器,堆中的比较器是比较的是地址,而在Huffman树中,需要比较的是树中权值的大小,因此,需要重新定义比较器,从而比较每个结点的权值。
构造树的代码如下所示:
过程:
这里写图片描述

void _CreatHuffmanTree(W*array, size_t size, const W& invalid)
    {
        //定义比较器,此处使用的原因是:在此要比较的是权值的大小
        struct Less
        {
            bool operator()(pNode left, pNode right)
            {
                return left->_weight < right->_weight;
            }
        };

        priority_queue<pNode, vector<pNode>, Less> hp;
        //将所有元素先放入到堆中
        for (size_t i = 0; i < size; ++i)
        {
            if (array[i] != invalid)                
                hp.push(new HuffmanTreeNode<W>(array[i]));          
        }
        //堆中没有元素(空堆)
        if (hp.empty())
            _pRoot = NULL;

        //利用堆创建Huffman树
        while ((int)hp.size()>1)
        {
            pNode pLeft = hp.top();
            hp.pop();

            pNode pRight = hp.top();
            hp.pop();

            pNode parent = new HuffmanTreeNode<W>(pLeft->_weight + pRight->_weight);

            parent->_pLeft = pLeft;
            parent->_pRight = pRight;
            hp.push(parent);
        }
        _pRoot = hp.top();
    }

三、树的析构函数
因为在树中,有对结点的申请,因此需要析构函数,从而确保内存安全。具体析构过程如下所示:

{
        //后序遍历
        pNode pCur = pRoot;
        if (pCur)
        {
            Destory(pCur->_pLeft);
            Destory(pCur->_pRight);
            delete pCur;
            pCur = NULL;
        }
    }

四、整体代码实现
首先利用库中的优先级队列,则实现过程如下:
库中

template < class T, class Container = vector<T>,
           class Compare = less<typename Container::value_type> > class<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值