算法练习七--哈夫曼编码C++实现

算法练习七–哈夫曼编码C++实现

  • 好久没写博客了,今天在九度上遇到了个哈夫曼编码的oj题目,实现了下,发现自己大一时视之如恶魔的哈夫曼树的构造如今也能轻易实现了,哇哈哈,特此记一笔

一、哈夫曼树介绍

在一般的数据结构的书中,树的那章后面,著者一般都会介绍一下哈夫曼(HUFFMAN)树和哈夫曼编码。哈夫曼编码是哈夫曼树的一个应用。哈夫曼编码应用广泛,如JPEG中就应用了哈夫曼编码。 首先介绍什么是哈夫曼树。哈夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的 路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点的层数)。树的带权路径长度记为WPL(W1*L1+W2*L2+W3*L3+…+Wn*Ln),N个权值Wi(i=1,2,…n)构成一棵有N个叶结点的二叉树,相应的叶结点的路径长度为Li(i=1,2,…n)。可以证明哈夫曼树的WPL是最小的。

二、算法步骤

一、对给定的n个权值{W1,W2,W3,…,Wi,…,Wn}构成n棵二叉树的初始集合F= {T1,T2,T3,…,Ti,…,Tn},其中每棵二叉树Ti中只有一个权值为Wi的根结点,它的左右子树均为空。
二、在F中选取两棵根结点权值最小的树作为新构造的二叉树的左右子树,新二叉树的根结点的权值为其左右子树的根结点的权值之和。
三、从F中删除这两棵树,并把这棵新的二叉树同样以降序排列(因为在末尾进行删除和增加更加方便)加入到集合F中。
四、重复二和三两步,直到集合F中只有一棵二叉树为止。

PS:网上有很多对哈夫曼树手动构造生动形象的图文描述,这里不再赘述,重点说明算法的实现

三、talk is cheap show the code

#include
#include 
#include 
using namespace std;
/**********************************************************
// Method: 
// Description: http://ac.jobdu.com/problem.php?pid=1172
// Author:  
// Date: 2016/03/18 19:47
// Returns: 
// Parameter: 
// History:
// G:\VisualStudio2013Projects\algorithmNew\algorithmNew\哈夫曼编码.h
**********************************************************/

class huffumanNode
{
public:
    int weight;
    huffumanNode *left;
    huffumanNode *right;
    //用来构造叶子节点
    huffumanNode(int setWeight)
    {

        this->weight = setWeight;
        this->left = NULL;
        this->right = NULL;
    }
    //用来构造中间的节点
    huffumanNode(int setWeight, huffumanNode *setLeft, huffumanNode *setRight)
    {
        this->weight = setWeight;
        this->left = setLeft;
        this->right = setRight;
    }
    //判断是否是叶子节点
    bool isLeaf()
    {
        return this->left == NULL && this->right == NULL;
    }

};

//降序排序比较函数,以wieght的大小降序排列
bool myHuffumanComepare(huffumanNode *node1, huffumanNode *node2)
{
    return node1->weight > node2->weight;
}

/*得到带权路径长度。所谓树的带权路径长度,就是树中所有的叶结点

的权值乘上其到根结点的 路径长度(若根结点为0层,叶结点到根结点的路径长度

为叶结点的层数)*/
void getHuffmanSum(huffumanNode *root,int length,int &sum)
{
    if (!root)
    {
        return;
    }
    if (root->isLeaf())
    {
        sum += root->weight*length;
    }
    length++;
    getHuffmanSum(root->left, length, sum);
    getHuffmanSum(root->right, length, sum);
}
//前序遍历打印,提交时不要调用这个哈,仅为调试
void prePrint(huffumanNode *root)
{
    if (!root)
    {
        return;
    }
    cout << root->weight << " ";
    prePrint(root->left);
    prePrint(root->right);
}

int buildHuffuman()
{
    int n;
    while (cin >> n)
    {
        vector weightArray;
        while (n--)
        {
            int tempWeight;
            cin >> tempWeight;
            huffumanNode *newNode = new huffumanNode(tempWeight);
            weightArray.push_back(newNode);
        }
        sort(weightArray.begin(), weightArray.end(), myHuffumanComepare);
        while ((int)weightArray.size() > 1)
        {
            huffumanNode *minNode1 = weightArray[weightArray.size() - 1];
            huffumanNode *minNode2 = weightArray[weightArray.size() - 2];
            int fatherWeight = minNode1->weight + minNode2->weight;
            /*根据最小的两个权重节点,构造新节点*/
            huffumanNode *fatherNode = new huffumanNode(fatherWeight, minNode1, minNode2);

            weightArray.pop_back();
            weightArray.pop_back();
            weightArray.push_back(fatherNode);

            sort(weightArray.begin(), weightArray.end(), myHuffumanComepare);
        }
        prePrint(weightArray[0]);
        cout << endl;
        int length = 0;
        int sum = 0;
        getHuffmanSum(weightArray[0], length, sum);
        cout << "weightSum: " << sum << endl;
    }
    return 0;
}

运行:
算法练习七--哈夫曼编码C++实现_第1张图片

你可能感兴趣的:(算法练习)