哈弗曼树

在介绍哈弗曼树之前先来看几个简单的概念:
在一个二叉树中:
定义一个从A结点到B结点所经过的分支序列为从A结点到B结点的路径。
定义从A结点到B结点所经过的分支个数为从A结点到B结点的路径长度。
从二叉树的根节点到二叉树中所有节点的路径长度之和为该二叉树的路径长度。
这里写图片描述
Huffman树:带权路径长度最短的树称为哈夫曼树。
Huffman树的创建:(用小堆来保存二叉树森林中的树)如int array[]={5,3,2,7}。
1.先进行排序:升序排列为{2,3,5,7}。
2.选出最小的两个数,先进行建树。这里写图片描述
3.将新的二叉树放入二叉树森林中。
这里写图片描述
4.继续步骤2和3。
这里写图片描述

下面为构建Huffman树的算法:
1.创建以权值为根的二叉树森林——>小堆
2.构建(直到二叉树森林中只剩一棵树)
1>.取权值最小的树pLeft,—–删除其。
2>.取权值最小的树pRight,—–删除其。
3>.pLeft的权值与pRight的权值作为其双亲,创建新树,将新树佳人苑二叉树森林中。

3.比较左右子树权值的大小,决定放在左子树还是右子树。

具体的代码实现如下:

#include<iostream>
#include<vector>
using namespace std;
template<class T>
class Heap
{
public:
    Heap()
    {}
    Heap(const T*array, size_t size)//堆的创建
    {
        //1.将数组中的元素存起来
        _array.resize(size);
        for (size_t i = 0; i < size; i++)
        {
            _array[i] = array[i];
        }
        //2.向下调整
        int root = (size - 2) >> 1;
        for (; root >= 0; root--)
        {
            _AdjustDown(root);
        }
    }
    void Push(const T& data)
    {
        _array.push_back(data);
        if (_array.size() > 1)
        {
            _AdjustUp(_array.size() - 1);
        }
    }
    void Pop()
    {
        if (Size() == 0)
            return;
        else
        {
            size_t last = _array.size() - 1;
            swap(_array[0], _array[last]);
            _array.pop_back();
            //2.向下调整
            _AdjustDown(0);
        }
    }
    T Top()const
    {
        return _array[0];
    }
    bool Empty()const
    {
        return _array.empty();
    }
    size_t Size()const
    {
        return  _array.size();
    }
private:
    void _AdjustDown(size_t parent)//向下调整
    {
        size_t child = parent * 2 + 1;
        size_t size = _array.size();
        while (child < size)
        {
            if ((child + 1 < size) && (_array[child] > _array[child + 1]))
            {
                child += 1;
            }
            if (_array[parent]>_array[child])
            {
                swap(_array[parent], _array[child]);
                parent = child;
                child = parent * 2 + 1;//继续走到其左侧,进行调整
            }
            else
            {
                break;
            }
        }
    }
    void _AdjustUp(size_t child)//向上调整
    {
        size_t size = _array.size();
        size_t parent = (size - 2) >> 1;
        while (child > 0)
        {
            if (_array[parent] > _array[child])
            {
                swap(_array[parent], _array[child]);
                child = parent;
                parent = (child - 1) >> 1;
            }
            else
            {
                break;
            }
        }
    }
private:
    vector<T>_array;
};
template<class W>
struct HuffmanTreeNode
{
    HuffmanTreeNode()
    : _pLeft(NULL)
    , _pRight(NULL)
    , _weight(0)
    {}
    HuffmanTreeNode(W weight)
    :_pLeft(NULL)
    , _pRight(NULL)
    , _weight(weight)
    {}
    HuffmanTreeNode<W>*_pLeft;
    HuffmanTreeNode<W>*_pRight;
    W _weight;//权值
};
template<class W>
class HuffmanTree
{
public:
    typedef HuffmanTreeNode<W> Node;
    typedef Node* pNode;
    HuffmanTree()
        :_pRoot(NULL)
    {}
    HuffmanTree( W*array, size_t size, const W&invalid)
    {
        _CreatHuffmanTree(array, size, invalid);
    }
    ~HuffmanTree()
    {
        _Destroy(_pRoot);
    }
private:
    void _CreatHuffmanTree(W*array, size_t size, const W&invalid)
    {
        if (hp.Empty())
        {
            _pRoot = NULL;
        }
        Heap<pNode>hp;//堆中存的是节点
        for (size_t i = 0; i<size; i++)
        {
            if (array[i] != invalid)
            {
                hp.Push(new Node(array[i]));
            }
        }
        while (hp.Size()> 1)
        {
            //取堆顶元素
            pNode pLeft = hp.Top();
            hp.Pop();
            pNode pRight = hp.Top();
            hp.Pop();
            pNode parent = new Node(pLeft->_weight + pRight->_weight);//左右权值相加
            if (pLeft->_weight < pRight->_weight)
            {
                parent->_pLeft = pLeft;
                parent->_pRight = pRight;
            }
            else
            {
                parent->_pLeft = pRight;
                parent->_pRight = pLeft;
            }
            hp.Push(parent);
        }
        _pRoot = hp.Top();
    }
    void _Destory(pNode &pRoot)
    {
        if (pRoot)
        {
            _Destory(pRoot->_pLeft);
            _Destory(pRoot->_pRight);
            delete pRoot;
        }
    }
    pNode _pRoot;
    Heap<W> hp;
};
int main()
{
    int array[] = { 5, 3, 2, 7 };
    HuffmanTree<int>h(array, 4, 0);
    system("pause");
    return 0;
}

