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

字符出现次数的哈夫曼树

分析和代码

/**
给定数组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有好的实现方法吗?

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您解答如何使用Python构造一棵哈夫曼树哈夫曼树是一种常用于数据压缩的树形结构,它的构造过程可以分为以下几个步骤: 1. 统计各字符在文本中出现次数 2. 将出现次数存储为节点权值 3. 将权值列表按升序排列 4. 取出前两个节点,并将它们合并为一颗新节点,权值为两者之和 5. 将新节点插入列表中,并按权值大小重新排序 6. 重复步骤4、5,直到列表只剩下一颗节点,即为哈夫曼树的根节点。 以下是使用Python实现的代码: ```python class Node: def __init__(self, value, char=None): self.value = value self.char = char self.left = None self.right = None def create_tree(freq): nodes = [Node(freq[i], i) for i in range(len(freq))] # 创建节点列表 while len(nodes) > 1: nodes.sort(key=lambda x: x.value) # 按value大小排序 left = nodes.pop(0) right = nodes.pop(0) parent = Node(left.value+right.value) # 创建新节点并合并左右节点 parent.left = left parent.right = right nodes.append(parent) # 将新节点插入列表 root = nodes[0] # 列表中唯一剩下的节点即为根节点 return root freq = [5, 9, 12, 13, 16, 45] # 各字符出现次数 root = create_tree(freq) ``` 以上代码中,先定义了节点类Node,包括节点权值value、节点字符char、左右子节点left、right四个属性。create_tree函数中,先根据各字符出现次数创建节点列表,然后通过排序和合并节点的方式,逐步构建哈夫曼树,最后返回根节点。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值