HuffmanTree,哈夫曼树的原理和c++实现

一、什么是哈夫曼树

哈夫曼树又称为最优树.

通过权值来构造树,权值越大,离根节点越近

经常用于无损压缩算法

用于需要优化存储空间的场景

原理很简单,不多赘述

具体看百度百科的解释

需要注意 构建哈夫曼树不仅要值,还需要对应的权值

比如越常出现的,权值越大

二、构造哈夫曼树

通过权值来构造哈夫曼树

我画了几个图,具体过程如下

三、路径、编码、解码

上面通过权值构建了哈夫曼树,再将字符与权值对应起来

往左记作0 往右记作1

从根节点到各个叶子节点经过的0和1

就是该节点对应的路径

aaabbeaf编码:01010110101110011111

01010110101110011111解码:aaabbeaf

比如一个字符a原来占8位,通过哈夫曼编码后,就只占用2个位

但缺点是 权值较低的 占用字节会比较高,比如e,就占用4个位

四、代码

下面代码只是例子,编码解码并没有真的用位来表示,而是用字符串代替

HuffmanTree.h

#pragma once
#include<queue>
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
class HuffmanTree
{
	struct Node
	{
		int weight;//权值
		Node* left;//左孩子
		Node* right;//右孩子
		char value;//节点值
		string path;//存放路径
	};
	
	//仅用于优先级队列比较
	struct NodeCMP
	{
		bool operator()(Node* a, Node* b)
		{
			return a->weight > b->weight;
		}
	};
private:
	Node* root = nullptr;
	vector<pair<char, string>*>map;
public:
	HuffmanTree(vector<int>& weight, vector<char>& value) {
		createHuffmanTreeNode(weight,value);
		createHuffmanTreePath();
	}
	//初始化节点
	void createHuffmanTreeNode(vector<int>& weight, vector<char>& value) {
		priority_queue<Node*,vector<Node*>, NodeCMP>que;//优先级队列构造树
		for (size_t i = 0; i < weight.size(); i++){
			Node* temp = new Node{ weight[i] ,nullptr,nullptr,value[i] };
			que.push(temp);
		}
		while (que.size() >= 2){
			Node* min1 = que.top();
			que.pop();
			Node* min2 = que.top();
			que.pop();
			Node* node = new Node{ min1->weight + min2->weight,min1,min2 };
			que.push(node);
		}
		root = que.top();
	}
	//初始化路径
	void createHuffmanTreePath() {
		if (root == nullptr)return;
		queue<Node*>que;
		que.push(root);
		while (que.size()){
			Node* temp = que.front();
			que.pop();
			if (temp->left != nullptr) {
				que.push(temp->left);
				temp->left->path.append(temp->path + 0);
			}
			if (temp->right != nullptr){
				que.push(temp->right);
				temp->right->path.append(temp->path + 1);
			}
			if (temp->left == nullptr && temp->right == nullptr) {
				map.push_back(new pair<char, string>(temp->value, temp->path));
			}
		}
	}
	string encode(string data) {
		string result;
		for (size_t i = 0; i < data.size(); i++) {
			char ch = data[i];
			for (size_t j = 0; j < map.size(); j++) {
				pair<char, string>* mapData = map[j];
				if (mapData->first == ch) {
					result.append(mapData->second);
					break;
				}
			}
		}
		return result;
	}
	string decode(string data) {
		string result;
		while (data.size())
		{
			for (size_t i = 0; i < map.size(); i++)
			{
				pair<char, string>* mapData = map[i];
				if (data.find(mapData->second) == 0) {
					result.push_back(mapData->first);
					data = data.substr(mapData->second.size());
					break;
				}
			}
		}
		return result;
	}

};

main.cpp

#include<iostream>
#include<vector>
#includeHuffmanTree.h
int main() 
{
	vector<int>weight = { 8,9,7,4,2,3 };
	vector<char>value = { 'a','b','c','d','e','f'};
	HuffmanTree tree(weight,value);
	string str;
	str = tree.encode(aaabbeaf);
	cout << str << endl;
	str = tree.decode(str);
	cout << str << endl;

	return 0;
}
posted @ 2021-12-23 21:45  laomuji666  阅读(123)  评论(0编辑  收藏  举报