Huffman编码树的C++实现

Huffman编码树

  • Huffman编码将为字母分配代码。代码长度取决于对应字母的相对使用频率或者“权重”(weight),因此它是一种变长编码。
  • 每个字母的Huffman编码是从称为Huffman编码树(Huffman coding tree)或简称为Huffman树(Huffman tree)的满二叉树中得到。
  • Huffman树的每个叶结点对应于一个字母,叶结点的权重就是它对应字母出现的频率。
  • 一个叶结点的加权路径长度定义为权重乘以路径长度。
  • 权重大的叶结点的深度小,因为它相对总路径长度的花费最小;权重晓得叶结点的深度大,因而它相对总路径长度的花费最大。
  • Huffman树的建立:首先,穿件n个初始的Huffman树,每棵树值包含一个单一的叶结点,叶结点记录对应的字母。将这n棵树按照权重(如频率)大小顺序排为一列。接着,拿走前两棵树(权重最小的两棵树),再把它们标记为Huffman树的叶结点,把这两个叶结点标记为一个分支节点的两个子结点,而这个分支节点的权重就为两个叶结点权重的和。把所得的新树放回到序列中的适当位置,是的权重的顺序保持升序。重复上述步骤,直至序列中只剩下一个元素,则Huffman树建立完毕。
    如下图所示:图片描述
    图片描述

  • 抽象基类HuffmanNode:

template<typename E>class HuffmanNode{
public:
    virtual ~HuffmanNode() {}
    virtual int weight() = 0;
    virtual bool isLeaf() = 0;
};
  • 子类LeafNode(用于叶子结点):
template<typename E>class LeafNode :public HuffmanNode < E > {
private:
    E it;     //元素值
    int wgt;  //权重
public:
    //构造函数
    LeafNode(const E& val,int wg)
    {
        it = val;
        wgt = wg;
    }

    int weight() { return wgt; }    //返回权重
    E val() { return E; }           //返回元素值
    bool isLeaf() { return true; }  //返回就是叶结点
};
  • 子类IntlNode(用于分支结点):
template<typename E>
class IntlNode :public HuffmanNode < E > {
private:
    HuffmanNode<E>* lc;   //左子结点
    HuffmanNode<E>* rc;   //右子结点
    int wgt;              //权重
public:
    //构造函数
    IntlNode(HuffmanNode<E>* l,HuffmanNode<E>* r)
    {
        wgt = l->weight() + r->weight();
        lc = l;
        rc = r;
    }

    int weight() { return wgt; }   //返回权重
    bool isLeaf() { return false; } //不是叶结点
    //返回左子结点和设置左子结点
    HuffmanNode<E>* left() const { return lc; }
    void setLeft(HuffmanNode<E>* l) { lc = l; }
    //返回右子结点和设置右子结点
    HuffmanNode<E>* right() const { return rc; }
    void setRight(HuffmanNode<E>* r) { rc = r; }
};
  • 最小堆的实现(用于选出一组树中最小的元素):
template<typename E> class heap{
private:
    E* Heap;    //堆序列的指针
    int maxsize;   //堆的最大容量
    int n;      //堆里面的元素数量

    void siftdown(int pos)
    {
        while (!isLeaf(pos))
        {
            int j = leftchild(pos);
            int rc = rightchild(pos);
            if ((rc < n) && prior(Heap[j], Heap[rc]))
                j = rc;
            if (prior(Heap[j], Heap[pos]))    return;
            swap(Heap, pos, j);
            pos = j;
        }
    }
public:

    //构造函数
    heap(E* h, int num, int max)
    {
        Heap = h; n = num; maxsize = max;s
        buildHeap();
    }
    //返回对的大小
    int size() const
    {
        return n;
    }
    //判断是否为叶节点
    bool isLeaf(int pos) const
    {
        return (pos >= n / 2) && (pos < n);
    }
    //返回左节点
    int leftchild(int pos) const
    {
        return 2 * pos + 1;
    }
    //返回右节点
    int rightchild(int pos) const
    {
        return 2 * pos + 2;
    }
    //返回父节点
    int parent(int pos) const
    {
        return (pos - 1) / 2;
    }
    //建堆
    void buildHeap()
    {
        for (int i = n / 2 - 1; i >= 0; i--) siftdown(i);
    }
    //插入一个元素
    void insert(const E& it)
    {
        assert(n < maxsize, "Heap is full");
        int curr = n++;
        Heap[curr] = it;
        while ((curr != 0) && (prior(Heap[curr], Heap[parent(curr)])))
        {
            swap(Heap, curr, parent(curr));
            curr = parent(curr);
        }
    }
    //移除根节点
    E removefirst()
    {
        assert(n > 0, "Heap is empty");
        swap(Heap, 0, --n);
        if (n != 0)siftdown(0);
        return Heap[n];
    }
    //判断第一个参数是否再第二个参数之前
    bool prior(E a, E b)
    {

        if (a > b)   return true;
        else return false;
    }
    //交换值
    void swap(E* heap, int i, int j)
    {
        E temp;
        temp = heap[i];
        heap[i] = heap[j];
        heap[j] = temp;
    }
};
  • Huffman树的实现:
template<typename E> 
class HuffmanTree{
private:
    HuffmanNode<E>* Root;       //根结点
public:
    //构造叶结点
    HUffmanTree(E& val, int wg)
    {
        Root = new LeafNode<E>(val, wg);
    }
    //构造分支节点
    HuffmanTree(HuffmanTree<E>* l, HuffmanTree<E>* r)
    {
        Root = new IntlNode<E>(l->root(), r->Root());
    }
    ~HuffmanTree() {}
    //返回根结点
    HuffmanTree<E>* root() { return Root; }
    //返回权值
    int weight() { return Root->weight(); }
};
  • 建立Huffman树:
template<typename E>
HuffmanTree<E>* buildHuffman(HuffmanTree<E>** TreeArray, int count)
{
    heap<HuffmanTree<E>*>* forest = new heap<HuffmanTree<E>*>(TreeArray, count, count);  //建造一个最小堆
    HuffmanTree<char> *temp1, *temp2, *temp3 = NULL;                                     //三个Huffman树
    while (forest->size() > 1)
    {
        temp1 = forest->removefirst();    //将前两个树组合起来
        temp2 = forest->removefirst();
        temp3 = new HuffmanTree<E>(temp1, temp2);  
        forest->insert(temp3);         //把新树放在堆的最后
        delete temp1;                  //必须删除已用的树
        delete temp2;
    }
    return temp3;
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值