1. 程式人生 > >Huffman編碼和解碼

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 <iostream>
#include <cfloat>
#include <cstring>
#include <cstdio>
//設定權重值
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 <iostream>
#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;
}
  • 執行結果 這裡寫圖片描述