c++实现huffmantree编码

目标

已知一组包含至少8个字符的数组及各字符的出现概率。求该字符串数组的哈夫曼编码及平均码长。

1.什么是Huffman编码
例如:c++一个字符是8bit,在传输时就会发送8bit,那么8个字符,就是8*8=64bit。Huffman编码对这些字符进行编码,将8字符变为了26bit,节约了空间Huffman编码后对应的
本文主要是代码实现,需要懂原理的建议看其他的博主文章,或则看我代码中的解释
以下是代码:

#include<iostream>
#include<time.h>
#include<stdlib.h>
#include<list>
#include <algorithm>
using namespace std;
#define CHARNUM 8//表示字符数; 
#define HUFNODE (2*CHARNUM)//用于表示创建humffmantree的节点的多少 
class Node{
	public:
		double weight=-1;
		char c;
		int left=-1;
		int right=-1;
		string code="";
		Node(){}
		Node(double weight,char c){
			(*this).weight=weight;
			(*this).c=c;
		}
};
bool cmp(Node *a,Node *b){
	return a->weight<b->weight;
}
class HumfTree{
	public :
		//创建一个数组,记录数据 
		Node *node[HUFNODE];
		Node *node1[HUFNODE-1];
		HumfTree(){
			
		}
//		初始化humffmantree;
//		对数组进行赋值; 
		void init(){
//			对每个节点进行赋值;
			int arr[CHARNUM];
			double sum=0;
			double weight;
			for(int i=0;i<CHARNUM;i++){
				arr[i] = rand()%15+1;
				sum+=arr[i]; 
			}
			for(int i=0;i<CHARNUM;i++){
				weight=arr[i]/sum;
				node[i] = new Node(weight,char(97+i));
			}
		}		
//		创建一个树, 
		void createTree(){
			int nodeNum=CHARNUM;
			int index=CHARNUM;
			
			int pre;
			Node temp;
			for(int i=0;i<CHARNUM-1;i++){
//				cout<<i<<endl;
				//cout<<i-(CHARNUM-1)<<endl;
				
				pre=2*i;
//				cout<<i+CHARNUM<<endl;
				sort(node+pre,node+pre+CHARNUM-i,cmp);
				node[i+CHARNUM] = new Node((node[pre]->weight+node[pre+1]->weight),'.');
				node[i+CHARNUM]->left=pre;
				node[i+CHARNUM]->right=pre+1;
			}
		}
//		以下两个方法表示进行前序遍历这个树 , 
		void preOrder(){
			selectAndCode(HUFNODE-2,"");
		}
		//遍历方法1.0 
		//这里遍历逻辑树,没有编码 
		void select(int index){
			cout<<node[index]->c<<":"<<node[index]->weight<<endl;
			if(node[index]->left!=-1){
				select(node[index]->left);
			}
			if(node[index]->right!=-1){
				select(node[index]->right);
			}
		}
		//遍历方法2.0 
		//这个方法用于前序遍历和编码 
		void selectAndCode(int index,string s){
			cout<<node[index]->c<<":"<<node[index]->weight<<endl;
			if(node[index]->c!='.'){
				node[index]->code=s;
			}
			if(node[index]->left!=-1){
				selectAndCode(node[index]->left,s+"0");
			}
			if(node[index]->right!=-1){
				selectAndCode(node[index]->right,s+"1");
			}
		}
		
		//该方法用于展示字符的huffman编码 
		void showCharCode(){
			for(int i=0;i<HUFNODE-1;i++){
				if(node[i]->c!='.'){
					cout<<node[i]->c<<":"<<node[i]->code<<endl;
				}
			}
		}
		
		//用于测试的方法; 
		void show(){
			double j=0;
			for(int i=0;i<8;i++){
				cout<<node[i]->c<<"权重"<<node[i]->weight<<endl;
				j+=node[i]->weight;
			} 
			cout<<"和"<<j<<endl<<endl; 
		}
		//计算wpi 
		double getWPI(){
			double ans=0;
			for(int i=0;i<HUFNODE-1;i++){
				if(node[i]->c!='.'){
					cout<<node[i]->c<<":"<<node[i]->code<<endl;
					
					//计算wpi 
					double w=node[i]->weight;
					int len=node[i]->code.length();
					ans+=w*len;
				}
			}
			
			return ans;
		} 
		
};


int main(){
	//改行代码用于生成随机数,不改变改行代码,生成的随机数不会改变,方便用于测试代码 
//	srand((int)time(0));
	
	HumfTree tree;
	tree.init();
	//显示一下各个数的权重 
	tree.show();
	tree.createTree();
	//前序遍历 
	cout<<"前序遍历"<<endl;
	tree.preOrder();
	
	
	//显示编码; 
	cout<<endl<<"显示编码"<<endl;
	tree.showCharCode();
	cout<<"....."<<endl; 
	//显示wpi 
	double wpi=tree.getWPI();
	cout<<endl<<"wpi="<<wpi<<endl;
	return 0;
} 

下面是原理分析,

下面是请添加图片描述
结果验证
请添加图片描述
有问题可以加我qq
2086385336

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值