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