哈夫曼编码问题(C++ and 贪心 and 指针运用)

本文详细介绍了哈夫曼编码的基本概念,以及如何利用哈夫曼树构造最短的不等长编码方案。通过具体步骤解析哈夫曼树的构建过程,并提供了完整的C++实现代码,帮助读者深入理解并掌握哈夫曼编码的原理和应用。

1. 哈夫曼编码问题

问题描述:设需要编码的字符集为{d1, d2, …, dn},它们出现的频率为{w1, w2, …, wn},应用哈夫曼树构造最短的不等长编码方案。

提示:哈夫曼树(Huffman Tree),又叫最优二叉树,指的是对于一组具有确定权值的叶子结点的具有最小带权路径长度的二叉树。

哈夫曼树的构造算法:假设有n个权值,则构造出的哈夫曼树有n个叶子结点。n个权值分别设为w1,w2,...,wn,则哈夫曼树的构造规则为:

(1)将w1,w2,...,wn看成是有n棵树的森林(每棵树仅有一个结点);

(2)在森林中选出两个根结点的权值最小的树合并,作为一棵新树的左、右子树,且新树的根结点权值为其左、右子树根结点权值之和;

(3)从森林中删除选取的两棵树,并将新树加入森林;

(4)重复(2)、(3)步,直到森林中只剩一棵树为止,该树即为所求得的哈夫曼树。

#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
using namespace std;
struct Node {
	Node(double d, Node* l = NULL, Node* r = NULL, Node* f = NULL) :data(d), left(l), right(r), father(f) {}
	double data;
	Node* father, * left, * right;	//父,左右孩子
	string code;	//存储编码
};
typedef Node* Tree;
										//通过中序,构建编码
void creatCode(Node* node, string s) {		
	if (node != NULL) {
		creatCode(node->left, s + '0');
		if (node->left == NULL && node->right == NULL)		//是叶子节点就更新编码
			node->code = s;
		creatCode(node->right, s + '1');
	}
}	
int main() {
	vector<double> w;
	vector<Node*> node;
	double tmp;
	Tree tree;
	cout << "输入权值,数字后紧跟回车结束:";
	do {
		cin >> tmp;
		w.push_back(tmp);
	} while (getchar() != '\n');
	sort(w.begin(), w.end(), greater<double>());	//降序排序
	for (int i = 0; i < w.size(); i++)
		node.push_back(new Node(w[i]));
	vector<Node*> out = node;
	Node * left, *right;
	do {
		right = node.back(); node.pop_back();		//取出最小的两个
		left = node.back(); node.pop_back();
		node.push_back(new Node(left->data + right->data, left, right));		//将新结点(求和)推进数组中
		left->father = node.back();			//更新父结点
		right->father = node.back();
		out.push_back(node.back());			//存储此结点
		for (int i = node.size() - 1; i > 0 && node[i]->data > node[i - 1]->data; i--)		//从末尾冒泡,排序
			swap(node[i], node[i - 1]);
	} while (node.size() != 1);	  //构建树结构
	tree = node.front();			//剩余的一个结点即根结点
	creatCode(tree, "");			
	printf("结点\t父结点\t左孩子\t右孩子\t编码\n");
	for (int i = 0; i < out.size(); i++)
		printf("%.2lf\t%.2lf\t%.2lf\t%.2lf\t%s\n", out[i]->data, out[i]->father == NULL ? 0 : out[i]->father->data, out[i]->left == NULL ? 0 : out[i]->left->data, out[i]->right == NULL ? 0 : out[i]->right->data, out[i]->code.c_str());
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值