HuffmanTree(C++类实现)

.h文件


#ifndef HUFFMANTREE_H
#define HUFFMANTREE_H

class HuffmanTree{
private:
    typedef struct HTNode
    {
        int data;
        int weight;
        int lson, rson, father;
    }HTNode;
    HTNode * Huffman_tree;
    int n, m; // n: charTotal, m: nodeTotal
    char ** huffman_code; // 声明一个指向每个叶子Huffman编码字符数组的指针数组
    

public:
    /**
     *  构造函数
        @name HuffmanTree(const char* str)
        @param arg1 需要进行哈夫曼编码的字符串
        @return
        注意: 要求树的左孩子为权制较小的编码,左孩子的二进制编号为0
    */
    HuffmanTree(const char* str);

    /**
     *  析构函数
        @name ~HuffmanTree()
        @param 
        @return
    */
    ~HuffmanTree();

    /**
     *  获得哈夫曼树关于字符C的编码
        @name int getcode(char)
        @param  arg1 需要获取编码的字符
        @return 哈夫曼树下C的编码
    */
    char* getcode(char c);


    /**
     *  获得哈夫曼树的WPL
        @name int getWPL()
        @param 
        @return 哈夫曼树的WPL
    */
    int getWPL();
    void select(int n, int& a, int& b);
    void createHuffmanCode();
};

#endif

.cpp文件(实现)


#include "Huffman.h"
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

HuffmanTree::HuffmanTree(const char* str){
    n = m = 0;
    const int N = 128;
    int g[N] = {};
    for (int i = 0; str[i]; i ++)
    {
        if(!g[str[i] - 1]) n ++;
        g[str[i] - 1] ++;
    }
    m = (n << 1) - 1;
    Huffman_tree = new HTNode[m + 1];
    for (int i = 0, j = 1; i < N; i ++)
    {
        if(g[i]){
            Huffman_tree[j ++] = {i + 1, g[i]};
        }
    }
    for (int i = n + 1; i <= m; i ++)
    {
        int a, b;
        select(i - 1, a, b);
        Huffman_tree[i].lson = a, Huffman_tree[i].rson = b;
        Huffman_tree[i].weight = Huffman_tree[a].weight + Huffman_tree[b].weight;
        Huffman_tree[i].father = 0;
        Huffman_tree[a].father = Huffman_tree[b].father = i;
    }
    createHuffmanCode();
}

HuffmanTree::~HuffmanTree(){
    delete [] Huffman_tree;
    delete [] huffman_code;
}

void HuffmanTree::select(int n, int& a, int& b){
    int mina = INT_MAX;
    int minb = INT_MAX;
    for (int i = 1; i <= n; i ++)
    {
        if(Huffman_tree[i].father) continue;
        int w = Huffman_tree[i].weight;
        if(w < mina){
            minb = mina;
            b = a;
            mina = w;
            a = i;
        }
        else if(w < minb){
            minb = w;
            b = i;
        }
    }
}

void HuffmanTree::createHuffmanCode()
{
    huffman_code = new char* [n + 1];
    char* cd = new char[n];
    cd[n - 1] = '\0';
    for (int i = 1; i <= n; i ++)
    {
        int st = n - 1;
        int ii = i;
        while(ii != m)
        {
            int f = Huffman_tree[ii].father;
            if(Huffman_tree[f].lson == ii) cd[-- st] = '0';
            else cd[-- st] = '1';
            ii = f;
        }
        huffman_code[i] = new char[n - st + 1];
        strcpy(huffman_code[i], &cd[st]);
    }
    delete [] cd;
}

char* HuffmanTree::getcode(char c){
    int cc = c;
    int i = 1;
    for (; i <= n; i ++) if(cc == Huffman_tree[i].data) break;
    return huffman_code[i];
}

int HuffmanTree::getWPL(){
    int res = 0;
    for (int i = 1; i <= n; i ++)
    {
        int k = i;
        int cnt = 0;
        while(k != m)
        {
            cnt ++;
            k = Huffman_tree[k].father;
        }
        res += cnt * Huffman_tree[i].weight;
    }
    return res;
}

.main测试文件

#include <iostream>
#include <cstdio>
#include <cstring>

#include "Huffman.h"
using namespace std;

int main()
{
    HuffmanTree hf("aaaaaaaabbbbccd");
    
    if(strcmp(hf.getcode('a'), "1") == 0) cout << "pass check point 1!" << endl;
    if(strcmp(hf.getcode('b'), "01") == 0) cout << "pass check point 2!" << endl;
    if(strcmp(hf.getcode('c'), "001") == 0) cout << "pass check point 3!" << endl;
    if(strcmp(hf.getcode('d'), "000") == 0) cout << "pass check point 4!" << endl;
    
    if(hf.getWPL() == 25) cout << "pass check point 5!" << endl;

    HuffmanTree tr("abcdabcabbddefffffgggggggggggggggggggg");
    printf("a : %s\n", tr.getcode('a'));
    printf("b : %s\n", tr.getcode('b'));
    printf("c : %s\n", tr.getcode('c'));
    printf("d : %s\n", tr.getcode('d'));
    printf("e : %s\n", tr.getcode('e'));
    printf("f : %s\n", tr.getcode('f'));
    printf("g : %s\n", tr.getcode('g'));
    cout << tr.getWPL() << endl;

    return 0;
}

测试效果:
测试效果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Victayria

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值