include
添加头文件
This commit is contained in:
parent
04551008b3
commit
73cb477411
110
huffman_code.h
Normal file
110
huffman_code.h
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
//
|
||||||
|
// Created by dongl on 22-11-13.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef CPP_DATA_STRUCT_HUFFMAN_CODE_H
|
||||||
|
#define CPP_DATA_STRUCT_HUFFMAN_CODE_H
|
||||||
|
#include <huffman_tree.h>
|
||||||
|
|
||||||
|
/// 解压缩 业务逻辑操作的类
|
||||||
|
class HTCode {
|
||||||
|
private:
|
||||||
|
char data_char{}; // 待编码的字符
|
||||||
|
std::byte code[10]{}; // 字符的解压缩编码
|
||||||
|
std::fstream file; // 文件流
|
||||||
|
//Huffman huffman; // 哈夫曼结构
|
||||||
|
Alphabet* alphabet; // 字符权重映射表
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
HTCode* Open(const std::string& file_path, Alphabet* alpha = new Alphabet[27]){ // 记录字符与字符出现次数
|
||||||
|
|
||||||
|
// 记录字符数组的 初始化
|
||||||
|
// 初始化字符 出现次数 映射表 只支持中文
|
||||||
|
for (int i = 1; i <= 26; ++i) {
|
||||||
|
alpha[i].count = 0;
|
||||||
|
alpha[i].data = i + 97 - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打开文件
|
||||||
|
file.open(file_path, std::ios::in);
|
||||||
|
if(!file.is_open()){
|
||||||
|
std::cerr << "open '" << file_path << "' fail" <<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
char c; // 字符
|
||||||
|
int c_count = 0;// 字母数量
|
||||||
|
int count = 0; // 压缩全文 多少个字符 总字符数
|
||||||
|
int ascii; // 字符的ascii
|
||||||
|
// 读取文件 统计字符个数
|
||||||
|
while (!file.eof()){
|
||||||
|
if(file.fail()) break;
|
||||||
|
|
||||||
|
file >> c;
|
||||||
|
count++;
|
||||||
|
ascii = (int) c;
|
||||||
|
|
||||||
|
// 小写 小写区间
|
||||||
|
if (ascii >= 65 && ascii <= 90){
|
||||||
|
// 65 - 65 + 1 下标 alpha[1]
|
||||||
|
alpha[ascii - 65 + 1].count++;
|
||||||
|
c_count++;
|
||||||
|
}
|
||||||
|
// 大写
|
||||||
|
if (ascii >= 97 && ascii <= 122){
|
||||||
|
alpha[ascii - 97 + 1].count++;
|
||||||
|
c_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << c;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << std::endl;
|
||||||
|
std::cout << "总字符数" << count << "\n";
|
||||||
|
std::cout << "字母字符数" << c_count << "\n";
|
||||||
|
std::cout << "其他字符数" << count - c_count << std::endl;
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
for (int i = 1; i <= 26; ++i) {
|
||||||
|
printf("[%d] : %c - %d \n", i, (char)alpha[i].data, alpha[i].count);
|
||||||
|
}
|
||||||
|
|
||||||
|
alphabet = alpha;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// 建立哈夫曼表码表 利用哈夫曼树 将各个字符对应的编码表 保存在文件 {file}.txt.hmz
|
||||||
|
void CreateHuffmanCode(){
|
||||||
|
HuffmanTree ht = this->CreateHuffmanTree();
|
||||||
|
// 从叶子节点到根 逆向求每个字符的哈夫曼编码, 存在编码表中
|
||||||
|
char *cd = new char[26];
|
||||||
|
new char* [26 + 1];
|
||||||
|
cd[26-1] = '\0';
|
||||||
|
|
||||||
|
// for (int i = 1; i <= 26; ++i) {
|
||||||
|
// int start = 26 - 1;
|
||||||
|
// int c = i;
|
||||||
|
// auto f = ht[i].parent;
|
||||||
|
// while (f != 0){
|
||||||
|
// --start;
|
||||||
|
// if(f != 0){
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
HuffmanTree CreateHuffmanTree(){
|
||||||
|
HuffmanTree ht = (new Huffman(26, alphabet))->getHuffmanTree();
|
||||||
|
|
||||||
|
for (int i = 1; i <= 2 * 26 - 1; ++i) {
|
||||||
|
printf("下标%d,值%c, 权重%d, ", i, ht[i].info, ht[i].weight);
|
||||||
|
std::cout << "双亲" << ht[i].parent <<", 左叶子" << ht[i].left << ", 右叶子" << ht[i].right << std::endl;
|
||||||
|
}
|
||||||
|
return ht;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //CPP_DATA_STRUCT_HUFFMAN_CODE_H
|
109
huffman_tree.h
Normal file
109
huffman_tree.h
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
//
|
||||||
|
// Created by dongl on 22-11-11.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef CPP_DATA_STRUCT_HUFFMAN_TREE_H
|
||||||
|
#define CPP_DATA_STRUCT_HUFFMAN_TREE_H
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
/// 可变长度的字符串 树组
|
||||||
|
typedef char** huffman_code;
|
||||||
|
|
||||||
|
/// 哈夫曼节点结构 一棵树的节点结构
|
||||||
|
struct HTNodeBase {
|
||||||
|
struct HTNodeBase* parent; // 父节点
|
||||||
|
struct HTNodeBase* left; // 左子节点
|
||||||
|
struct HTNodeBase* right; // 右子节点
|
||||||
|
};
|
||||||
|
|
||||||
|
/// 哈夫曼节点结构 一棵树的节点信息
|
||||||
|
typedef struct HTNode : public HTNodeBase{
|
||||||
|
int weight; // 节点权重
|
||||||
|
int index; // 下标
|
||||||
|
char info; // 节点信息
|
||||||
|
} *HuffmanTree;
|
||||||
|
|
||||||
|
|
||||||
|
/// 字母信息 与 出现的次数
|
||||||
|
struct Alphabet {
|
||||||
|
char data; // 字符
|
||||||
|
int count; // 字母出现次数
|
||||||
|
};
|
||||||
|
|
||||||
|
/// 哈夫曼树 一棵树的结构
|
||||||
|
/// 构建树 操作树 的类
|
||||||
|
class Huffman{
|
||||||
|
private:
|
||||||
|
HuffmanTree ht; // 树根
|
||||||
|
int tree_node_sum{}; // 树的叶子数
|
||||||
|
public:
|
||||||
|
// 构建哈夫曼树
|
||||||
|
Huffman(int n, Alphabet* alphabet) {
|
||||||
|
// 如果节点小于1 没有必要构建 直接return
|
||||||
|
if (n <= 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// 树的空间
|
||||||
|
// 0号单元未用 ht[2 * n - 1]表示根节点
|
||||||
|
int m = 2 * n - 1;
|
||||||
|
ht = new HTNode[m + 1];
|
||||||
|
// 构建树的全部节点
|
||||||
|
for (int i = 1; i <= m; ++i) {
|
||||||
|
ht[i].left = nullptr;
|
||||||
|
ht[i].right = nullptr;
|
||||||
|
ht[i].parent = nullptr;
|
||||||
|
}
|
||||||
|
// 构建存在个数节点的 字符与权重
|
||||||
|
for (int i = 1; i <= n; ++i) {
|
||||||
|
ht[i].weight = alphabet[i].count;
|
||||||
|
ht[i].info = alphabet[i].data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 正式 构建 构造 huffman 的节点关系 点与点之间的关系
|
||||||
|
for (int i = n+1; i < m; ++i) {
|
||||||
|
// 左右节点
|
||||||
|
int s1,s2;
|
||||||
|
SelectHuffmanTree(i, s1, s2);
|
||||||
|
// 表示从F中删除s1 ,s2
|
||||||
|
ht[i].left = &ht[s1];
|
||||||
|
ht[i].right = &ht[s2];
|
||||||
|
// s1 和 s2 分为为 i 的 左右叶子 权值为他俩的和
|
||||||
|
ht[i].weight = ht[s1].weight + ht[s2].weight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HuffmanTree getHuffmanTree() {
|
||||||
|
return ht;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// 建立哈夫曼树 根据统计结果
|
||||||
|
/// @param ht
|
||||||
|
/// @param n
|
||||||
|
/// @param s1
|
||||||
|
/// @param s2
|
||||||
|
void SelectHuffmanTree(int n, int& s1, int& s2){
|
||||||
|
s1 = min_index(n - 1);
|
||||||
|
s2 = min_index(n - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int min_index(int n){
|
||||||
|
int min;
|
||||||
|
int min_weight;
|
||||||
|
|
||||||
|
for (int i = 1; i <= n; ++i) {
|
||||||
|
// 没有父节点 未分配过的
|
||||||
|
if(ht[i].parent == nullptr){
|
||||||
|
min = i;
|
||||||
|
min_weight = ht[i].weight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ht[min].parent = &ht[n + 1];
|
||||||
|
std::cout << "min=" << min << ", n=" << n << ", parent="
|
||||||
|
<< ht[min].parent << ", weight=" << ht[min].weight
|
||||||
|
<< ", info=" << ht[min].info << std::endl;
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif //CPP_DATA_STRUCT_HUFFMAN_TREE_H
|
Loading…
x
Reference in New Issue
Block a user