构造字符出现次数的哈夫曼树

字符出现次数的哈夫曼树

分析和代码

/**
给定数组vector<pair<char, int>>,其中pair的first是字符,second是字符出现的次数
请构造哈夫曼树?

思路:
1:构建以字符出现的次数为key的优先队列【最小堆哦】
2:将数组vector<pair<char, int>>加入到优先队列中
3:每次从优先队列弹出两个元素,构建以两个key的和为根、两个key为孩子的二叉树,然后将两个key的和加入到优先队列中
4:重复3直到优先队列中只有一个元素


优先队列:
	priority_queue<pair<int, HuffmnNode*>, vector<pair<int, HuffmnNode*>>, Comp> 
	其中:
		pair的int为字符出现的次数,
		HuffmnNode为哈夫曼树的节点
			struct HuffmnNode{
				char ch;					//字符,非叶子节点用' '代替
				int value;					//字符出现的次数【也可以看成是权值】
				struct HuffmnNode* left;	//树的左孩子
				struct HuffmnNode* right;	//树的右孩子
			};	
		vector<pair<int, HuffmnNode*>>是优先队列使用的容器
		Comp是比较器【仿函数】
Huffman:
	HuffmnNode* m_root;								//树的根节点
	unordered_map<char, string> m_char_to_encode;	//字符到密文的hash表

*/
class Huffman{
    
    
private:
	//哈夫曼树的节点
	struct HuffmnNode{
    
    
		HuffmnNode(char ch, int value){
    
    
			this->ch = ch;
			this->value = value;
			left = nullptr;
			right = nullptr;
		}
		char ch;
		int value;
		struct HuffmnNode* left;
		struct HuffmnNode* right;
	};
public:
	//优先队列的比较器
	struct Comp{
    
    
		bool operator()(const pair<int, HuffmnNode*>& x, const pair<int, HuffmnNode*>& y){
    
    
			return x.first > y.first;
		}
	};
	//构造哈夫曼树
	void generate_huffman(vector<pair<char, int>>& v){
    
    
		
		priority_queue<pair<int, HuffmnNode*>, vector<pair<int, HuffmnNode*>>, Comp> pq;
		
		//将数组vector加入到优先队列中
		for (auto& data : v){
    
    
			HuffmnNode* temp = new HuffmnNode(data.first, data.second);
			pq.push(make_pair(data.second, temp));
		}
		
		//构造树
		while (pq.size() != 1){
    
    
			//弹出来
			auto tp1 = pq.top(); pq.pop();
			auto tp2 = pq.top(); pq.pop();
			
			//构造树
			HuffmnNode* temp = new HuffmnNode(' ', tp1.first + tp2.first);
			temp->left = tp1.second;
			temp->right = tp2.second;
			//再加进去
			pq.push(make_pair(tp1.first + tp2.first, temp));
		}
		//树根
		m_root = pq.top().second;

		generate_encode(m_root,string(""));
	}
	
	//根据哈夫曼树生成密文
	void generate_encode(HuffmnNode* head,string& str){
    
    
		if (head->left == nullptr && head->right == nullptr){
    
    
			m_char_to_encode.insert(make_pair(head->ch, str));
			return;
		}
		if (head->left != nullptr){
    
    
			str.push_back('0');
			generate_encode(head->left, str);
			str.pop_back();
		}
		if (head->right != nullptr){
    
    
			str.push_back('1');
			generate_encode(head->right, str);
			str.pop_back();
		}
	}
	
	//加密
	string encode(string& str){
    
    
		string ret;
		for (auto ch : str){
    
    
			ret += m_char_to_encode[ch];
		}
		return ret;
	}
	
	//解密
	string decode(string& encode){
    
    
		string ret;
		for (size_t i = 0; i < encode.size(); /*++i*/){
    
    
			HuffmnNode* temp = m_root;
			while (temp->left != nullptr && temp->right != nullptr){
    
    
				temp = encode[i] == '0' ? temp->left : temp = temp->right;				
				++i;
			}
			ret.push_back(temp->ch);
		}
		return ret;
	}
private:
	HuffmnNode* m_root;
	unordered_map<char, string> m_char_to_encode;
};

思考

1、没有写析构函数释放资源
2、decode有好的实现方法吗?

猜你喜欢

转载自blog.csdn.net/xiaolixi199311/article/details/106392832