Huffman编码和解码

  • 头文件
#ifndef TEST_H_INCLUDED
#define TEST_H_INCLUDED

typedef short int Bool;

class HuffmanTreeNode{
private:
    float m_weight;
    short int m_parent, m_lchild, m_rchild;
public:
    void SetWeight();
    const float & GetWeight();
    const short int & GetLchild();
    const short int & GetRchild();
    const short int & GetParent();
    void ResetMember(int, int, int);
    void ResetWeight(float);
    void ResetParent(short int);
    void ResetLchild(short int);
    void ResetRchild(short int);
    Bool IsRootNode();
};

class HuffmanCode{
private:
    int m_huffman_node_num; //当前m_huffman_tree_ptr中所以树的结点总个数
    char ** m_char_code;
    HuffmanTreeNode * m_huffman_tree_ptr;
protected:
    void SetCharNum();
    void GetTwoMinWeight(int &, int &);
public:
    HuffmanCode();
    ~HuffmanCode();
    Bool CreatHuffmanTree();
    //int FindRootNode();
    void HuffmanCoding();
    void ShowCharCode();
    void StrHuffmanCoding();
    void StrHuffmanDecoding();
};

#endif // TEST_H_INCLUDED
  • C++实现文件
#include "test.h"
#include 
#include 
#include 
#include 
//设置权重值
void HuffmanTreeNode::SetWeight(){
    std::cin >> m_weight;
}//SetWeight
//获取权重值
const float & HuffmanTreeNode::GetWeight(){
    return m_weight;
}
//获取双亲指针
const short int & HuffmanTreeNode::GetParent(){
    return m_parent;
}
const short int & HuffmanTreeNode::GetLchild(){
    return m_lchild;
}
const short int & HuffmanTreeNode::GetRchild(){
    return m_rchild;
}
//重置成员
void HuffmanTreeNode::ResetMember(int parent, int lchild, int rchild){
    m_parent = parent;
    m_lchild = lchild;
    m_rchild = rchild;
}
//重置权重
void HuffmanTreeNode::ResetWeight(float weight){
    m_weight = weight;
}
//重置双亲
void HuffmanTreeNode::ResetParent(short int parent){
    m_parent = parent;
}
//重置左儿子
void HuffmanTreeNode::ResetLchild(short int lchild){
    m_lchild = lchild;
}
//重置右儿子
void HuffmanTreeNode::ResetRchild(short int rchild){
    m_rchild = rchild;
}
//判断是否为根结点
Bool HuffmanTreeNode::IsRootNode(){
    if(m_parent == -1) return 1;
    else return 0;
}
//设置字符数目
void HuffmanCode::SetCharNum(){
    std::cout << "请输入字符数目:";
    std::cin >> m_huffman_node_num;
}
//获取n个字符和权值
HuffmanCode::HuffmanCode(){
    SetCharNum();
    m_char_code = new char *[m_huffman_node_num];
    m_huffman_tree_ptr = new HuffmanTreeNode[2*m_huffman_node_num-1];
    std::cout << "请输入字符和权值:";
    for(int i = 0; i < m_huffman_node_num; ++i){
        *(m_char_code + i) = new char[2];
        m_char_code[i][1] = '\0';
        std::cin >> m_char_code[i][0];
        m_huffman_tree_ptr[i].SetWeight();
        m_huffman_tree_ptr[i].ResetMember(-1, -1, -1);
    }
}//SetCharAndWeight
//获取两个最小的权重
void HuffmanCode::GetTwoMinWeight(int & first_min_weight_pos, int & second_min_weight_pos){
    int j = 0;
    for(int i = 0; i < m_huffman_node_num; ++i)
        if(m_huffman_tree_ptr[i].IsRootNode()){
            if(j == 0) first_min_weight_pos = i;
            if(j == 1) second_min_weight_pos = i;
            ++j;
        }
    if(j == 2) return;
    else{
        float first_min_weight = FLT_MAX; //将最小权重初始值设为float型的最大值
        float second_min_weight = first_min_weight;
        first_min_weight_pos = 0;
        second_min_weight_pos = 0;
        float weight;
        for(int i = 0; i < m_huffman_node_num; ++i){
            if(!m_huffman_tree_ptr[i].IsRootNode()) continue;
            weight = m_huffman_tree_ptr[i].GetWeight();
            if(weight < first_min_weight){
                second_min_weight = first_min_weight;
                second_min_weight_pos = first_min_weight_pos;
                first_min_weight = weight;
                first_min_weight_pos = i;
            }
            else if(weight < second_min_weight){
                second_min_weight = weight;
                second_min_weight_pos = i;
            }
        }
    }
}//GetTwoMinWeight
//建立Huffman树
Bool HuffmanCode::CreatHuffmanTree(){
    int first_min_weight_pos, second_min_weight_pos;
    int n = 2 * m_huffman_node_num - 1;
    while(m_huffman_node_num != n){
        GetTwoMinWeight(first_min_weight_pos, second_min_weight_pos);
        float added_weight = m_huffman_tree_ptr[first_min_weight_pos].GetWeight()
                             + m_huffman_tree_ptr[second_min_weight_pos].GetWeight();
        m_huffman_tree_ptr[m_huffman_node_num].ResetMember(-1, first_min_weight_pos, second_min_weight_pos);
        m_huffman_tree_ptr[m_huffman_node_num].ResetWeight(added_weight);
        m_huffman_tree_ptr[first_min_weight_pos].ResetParent(m_huffman_node_num);
        m_huffman_tree_ptr[second_min_weight_pos].ResetParent(m_huffman_node_num);
        ++m_huffman_node_num;
    }
    return 1;
}//CreatHuffmanTree
/*
//寻找根节点所在位置
int HuffmanCode::FindRootNode(){
    for(int i = 0; i < m_huffman_node_num; ++i)
        if(m_huffman_tree_ptr[i].IsRootNode())
            return i;
    return 0;
}*/
//Huffman编码
void HuffmanCode::HuffmanCoding(){
    int N = m_huffman_node_num / 2 + 1;
    for(int i = 0; i < N; ++i){
        int len = 2;
        short int next_node = m_huffman_tree_ptr[i].GetParent();
        short int now_node = i;
        while(next_node >= 0){
            ++len;
            char * ch_ptr = new char[len];
            strcpy(ch_ptr, *(m_char_code + i));
            delete [] *(m_char_code + i);
            *(m_char_code + i) = ch_ptr;
            for(int j = len - 1; j > 1; --j)
                m_char_code[i][j] = m_char_code[i][j-1];
            if(m_huffman_tree_ptr[next_node].GetLchild() == now_node)
                m_char_code[i][1] = '0';
            else if(m_huffman_tree_ptr[next_node].GetRchild() == now_node)
                m_char_code[i][1] = '1';
            now_node = m_huffman_tree_ptr[now_node].GetParent();
            next_node = m_huffman_tree_ptr[next_node].GetParent();
        }
    }
}
//显示字符编码
void HuffmanCode::ShowCharCode(){
    int N = m_huffman_node_num / 2 + 1;
    for(int i = 0; i < N; ++i){
        std::cout << **(m_char_code + i) << ':';
        int j = 1;
        while(*(*(m_char_code + i) + j) != '\0'){
            std::cout << *(*(m_char_code + i) + j);
            ++j;
        }
        std::cout << std::endl;
    }
}
//字符串编码
void HuffmanCode::StrHuffmanCoding(){
    char ch[52] = {0};
    int num = 0;
    std::cout << "请输入字符串:";
    ch[num] = getchar();
    ch[num] = getchar();
    while(ch[num++] != '\n')
        ch[num] = getchar();
    ch[num] = '\0';//num为输入的字符个数(除空字符和换行符外)
    std::cout << "相应的编码为:";
    int N = m_huffman_node_num / 2 + 1;
    for(int i = 0; i < num; ++i){
        for(int j = 0; j < N; ++j){
            if(ch[i] == m_char_code[j][0])
                std::cout << m_char_code[j] + 1;
        }
    }
    std::cout << std::endl;
}
//字符解码
void HuffmanCode::StrHuffmanDecoding(){
    char * ch_ptr = new char[2];
    ch_ptr[1] = '\0';
    std::cout << "请输入编码:";
    int num = 0;
    //ch_ptr[num] = getchar();
    ch_ptr[num] = getchar();
    while(ch_ptr[num] != '\n'){
        ++num;
        char * new_ch_ptr = new char[num + 2];
        strcpy(new_ch_ptr, ch_ptr);
        delete [] ch_ptr;
        ch_ptr = new_ch_ptr;
        ch_ptr[num + 1] = ch_ptr[num];
        ch_ptr[num] = getchar();
    }
    ch_ptr[num] = '\0';
    char * new_ch_ptr = new char[num + 1];
    strcpy(new_ch_ptr, ch_ptr);
    delete [] ch_ptr;
    ch_ptr = new_ch_ptr;
    std::cout << "与编码匹配的字符串:";
    int j2 = 0;
    int j2_p;
    int N = m_huffman_node_num / 2 + 1;
    while(ch_ptr[j2] != '\0'){
        for(int i = 0; i < N; ++i){
            int j1 = 0;
            j2_p = j2;
            while(m_char_code[i][j1+1] == ch_ptr[j2]){
                ++j1; ++j2;
                if(m_char_code[i][j1+1] == '\0'){
                    std::cout << m_char_code[i][0];
                    break;
                }
                if(m_char_code[i][j1+1] != ch_ptr[j2]){
                    j2 = j2_p; break;
                }
            }
            if(ch_ptr[j2] == '\0') return;
        }
    }
}
//释放Huffman树
HuffmanCode::~HuffmanCode(){
    //注意此时的m_huffman_node_num和之前不同
    for(int i = 0; i < m_huffman_node_num/2+1; ++i){
        delete [] *(m_char_code + 2);
    }
    delete [] m_char_code;
    delete [] m_huffman_tree_ptr;
}
  • 主程序文件
#include 
#include "test.h"

int main()
{
    std::cout << "/*************字符输入************/" << std::endl;
    HuffmanCode huffman;
    std::cout << std::endl;
    if(huffman.CreatHuffmanTree()){
        huffman.HuffmanCoding(); //Huffman编码
        std::cout << "/******显示字符的Huffman编码******/" << std::endl;
        huffman.ShowCharCode();
        std::cout << std::endl;
    }
    std::cout << "/*****显示字符串的Huffman编码*****/" << std::endl;
    huffman.StrHuffmanCoding();
    std::cout << std::endl;
    std::cout << "/********Huffman字符串译码********/" << std::endl;
    huffman.StrHuffmanDecoding();
    std::cout << std::endl;
    return 0;
}
  • 执行结果
    Huffman编码和解码_第1张图片

你可能感兴趣的:(C++)