可以利用huffman 树的特性,只要别人拿不到你的huffmanKey 别人就无法还原你的数据 ,一般可以用于文件加密
#pragma once
#include <vector>
#include <string>
struct HuffmanNode {
char data;
unsigned int frequency;
HuffmanNode* left;
HuffmanNode* right;
HuffmanNode(char data, unsigned int frequency) : data(data), frequency(frequency), left(nullptr), right(nullptr) {}
};
class HuffmanUtil
{
private:
std::string treeToKey(HuffmanNode* root);
HuffmanNode* keyToTree(std::string key);
public:
std::string encodeHuffman(std::vector<uint8_t> &sourceCode, std::vector<uint8_t> &resultCode);
void decodeHuffman(std::vector<uint8_t>& encode, std::vector<uint8_t>& decode, std::string key);
};
#include "HuffmanUtil.h"
#include <unordered_map>
#include <bitset>
#include <queue>
namespace {
struct Compare {
bool operator()(HuffmanNode* left, HuffmanNode* right) {
return left->frequency > right->frequency;
}
};
HuffmanNode* buildHuffmanTree(const std::unordered_map<char, unsigned>& frequencies) {
std::priority_queue<HuffmanNode*, std::vector<HuffmanNode*>, Compare> minHeap;
for (const auto& pair : frequencies) {
minHeap.push(new HuffmanNode(pair.first, pair.second));
}
while (minHeap.size() > 1) {
HuffmanNode* left = minHeap.top();
minHeap.pop();
HuffmanNode* right = minHeap.top();
minHeap.pop();
HuffmanNode* internalNode = new HuffmanNode('$', left->frequency + right->frequency);
internalNode->left = left;
internalNode->right = right;
minHeap.push(internalNode);
}
return minHeap.top();
}
void serializeHuffmanTree(std::vector<unsigned int>& outKey, HuffmanNode* root) {
if (root) {
outKey.push_back(root->data);
outKey.push_back(root->frequency);
serializeHuffmanTree(outKey, root->left);
serializeHuffmanTree(outKey, root->right);
}
else {
outKey.push_back('\0');
}
}
HuffmanNode* deserializeHuffmanTree(std::vector<unsigned int>&key, int &seek) {
char data;
unsigned int frequency;
data = (char)key[seek];
seek++;
if (data == '\0') {
return nullptr;
}
frequency = (char)key[seek];
seek++;
HuffmanNode* left = deserializeHuffmanTree(key, seek);
HuffmanNode* right = deserializeHuffmanTree(key, seek);
auto result = new HuffmanNode(data, frequency);
result->left = left;
result->right = right;
return result;
}
void generateCodes(HuffmanNode* root, std::string code, std::unordered_map<char, std::string>& huffmanCodes) {
if (!root)
return;
if (!root->left && !root->right) {
huffmanCodes[root->data] = code;
}
generateCodes(root->left, code + "0", huffmanCodes);
generateCodes(root->right, code + "1", huffmanCodes);
}
std::string decodeToString(std::vector<uint8_t>& encode) {
std::string result;
for (auto tmp : encode) {
for (int i = 1; i <= 8; i++) {
if (((tmp & (0x1 << (8 - i))) != 0)) {
result.append("1");
}
else {
result.append("0");
}
}
}
return result;
}
}
std::string HuffmanUtil::treeToKey(HuffmanNode* root)
{
std::vector<unsigned int> key;
serializeHuffmanTree(key, root);
return std::string(key.begin(), key.end());
}
HuffmanNode* HuffmanUtil::keyToTree(std::string key)
{
std::vector<unsigned int> decode_key(key.begin(), key.end());
int seek = 0;
return deserializeHuffmanTree(decode_key, seek);
}
std::string HuffmanUtil::encodeHuffman(std::vector<uint8_t>& sourceCode, std::vector<uint8_t>& resultCode)
{
std::unordered_map<char, unsigned int> frequencies;
for (uint8_t c : sourceCode) {
frequencies[c]++;
}
HuffmanNode *root = buildHuffmanTree(frequencies);
std::string huffmanKey = treeToKey(root);
std::unordered_map<char, std::string> huffmanCodes;
generateCodes(root, "", huffmanCodes);
std::string encodedString = "";
for (uint8_t c : sourceCode) {
encodedString += huffmanCodes[c];
}
int fill_num = 0;
std::string outencode_string = encodedString;
while (encodedString.length() % 8 != 0) {
encodedString += "0";
fill_num++;
}
for (size_t i = 0; i < encodedString.length(); i += 8) {
std::bitset<8> byte(encodedString.substr(i, 8));
resultCode.push_back(byte.to_ulong());
}
std::string result = std::to_string(fill_num);
return result.append(huffmanKey);
}
void HuffmanUtil::decodeHuffman(std::vector<uint8_t>& encode, std::vector<uint8_t>& decode, std::string key)
{
std::string real_key = key.substr(1);
int fill_num = std::stoi(key.substr(0, 1), 0, 10);
HuffmanNode* root = keyToTree(real_key);
std::string encodeString = decodeToString(encode);
encodeString = encodeString.substr(0, encodeString.size() - fill_num);
HuffmanNode* current = root;
for (char bit : encodeString) {
if (bit == '0') {
current = current->left;
}
else {
current = current->right;
}
if (!current->left && !current->right) {
decode.push_back(current->data);
current = root;
}
}
}
string resultCode = "askdjaslkdqjlmqnlkzxncokjkashdokajdokqwdjlkasdnldk";
vector<uint8_t> xx(resultCode.begin(), resultCode.end());
vector<uint8_t> yy;
vector<uint8_t> zz;
HuffmanUtil hummanUtil;
std::string huffmanKey = hummanUtil.encodeHuffman(xx, yy);
hummanUtil.decodeHuffman(yy, zz, huffmanKey);