仿函数的形式写法为:

#include<iostream>
#include<vector>
using namespace std;
template<class T>
struct Greater
{
    bool operator()(const T&a, const T&b)
    {
        return a > b;
    }
};
template<class T>
struct Smaller
{
    bool operator()(const T&a, const T&b)
    {
        return a < b;
    }
};
template<class T, class compare = Smaller<T>>
class Heap
{
public:
    Heap()
    {}
    Heap(T*array, int size)//堆的创建
    {
        //1.将数组中的元素存起来
        _array.resize(size);
        for (int i = 0; i < size; i++)
        {
            _array[i] = array[i];
        }
        //2.向下调整
        int root = (size - 2) >> 1;
        for (; root >= 0; root--)
        {
            _AdjustDown(root);
        }
    }
    void Push(const T& data)
    {
        _array.push_back(data);
        if (_array.size() > 1)
        {
            _AdjustUp(_array.size() - 1);
        }
    }
    void Pop()
    {
        if (Size() == 0)
            return;
        else
        {
            int last = _array.size() - 1;
            swap(_array[0], _array[last]);
            _array.pop_back();
            //2.向下调整
            _AdjustDown(0);
        }
    }
    T Top()const
    {
        return _array[0];
    }
    bool Empty()const
    {
        return _array.empty();
    }
    size_t Size()const
    {
        return  _array.size();
    }
private:
    void _AdjustDown(int parent)//向下调整
    {
        int child = parent * 2 + 1;
        int size = _array.size();
        while (child < size)
        {
            if ((child + 1 < size) && (compare()(_array[child], _array[child + 1])))
            {
                child += 1;
            }
            if (compare()(_array[parent], _array[child]))
            {
                swap(_array[parent], _array[child]);
                parent = child;
                child = parent * 2 + 1;//继续走到其左侧,进行调整
            }
            else
                return;
        }
    }
    void _AdjustUp(int child)//向上调整
    {
        int size = _array.size();
        int parent = (size - 2) >> 1;
        while (child > 0)
        {
            if (compare()(_array[parent], _array[child]))
            {
                swap(_array[parent], _array[child]);
                child = parent;
                parent = (child - 1) >> 1;
            }
            else
            {
                break;
            }
        }
    }
private:
    vector<T>_array;
};
template<class W>
struct HuffmanTreeNode
{
    HuffmanTreeNode()
    : _pLeft(NULL)
    , _pRight(NULL)
    , _weight(0)
    {}
    HuffmanTreeNode(W weight)
    :_pLeft(NULL)
    , _pRight(NULL)
    , _weight(weight)
    {}
    HuffmanTreeNode<W>*_pLeft;
    HuffmanTreeNode<W>*_pRight;
    W _weight;//权值
};
template<class W>
class HuffmanTree
{
public:
    typedef HuffmanTreeNode<W> Node;
    typedef Node* pNode;
    HuffmanTree()
        :_pRoot(NULL)
    {}
    HuffmanTree( W*array, size_t size, const W&invalid)
    {
        _CreatHuffmanTree(array, size, invalid);
    }
    ~HuffmanTree()
    {
        _Destroy(_pRoot);
    }
private:
    void _CreatHuffmanTree(W*array, size_t size, const W&invalid)
    {
        struct compare
        {                                          
            bool operator()(pNode pLeft, pNode Pright)
            {
                return pLeft->_weight < Pright->_weight;
            }
        };
        Heap<pNode, compare>hp;//堆中存的是节点
        for (size_t i = 0; i<size; i++)
        {
            if (array[i] != invalid)
            {
                hp.Push(new Node(array[i]));
            }
        }
        if (hp.Empty())
        {
            _pRoot = NULL;
        }
        while (hp.Size()> 1)
        {
            //取堆顶元素
            pNode pLeft = hp.Top();
            hp.Pop();
            pNode pRight = hp.Top();
            hp.Pop();
            pNode parent = new Node(pLeft->_weight + pRight->_weight);//左右权值相加
            hp.Push(parent);
        }
        _pRoot = hp.Top();
    }
    void _Destory(pNode &pRoot)
    {
        if (pRoot)
        {
            _Destory(pRoot->_pLeft);
            _Destory(pRoot->_pRight);
            delete pRoot;
        }
    }
    pNode _pRoot;
    Heap<W> hp;
};
int main()
{
    int array[] = { 5, 3, 2, 7 };
    HuffmanTree<int>h(array, 4, 0);
    system("pause");
    return 0;
}

struct compare
{
bool operator()(pNode pLeft, pNode Pright)
{
return pLeft->_weight < Pright->_weight;
}
};
关于此结构的说明:
我们需要将节点保存在堆中,但是在结构体中是节点的地址,则需要比较其权值,之后进行调整。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值