赫夫曼编码

名词我就不解释了。


注意构造赫夫曼树的过程并不唯一,因为左右孩子次序并无规定,节点权值相等时先后次序也不尽相同。

不过最后得到的一定都是符合要求的编码就是了。


所以我这里按《数据结构》例6.2输入源数据,得到的结果略微有些差异,不过确实是正确的。


实现时,用了较多vector,反倒把代码搞得不太简洁了,不管了,代码如下:


/*
2014.6.11
对一组给定的权值进行赫夫曼编码

考虑到此演示程序输出结果即结束,不再在为防内存泄露编写析构函数上浪费时间
*/
#include <iostream>
#include <vector>
#include <string>

using std::cin;
using std::cout;
using std::endl;
using std::vector;
using std::string;

struct HuffmanTreeNode
{
    float data;
    HuffmanTreeNode *lchild;
    HuffmanTreeNode *rchild;
    HuffmanTreeNode *parent;
};

struct Result
{
    HuffmanTreeNode *leaf;
    string code;
};

class Chuffcode
{
private:
    string RootAndEncode(HuffmanTreeNode *leaf);

public:
    Chuffcode(vector<float> src);
};

string Chuffcode::RootAndEncode(HuffmanTreeNode *leaf)
{
    string result;

    while (leaf->parent != NULL)
    {
        if (leaf->parent->lchild == leaf)   //左为0,右为1
        {
            result.insert(0, "0");
        }
        else
        {
            result.insert(0, "1");
        }

        leaf = leaf->parent;
    }
    
    return result;
}

Chuffcode::Chuffcode(vector<float> src)
{
    //为每个权值元素建立二叉树,记下叶子地址集(方便将来取结果),并放进森林(循环处理森林)
    vector<Result> results;
    vector<HuffmanTreeNode *> trees;

    vector<float>::iterator iter;
    for(iter = src.begin(); iter != src.end(); ++iter)
    {
        HuffmanTreeNode *pNode = new HuffmanTreeNode;
        pNode->data = *iter;
        pNode->lchild = NULL;
        pNode->rchild = NULL;
        pNode->parent = NULL;

        Result leafinfo;
        leafinfo.leaf = pNode;
        leafinfo.code = "";
        results.push_back(leafinfo);

        trees.push_back(pNode);
    }

    //重复下个步骤直至只剩一棵树
    //遍历森林中树的根节点,剔出权值最低的两棵构成新树的叶子,新树放回森林

    while (trees.size() != 1)
    {
        //找出最小节点
        vector<HuffmanTreeNode *>::iterator iter2;
        
        HuffmanTreeNode *minNode1 = trees[0];
        float min = trees[0]->data;
        vector<HuffmanTreeNode *>::iterator minIter = trees.begin();

        for(iter2 = trees.begin() + 1; iter2 != trees.end(); ++iter2)
        {
            if ((*iter2)->data < min)
            {
                minNode1 = *iter2;
                min = (*iter2)->data;
                minIter = iter2;
            }
        }

        //删除最小节点
        trees.erase(minIter);
        
        //找出次小节点并删除
        HuffmanTreeNode *minNode2 = trees[0];
        min = trees[0]->data;
        minIter = trees.begin();

        for(iter2 = trees.begin() + 1; iter2 != trees.end(); ++iter2)
        {
            if ((*iter2)->data < min)
            {
                minNode2 = *iter2;
                min = (*iter2)->data;
                minIter = iter2;
            }
        }

        trees.erase(minIter);

        //组合两节点成一棵树
        HuffmanTreeNode *newNode = new HuffmanTreeNode;
        newNode->data = minNode1->data + minNode2->data;
        newNode->lchild = minNode1;
        newNode->rchild = minNode2;
        newNode->parent = NULL;

        minNode1->parent = newNode;
        minNode2->parent = newNode;
        
        //加回森林
        trees.push_back(newNode);
    }      

    //从每片叶子寻回根,根据路径确定编码
    vector<Result>::iterator leafiter;
    for(leafiter = results.begin(); leafiter != results.end(); ++leafiter)
    {
        (*leafiter).code = RootAndEncode((*leafiter).leaf);
    }
    
    //打印结果
    for(leafiter = results.begin(); leafiter != results.end(); ++leafiter)
    {
        cout<<(*leafiter).code<<endl;
    }
}

int main()
{
    vector<float> src;
    float value;

    while (cin >> value)    //按ctrl+z输入结束符表示输入终止
    {
        src.push_back(value);
    }

    Chuffcode encoder(src);
}

/*
运行结果:
0.05 0.29 0.07 0.08 0.14 0.23 0.03 0.11^Z
0001
10
1110
1111
110
01
0000
001
*/


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值