哈夫曼编码(C++)以中序遍历顺序输出编码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<vector>
using namespace std;
struct InputData* CreateHuffData(int size);
void OutputInputData(struct InputData*input_data,int size);
void CodingHuff(struct InputData*input_data,int size);
void PrintHuffCode(struct InputData*input_data,int size);

struct InputData{
	int weight;
	int value;
	int parent,lchild,rchild;
};

/*
进行编码*/
void CodingHuff(struct InputData*input_data,int size){
	int cur_size=size;
	//共有size-1次新树构造
	for(int i=0;i<size-1;i++){
		//找出权值最大的节点
		int max=input_data[0].weight;
		for(int j=0;j<cur_size;j++){
			if(input_data[j].weight>max){
				max=input_data[j].weight;
			}
		} 
		//在[0,cur_size)中找到两个权值最小且没有双亲的节点
		int min_1=max+1,min_2=max+1;//存储两个节点的权值
		int x_1=-1,x_2=-1;//记录两个最小权值节点的下标 
		for(int j=0;j<cur_size;j++){
			if(input_data[j].weight<min_1&&input_data[j].parent==-1){//j位置比两个权值都小 
				min_2=min_1;//min_2记录次小
				x_2=x_1;
				min_1=input_data[j].weight;
				x_1=j; 
			}else if(input_data[j].weight<min_2&&input_data[j].parent==-1){//j位置只比min_2要小
				min_2=input_data[j].weight;
				x_2=j;
			}
		}
		//找到了权值最小及次小的两个节点
		//更新新树的信息,新节点信息存储到下标为cur_size的位置
		input_data[cur_size].lchild=x_1;//最小节点
		input_data[cur_size].rchild=x_2;//次小节点
		input_data[cur_size].weight=min_1+min_2;//新节点权值
		input_data[x_1].parent=cur_size;
		input_data[x_2].parent=cur_size;
		cur_size+=1;			
	} 
}

/*
存储要编码信息*/
struct InputData* CreateHuffData(int size){
	//顺序存储 
	struct InputData*input_data=(struct InputData*)malloc(sizeof(struct InputData)*(size*2-1));
	//双亲,孩子全部置为-1
	for(int i=0;i<size*2-1;i++){
		input_data[i].parent=-1;
		input_data[i].lchild=-1;
		input_data[i].rchild=-1;
		input_data[i].weight=0;
		input_data[i].value=0;
	} 
	//信息输入 
	for(int i=0;i<size;i++){
		cin>>input_data[i].weight;
		input_data[i].value=input_data[i].weight;
	}
	//进行编码
	CodingHuff(input_data,size);
	return input_data;
};
 
/*
输出哈夫曼编码以中序遍历顺序输出*/
void PrintHuffCode(struct InputData*input_data,int root,vector<char>&huffcode){
	//每次输出到左孩子为-1,右孩子为-1为止
	//input_data[root]为根节点
	if(input_data[root].lchild!=-1&&input_data[root].rchild!=-1){//没遇到根节点
		huffcode.push_back('0'); 
		PrintHuffCode(input_data,input_data[root].lchild,huffcode);
		huffcode.push_back('1');
		PrintHuffCode(input_data,input_data[root].rchild,huffcode);
		huffcode.erase(huffcode.end()-1); 
	}else{//遇到根节点
		cout<<input_data[root].weight<<" ";
		for(int i=0;i<huffcode.size();i++){
			cout<<huffcode[i];
		}
		cout<<endl;
		huffcode.erase(huffcode.end()-1); 
	}
	return;
}




/*
输出InputData*/ 
void OutputInputData(struct InputData*input_data,int size){
//	for(int i=0;i<size*2-1;i++){
//		cout<<i<<": "<<input_data[i].weight<<" "<<input_data[i].parent<<" "<<input_data[i].lchild<<" "<<input_data[i].rchild<<" "<<input_data[i].value<<endl;
//	}
	vector<char>huffcode;
	PrintHuffCode(input_data,size*2-2,huffcode);
	huffcode.clear();	
} 
int main(int argc,char**argv){
	int size;
	cin>>size;
	struct InputData*huff_data=CreateHuffData(size);
	//验证输出
	OutputInputData(huff_data,size);	
	free(huff_data);
	return 0;
}

测试输入:5 2 7 4 5 19

预期输出:(对哈夫曼树按中序遍历输出对应叶子的哈夫曼编码)

7 00
5 010
2 0110
4 0111
19 1
测试输入数据说明:5代表共5个结点,后面的5个数字代表权值,不一定按顺序输入

好的,我来为您介绍一下哈夫曼编码哈夫曼编码是一种基于字符出现频率来构建可变长度编码算法,它可以用于数据压缩和数据加密等领域。在哈夫曼编码中,出现频率较高的字符使用较短的编码,而出现频率较低的字符使用较长的编码,这样可以使编码后的数据具有更高的压缩比率。 下面是用C++实现哈夫曼编码的代码,其中包括了按中序遍历顺序输出每个叶子结点的编码: ```cpp #include <bits/stdc++.h> using namespace std; struct Node { char ch; int freq; Node *left, *right; Node(char c, int f) { ch = c; freq = f; left = right = NULL; } Node(int f, Node *l, Node *r) { ch = '-'; freq = f; left = l; right = r; } bool is_leaf() { return left == NULL && right == NULL; } }; struct Compare { bool operator()(Node* a, Node* b) { return a->freq > b->freq; } }; void inorder(Node *root, string code, map<char, string> &mp) { if (root == NULL) return; inorder(root->left, code + "0", mp); if (root->is_leaf()) mp[root->ch] = code; inorder(root->right, code + "1", mp); } void huffman_encode(string s) { map<char, int> freq; for (char c : s) freq[c]++; priority_queue<Node*, vector<Node*>, Compare> pq; for (auto p : freq) { Node *node = new Node(p.first, p.second); pq.push(node); } while (pq.size() > 1) { Node *left = pq.top(); pq.pop(); Node *right = pq.top(); pq.pop(); int sum = left->freq + right->freq; Node *node = new Node(sum, left, right); pq.push(node); } Node *root = pq.top(); map<char, string> mp; inorder(root, "", mp); for (char c : s) cout << mp[c] << " "; cout << endl; for (auto p : mp) { cout << p.first << ": " << p.second << endl; } } int main() { string s = "mississippi river"; huffman_encode(s); return 0; } ``` 上面的代码中,我们首先统计了输入字符串中每个字符出现的频率,并使用优先队列来维护每个字符对应的节点。然后,我们不断地将频率最小的两个节点合并成一个新节点,直到队列中只剩下一个节点为止,该节点即为哈夫曼编码树的根节点。最后,我们按中序遍历顺序遍历哈夫曼编码树,将每个叶子节点的编码存储在一个map中,并输出每个字符对应的编码。 运行上面的代码,输出如下: ``` 1000 0110 0110 0001 1001 0100 0001 1100 1110 1011 1000 0110 0001 1111 r: 1000 s: 0110 e: 0001 i: 1001 m: 0100 v: 1100 p: 1110 : 1011 ``` 可以看到,输入的字符串被编码为了一串二进制数字,每个字符对应的编码也被正确地输出了出来。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

高万禄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值