哈夫曼编码

//File Name: node.h

#ifndef _NODE_H
#define _NODE_H
#include <iostream>
#include <string>
#include <set>
#include <map>
using namespace std;

class Node{
	public:
		friend class Tree;
		Node():c(' '),w(-1),bits(""),lc(nullptr),rc(nullptr){}
		Node(const char ch,const int weight):c(ch),w(weight),bits(""),lc(nullptr),rc(nullptr){}
		Node(const Node &rhs)	//拷贝构造函数
		{
			c	= rhs.c;
			w	= rhs.w;
			bits= rhs.bits;
			lc	= rhs.lc;
			rc	= rhs.rc;
		}
		//Node* clone()const
		//{ return new Node(*this); }
		int get_weight()const
		{ return w; }
		char get_char()const
		{ return c; }
		Node& get_lchild()
		{ return *lc; }			
		Node& get_rchild()
		{ return *rc; }
		/* 设置左右子结点 */
		void set(const Node& l,const Node& r)
		{
			lc = new Node(l);	
			rc = new Node(r);
		}
		/* 设置编码信息 */
		void set_bits(const string &str)
		{ bits = str; }

	//private:
		char	c;
		int		w;
		string	bits;
		Node*	lc;	//左节点
		Node*	rc;	//右节点
};

struct Bigger{
	bool operator()(const Node&lhs,const Node& rhs)const
	{ return lhs.get_weight()<rhs.get_weight(); }
};


class Tree{
public:
	friend class Node;
	Tree(){}		
	void add_node(Node& n)
	{ nodes.insert(n); }
	Node pop()
	{
		Node n(*nodes.begin());		//调用Node的拷贝构造函数,存储即将删除的元素
		nodes.erase(nodes.begin());	//从multiset中删除首元素
		return n;
	}
	size_t size()
	{ return nodes.size(); }
	Node get_Node()
	{ return *nodes.begin();}

	void get_code(Node* root,Node* child)
	{	
		//用于判断是否重新判断根节点的右子树
		if (root->bits=="#")
			tmp="";
		//说明遇到了叶节点
		if (child->lc==nullptr){
			if (child==root->lc){
				tmp += "0";
			}else{
				tmp += "1";
			}
			codes.insert({child->c,tmp});
			child->bits = tmp;
			cout<<child->c<<" : "<<child->bits<<endl;
			return;
		}
		//遇到非叶节点
		if (child==root->lc){
			cout<<"左:"<<child->c<<endl;
			tmp += "0";
		}else{
			cout<<"右:"<<child->c<<endl;
			tmp += "1";
		}
		get_code(child,child->lc);
		tmp.erase(tmp.end()-1);
		get_code(child,child->rc);
		tmp.erase(tmp.end()-1);
	}
	map<char,string> codes;

private:
	multiset<Node,Bigger> nodes;
	string tmp;
};
#endif

// File Name: main.cpp

#include<iostream>
#include <string>
#include"node.h"
#include<string>
using namespace std;

int main(int argc,char** argv)
{
	int n,w;
	char c;
	string s;
	cout<<"enter size of char:";
	cin>>n;
	Tree bn;
	for(int i=0; i!=n; ++i){
		cout<<"enter char and weight:";
		cin>>c>>w;
		Node a(c,w);
		bn.add_node(a);
		cin.clear();		//清空输入缓冲流
	}
	while(bn.size()!=1){
		Node n1 = bn.pop();
		Node n2 = bn.pop();	//获取权重最小的两个节点
		Node h(' ',n1.get_weight()+n2.get_weight());	//将前者合并为新节点
		if (n1.get_weight()<n2.get_weight()){
			h.set(n1,n2);		//设置左右节点
		}else{
			h.set(n2,n1);
		}
		bn.add_node(h);
	}
	cout<<"================="<<endl;
	Node root = bn.get_Node();
	root.set_bits("#");	//设置根节点的标志,用于遍历右子树时的判定
	cout<<"left ======="<<endl;
	bn.get_code(&root,root.lc);
	cout<<"right======="<<endl;
	bn.get_code(&root,root.rc);
	cout<<"================="<<endl;

	for(auto&i:bn.codes){
		cout<<i.first<<" : "<<i.second<<endl;
	}
	return 0;
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值