Huffman編碼和解碼
阿新 • • 發佈:2018-12-09
- 標頭檔案
#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;
}
- 執行結果