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