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

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;
}

 

  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
多元哈夫曼编码是一种用于数据压缩的算法,它可以将出现频率高的字符用较短的编码表示,而出现频率低的字符用较长的编码表示,以实现数据压缩的目的。 在多元哈夫曼编码中,每个字符都有一个权重或频率与之相关联。编码过程中,首先建立一棵哈夫曼树,然后根据哈夫曼树给每个字符赋予对应的编码。 下面是使用C语言实现多元哈夫曼编码的基本步骤: 1. 创建一个包含所有字符及其权重的结构体数组。 2. 根据权重对结构体数组进行排序,从小到大或者从大到小。 3. 不断合并权重最小的两个结点,直到只剩下一个结点,这个结点就是哈夫曼树的根结点。 4. 通过遍历哈夫曼树,为每个字符生成对应的编码。 5. 将字符及其对应的编码存储在一个映射表中。 6. 使用映射表将原始数据进行编码,并将编码后的数据存储在文件或内存中。 以下是一个简单的多元哈夫曼编码的C语言实现示例: ```c #include <stdio.h> #include <stdlib.h> typedef struct Node { char data; int weight; struct Node* left; struct Node* right; } Node; // 创建一个新的结点 Node* createNode(char data, int weight) { Node* newNode = (Node*)malloc(sizeof(Node)); newNode->data = data; newNode->weight = weight; newNode->left = NULL; newNode->right = NULL; return newNode; } // 合并两个结点 Node* mergeNodes(Node* node1, Node* node2) { Node* mergedNode = createNode('$', node1->weight + node2->weight); mergedNode->left = node1; mergedNode->right = node2; return mergedNode; } // 构建哈夫曼树 Node* buildHuffmanTree(Node** nodes, int size) { while (size > 1) { qsort(nodes, size, sizeof(Node*), compareNodes); // 对结点数组进行排序 Node* mergedNode = mergeNodes(nodes[0], nodes[1]); // 合并权重最小的两个结点 nodes[0] = mergedNode; // 将合并后的结点放到数组的第一个位置 for (int i = 1; i < size - 1; i++) { nodes[i] = nodes[i + 1]; // 将后面的结点往前移动 } size--; // 数组大小减一 } return nodes[0]; // 返回哈夫曼树的根结点 } // 生成编码 void generateCodes(Node* root, char* code, int codeLen) { if (root->left == NULL && root->right == NULL) { // 叶子结点 code[codeLen] = '\0'; printf("%c: %s\n", root->data, code); return; } code[codeLen] = '0'; generateCodes(root->left, code, codeLen + 1); code[codeLen] = '1'; generateCodes(root->right, code, codeLen + 1); } // 比较两个结点的权重 int compareNodes(const void* a, const void* b) { Node* nodeA = *(Node**)a; Node* nodeB = *(Node**)b; return nodeA->weight - nodeB->weight; } int main() { char data[] = {'a', 'b', 'c', 'd', 'e'}; int weight[] = {5, 9, 12, 13, 16}; int size = sizeof(data) / sizeof(data[0]); Node** nodes = (Node**)malloc(size * sizeof(Node*)); for (int i = 0; i < size; i++) { nodes[i] = createNode(data[i], weight[i]); } Node* root = buildHuffmanTree(nodes, size); char code[100]; generateCodes(root, code, 0); free(nodes); return 0; } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值