huffmanTree实现

176 阅读1分钟

通过字符出现的频率设置权重进行哈夫曼编码

#pragma once
#include<iostream>
#include<queue>
#include<string>
#include<utility>
#include<unordered_map>

struct Node {
	Node* left=nullptr;
	Node* right=nullptr;
	int weight = 0;
	char data='\0';
	bool isLeaf = false;
};

struct cmp{
	bool operator ()(Node* a, Node* b) {
		return (a->weight > b->weight);
	}
};

class HuffmanTree {
private:
	std::vector<std::pair<char, std::string>> code;
	size_t size = 0;
	Node* top;

	void dfs(Node* node, int pos, std::string& s);
public:
	HuffmanTree() = default;
	HuffmanTree(std::string data);
	~HuffmanTree();
	void HuffmanCode();

};

HuffmanTree::HuffmanTree(std::string data) {
	std::unordered_map<char, int> freqMap;
	std::priority_queue<Node*, std::vector<Node*>,cmp> queue;
	
	for(auto e : data) freqMap[e]++;
	this->size = freqMap.size();
	for (auto& e : freqMap) {
		Node* node = new Node;
		node->data = e.first;
		node->weight = e.second;
		node->isLeaf = true;
		queue.push(node);
	}

	while (queue.size() > 1) {
		//queue.size() > 1 保证无论奇数还是偶数最后queue都只剩一个节点
		Node* node1 = queue.top();
		queue.pop();
		Node* node2 = queue.top();
		queue.pop();

		Node* parent = new Node;
		parent->weight = node1->weight + node2->weight;
		if (node1->weight > node2->weight) {
			parent->left = node1;
			parent->right = node2;
		}
		else {
			parent->left = node2;
			parent->right = node1;
		}
		queue.push(parent);
	}
	top = queue.top();
}

void erase(Node* data) {
	if (nullptr == data)return;
	erase(data->left);
	erase(data->right);
	delete data;
}

HuffmanTree::~HuffmanTree() {
	erase(this->top);
}

void HuffmanTree::dfs(Node* node,int pos,std::string& s){
	if (node == nullptr) return;

	if (pos == 0) s += '0';
	else s += '1';
	dfs(node->left,0,s);
	dfs(node->right,1,s);
	if (true == node->isLeaf) {
		this->code.emplace_back(std::make_pair(node->data, s));
	}
	s.pop_back();
}

inline void HuffmanTree::HuffmanCode(){
	std::string s = "";
	dfs(this->top,0,s);
	sort(this->code.begin(), this->code.end(), [](auto a, auto b) {
		return a.first < b.first;
		});
	for (auto& e : this->code) {
		std::cout << e.first << " " << e.second << std::endl;
	}
}

调用如下

#include<iostream>
#include"HuffTree.h"

int main() {
	HuffmanTree a("1231231232222211asdfdsdfcghjgh");
	a.HuffmanCode();
}

编码如果没有出问题是这样的

1 0000
2 001
3 0110
a 000101
c 000100
d 0111
f 01000
g 01001
h 00011
j 01011
s 01010