注意: 所有的准备工作只是为了将这个题目分解成很多小问题解决,而最终我写的哈夫曼解压缩代码会与准备工作有很大区别。
前期准备
随机生成0~127的数
#include<math.h>
#include<time.h>
#include<stdlib.h>
int main() {
int n;
srand(time(NULL));
for (int i = 0; i < 10; i++) {
n = rand() % 128;
cout << n << " ";
}
}
输出随机生成的数对应的ASCLL字符
#include<iostream>
using namespace std;
#include<math.h>
#include<time.h>
#include<stdlib.h>
int main() {
srand(time(NULL));
char c;
for (int i = 0; i < 10; i++) {
c = rand() % 128;
cout << c << " ";
}
}
随机生成1024个字符,写入文件中
#include<iostream>
using namespace std;
#include<math.h>
#include<time.h>
#include<stdlib.h>
#include<fstream>
int main() {
srand(time(NULL));
ofstream ofs;
ofs.open("D:\\data.txt", ios::out);
char c;
for (int i = 0; i < pow(2, 10); i++) {
c = rand() % 128;
ofs << c;
}
ofs.close();
}
#include<iostream>
using namespace std;
#include<math.h>
#include<time.h>
#include<stdlib.h>
#include<fstream>
int main() {
srand(time(NULL));
char c = 32;
for (int i = 0; i < 95; i++) {
if (i % 10 == 0)
cout << "\n";
cout << c<<" ";
c++;
}
}
现在我想向文件随意输入ASCLL码在32~126之间的字符
#include<iostream>
using namespace std;
#include<math.h>
#include<time.h>
#include<stdlib.h>
#include<fstream>
int main() {
srand(time(NULL));
ofstream ofs;
ofs.open("D:\\data.txt", ios::out);
char c;
for (int i = 0; i < pow(2, 10); i++) {
c = 32 + rand() % 95;
ofs << c;
}
ofs.close();
}
向大家简单介绍一个,一个char型在内存中大小为1个字节,一个字节 = 8个比特位,一个比特位就是我们所熟知的二进制0和1。
计算文件中每个字符的个数
#include<iostream>
using namespace std;
#include<fstream>
#include<unordered_map>
int main() {
ifstream ifs;
ifs.open("D:\\data.txt", ios::in);
unordered_map<char, int> map;
char c;
while ((c = ifs.get()) != EOF) {
map[c]++;
}
ifs.close();
unordered_map<char, int>::iterator it = map.begin();
for (; it != map.end(); it++) {
cout << it->first << " " << it->second << "\n";
}
}
优先级队列
这个内容应该使用小根堆实现的,但是偷个懒直接用现成给的了。
#include < queue >就好了
这个作用是每次从队列里出来的数是队列中最小的数。
当然,优先级队列默认是每次从队列里出来的数是队列中最大的数
#include<iostream>
using namespace std;
#include<queue>
int main() {
priority_queue<int, vector<int>, greater<int>> q;
int arr[] = { 54,26,93,17,77,31,44,55,20 };
for (int i = 0; i < 9; i++) {
q.push(arr[i]);
}
int n;
for (int i = 0; i < 9; i++) {
n = q.top();
q.pop();
cout << n << " ";
}
}
#include<iostream>
using namespace std;
#include<queue>
struct huffmanNode
{
char element;
int weight;
huffmanNode* leftChild, * rightChild;
huffmanNode(char element = NULL, int weight = 0, huffmanNode* leftChild = NULL,
huffmanNode* rightChild = NULL) {
this->element = element;
this->weight = weight;
this->leftChild = leftChild;
this->rightChild = rightChild;
}
};
struct cmp
{
bool operator()(huffmanNode* x, huffmanNode* y) {
return x->weight > y->weight;
}
};
int main() {
priority_queue<huffmanNode*,vector<huffmanNode*>,cmp> q;
huffmanNode* h1 = new huffmanNode('a', 5);
huffmanNode* h2 = new huffmanNode('b', 7);
huffmanNode* h3 = new huffmanNode('c', 3);
q.push(h1);
q.push(h2);
q.push(h3);
huffmanNode* cur;
for (int i = 0; i < 3; i++) {
cur = q.top();
q.pop();
cout << cur->element << " ";
}
}
构建哈夫曼树:
#pragma once
#include<iostream>
using namespace std;
#include<queue>
#include<unordered_map>
#include<fstream>
struct huffmanNode
{
char element;
int weight;
huffmanNode* leftChild, * rightChild;
huffmanNode(char element = NULL, int weight = 0, huffmanNode* leftChild = NULL,
huffmanNode* rightChild = NULL) {
this->element = element;
this->weight = weight;
this->leftChild = leftChild;
this->rightChild = rightChild;
}
};
struct cmp
{
bool operator()(huffmanNode* x, huffmanNode* y) {
return x->weight > y->weight;
}
};
class huffmanTree
{
private:
unordered_map<char, int> map_weight;
unordered_map<char, string> map_code;
huffmanNode* root;
public:
huffmanTree();
~huffmanTree();
void createTree();
void compressedFile(const char* path = "D:\\data.txt");
void dispose(huffmanNode* t);
void print();
void print(huffmanNode* t);
void output();
};
huffmanTree::huffmanTree()
{
root = NULL;
}
huffmanTree::~huffmanTree()
{
dispose(root);
root = NULL;
}
void huffmanTree::createTree()
{
if (map_weight.empty()) {
cout << "未读取文件,请先读取文件!\n";
return;
}
priority_queue<huffmanNode*, vector<huffmanNode*>, cmp> q;
unordered_map<char, int>::iterator it = map_weight.begin();
for (; it != map_weight.end(); it++) {
huffmanNode* node = new huffmanNode(it->first, it->second);
q.push(node);
}
huffmanNode* w, * x, * y;
while (q.size() > 1) {
x = q.top();
q.pop();
y = q.top();
q.pop();
int weight = x->weight + y->weight;
w = new huffmanNode('?', weight, x, y);
q.push(w);
}
root = q.top();
}
void huffmanTree::compressedFile(const char* path)
{
ifstream ifs;
ifs.open(path, ios::in);
char c;
while ((c = ifs.get()) != EOF) {
map_weight[c]++;
}
ifs.close();
}
void huffmanTree::dispose(huffmanNode* t)
{
if (t != NULL) {
dispose(t->leftChild);
dispose(t->rightChild);
delete t;
}
}
void huffmanTree::print()
{
print(root);
}
void huffmanTree::print(huffmanNode* t)
{
if (t != NULL) {
print(t->leftChild);
cout << t->element;
print(t->rightChild);
}
}
void huffmanTree::output()
{
unordered_map<char, int>::iterator it = map_weight.begin();
for (; it != map_weight.end(); it++) {
cout << it->first << " " << it->second << "\n";
}
}
test.cpp
#include<iostream>
using namespace std;
#include"huffmanTree.h"
int main() {
huffmanTree h;
h.compressedFile();
h.createTree();
h.print();
return 0;
}