哈夫曼樹以及編碼

今天寫了寫哈夫曼樹..

首先是頭文件heads.h

#pragma once
#include<iostream>
#include<vector>
#include<string>
#include<deque>
#include<stack>
#include<unordered_map>
#include<algorithm>

using namespace std;

然後還是頭文件

#pragma once
#include"heads.h"

namespace haffuman
{
    class haffumant
    {
    public:
        struct tnode
        {
            char data;
            int weight;
            tnode *parent;
            tnode *lchild;
            tnode *rchild;
        };
    public:
        /*這裏寫了一個自己的排序的類,用來生成類對象*/
        class  mysort
        {
        public:
            bool operator ()(tnode * a, tnode *b)
            {
                return a->weight < b->weight;
            }
        };

        haffumant(int num, vector<tnode*> &datas) :sum(num), nodes(datas)
        {
            sort(nodes.begin(), nodes.end(), mysort());//按權值排序,當然可以用最小堆,這裏我不想用堆
        }
        haffumant() :sum(0)
        {
        }
        /*利用中序遍歷來完成編碼的工作,將編碼結果保存在了hashmap中*/
        void huffmancode()
        {

            stack<tnode *> tm_sta;
            tnode * psear = root;
            vector<int>  tm_code;
            tm_sta.push(root);

            while (!tm_sta.empty())
            {

                while (psear->lchild != NULL)
                {
                    tm_sta.push(psear->lchild);
                    psear = psear->lchild;
                    tm_code.push_back(0);
                }

                //psear = tm_sta.top();
                tm_sta.pop();

                code[psear->data] = tm_code;

                if (tm_sta.empty())
                {
                    break;
                }
                psear = tm_sta.top();
                tm_sta.pop();
                tm_code.pop_back();

                if (psear->rchild != nullptr)
                {
                    tm_sta.push(psear->rchild);
                    psear = psear->rchild;
                    tm_code.push_back(1);
                }
                else
                {
                    return;
                }
            }
        }
        void huffmancode1()
        {
            /*還有一種簡單的方法,由於保存了各個葉節點,那麼可以從下向上遍歷...通過parent指針.
             但是這種方法有種缺陷就是得到的編碼是顛倒的,當然可以通過遞歸來解決,或者棧..也可以通過
             其他手段,能解決逆置的問題就可以
            */
        }

        void settree()
        {
            while (nodes.size() > 1)
            {
                root = buynode(nodes[0]->weight + nodes[1]->weight, NULL, nodes[1], nodes[0]);
                nodes[0]->parent = root;
                nodes[1]->parent = root;

                nodes.erase(nodes.begin());
                nodes.erase(nodes.begin());
                nodes.push_back(root);
                sort(nodes.begin(), nodes.end(), mysort());
            }
        }
        void show()
        {
            show(root);
            for (auto it : code)
            {
                int i = 0;
                cout << it.first;
                while (i < it.second.size())
                {
                    cout << it.second[i++];
                }
                cout << "\n";
            }
        }

        ~haffumant()
        {
            clear(root);
        }
    private:
        void clear(tnode * node)
        {
            if (node != nullptr)
            {
                clear(node->lchild);
                clear(node->rchild);
                delete node;
            }
        }
        void show(tnode *root1)
        {
            if (root1 == NULL) return;
            cout << root1->data;
            show(root1->lchild);
            show(root1->rchild);
        }
        tnode * buynode(int weight, tnode *par, tnode*rchld, tnode *lchild)
        {
            return new tnode{ '@',weight,par,lchild,rchld };
        }
        vector<tnode*> nodes;
        tnode * root = NULL;
        unordered_map<char, vector<int>> code;
        int sum;
    };

};

最後就是主函數用來驗證下,寫的如何..

#include"haffumantree.h"

using namespace haffuman;

int main()
{
    vector<haffumant::tnode *> arr = 
    {                                                          
    new haffumant::tnode{'a',5,NULL,NULL,NULL},
    new haffumant::tnode{'c',2,NULL},
    new haffumant::tnode{'b',7,NULL},
    new haffumant::tnode{ 'd',13,NULL }
     };

    haffumant tree(arr.size(),arr);

    tree.settree();
    tree.huffmancode();
    tree.show();

}

哈夫曼樹,是最優二叉樹,也就是帶權路徑長度值最小的二叉樹,權值越大越靠近根,哈夫曼編碼也可以用於進行壓縮…

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章