目录
哈夫曼编码树类(构造哈夫曼编码树、字符串转编码、编码转字符串):
哈夫曼编码树类(构造哈夫曼编码树、字符串转编码、编码转字符串):
#pragma once
#include <iostream>
#include <string>
using namespace std;
class encoding_tree
{
private:
struct node
{
node* _left = nullptr;
node* _right = nullptr;
int _weight = 0;
char _character= '#';
string _code = "";
};
const int _max_node = 1000;
int _node_number;
node* _node_list = new node[_max_node];
//以下是不被看见的成员函数
//按照权值排序
template<typename T>
void sort(T* t_list, int* weight_list, int length)
{
for (int x = 0; x < length - 1; x++)
{
for (int y = 0; y < length - x - 1; y++)
{
if (weight_list[y] > weight_list[y + 1])
{
int temp_weight;
T temp_t;
temp_weight = weight_list[y];
temp_t = t_list[y];
weight_list[y] = weight_list[y + 1];
t_list[y] = t_list[y + 1];
weight_list[y + 1] = temp_weight;
t_list[y + 1] = temp_t;
}
}
}
}
//删除列表中的元素
template<typename T>
void erase(T* t_list, int& length, int position)
{
for (int x = position; x < length - 1; x++)
{
t_list[x] = t_list[x + 1];
}
length--;
}
//设置编码,这里采用的是递归的深度优先遍历
void set_code(node* temp_node, string code)
{
if (temp_node == nullptr)
{
return;
}
temp_node->_code = code;
set_code(temp_node->_left, code + "0");
set_code(temp_node->_right, code + "1");
}
//根据字符深度优先搜索
node* depth_first_search(node* temp_node, char temp_character)
{
node *temp_node_1, *temp_node_2;
if (temp_node == nullptr)
{
return nullptr;
}
if (temp_node->_character == temp_character)
{
return temp_node;
}
temp_node_1 = depth_first_search(temp_node->_left, temp_character);
if (temp_node_1 != nullptr && temp_node_1->_character == temp_character)
{
return temp_node_1;
}
temp_node_2 = depth_first_search(temp_node->_right, temp_character);
if (temp_node_2 != nullptr && temp_node_2->_character == temp_character)
{
return temp_node_2;
}
return nullptr;
}
//根据编码深度优先搜索,同时只要叶子结点
node* depth_first_search(node* temp_node, string temp_code)
{
node* temp_node_1, * temp_node_2;
if (temp_node == nullptr)
{
return nullptr;
}
if (temp_node->_left==nullptr && temp_node->_right == nullptr && temp_node->_code == temp_code)
{
return temp_node;
}
temp_node_1 = depth_first_search(temp_node->_left, temp_code);
if (temp_node_1 != nullptr && temp_node_1->_left == nullptr &&
temp_node_1->_right == nullptr && temp_node_1->_code == temp_code)
{
return temp_node_1;
}
temp_node_2 = depth_first_search(temp_node->_right, temp_code);
if (temp_node_2 != nullptr && temp_node_2->_left == nullptr &&
temp_node_2->_right == nullptr && temp_node_2->_code == temp_code)
{
return temp_node_2;
}
return nullptr;
}
public:
//构造函数,同时也是编码树构建
encoding_tree(string origin_string)
{
//初始化
_node_number = 0;
//长度
int length = (int)origin_string.length();
//权值数组
int* weight_list = new int[length];
//字符数组
char* character_list = new char[length];
//赋值
for (int x = 0; x < length; x++)
{
character_list[x] = origin_string[x];
}
//去除重复字符
for (int x = 0; x < length; x++)
{
weight_list[x] = 1;
for (int y = x + 1; y < length; y++)
{
if (character_list[y] == character_list[x])
{
weight_list[x]++;
erase(character_list, length, y);
y--;
}
}
}
//按照权值从小到大排序
sort(character_list, weight_list, length);
//结点数组赋值
node* node_list = new node[length];
for (int x = 0; x < length; x++)
{
node_list[x]._character = character_list[x];
node_list[x]._weight = weight_list[x];
}
//构造树
//如果只有一个结点
if(length == 1)
{
_node_list[_node_number] = node_list[0];
node_list[0]._left = &_node_list[_node_number];
node_list[0]._weight = weight_list[0];
node_list[0]._character = '#';
_node_number++;
}
while (length != 1)
{
_node_list[_node_number] = node_list[0];
_node_list[_node_number + 1] = node_list[1];
node_list[0]._left = &_node_list[_node_number];
node_list[0]._right = &_node_list[_node_number + 1];
node_list[0]._weight = weight_list[0] + weight_list[1];
node_list[0]._character = '#';
weight_list[0] += weight_list[1];
_node_number += 2;
erase(node_list, length, 1);
length++;
erase(weight_list, length, 1);
sort(node_list, weight_list, length);
}
_node_list[_node_number] = node_list[0];
_node_number++;
//设置编码
set_code(&_node_list[_node_number-1], "");
//回收内存
delete []weight_list;
delete []character_list;
delete []node_list;
}
//析构函数,清理内存
~encoding_tree()
{
delete []_node_list;
}
//根据字符串输出编码
string to_code(string character_list)
{
string code_list;
for (int x = 0; x < character_list.length(); x++)
{
node* temp_node = depth_first_search(&_node_list[_node_number - 1], character_list[x]);
code_list.append(temp_node->_code);
}
return code_list;
}
//根据编码还原字符串
string to_sentence(string code)
{
string temp_sentence;
while(!code.empty())
{
for (int x = 1; x <= code.length(); x++)
{
node* temp_node = depth_first_search(&_node_list[_node_number - 1], code.substr(0, x));
if (temp_node != nullptr)
{
temp_sentence.push_back(temp_node->_character);
code.erase(0, x);
break;
}
}
}
return temp_sentence;
}
//测试函数,展示整棵树
void test_show(node* temp_node, int x)
{
if (x == 0)
{
temp_node = &_node_list[_node_number - 1];
}
if (temp_node == nullptr)
{
return;
}
cout << temp_node->_character << " " <<
temp_node->_weight << " " << temp_node->_code << endl;
test_show(temp_node->_left,x+1);
test_show(temp_node->_right,x+1);
}
};
测试程序:
#include <iostream>
#include "encoding_tree.h"
using namespace std;
int main(void)
{
cout << "请在下面输入一段英文:" << endl;
string sentence;
getline(cin, sentence);
if(sentence.length() == 0)
{
cout << "输入句子为空,程序结束!" << endl;
return 0;
}
encoding_tree instance_encoding_tree(sentence);
//测试函数,展示树的全貌
//instance_encoding_tree.test_show(nullptr,0);
string code = instance_encoding_tree.to_code(sentence);
cout << "这段文字的编码为:" << endl;
cout << code << endl;
string restored_sentence = instance_encoding_tree.to_sentence(code);
cout << "编码再还原成文字为:" << endl;
cout << restored_sentence << endl;
return 0;
}