class Node //代表各个字符的结点
{
public:
int data;
string code;
shared_ptr<Node> leftChild,rightChild;
Node():leftChild(nullptr),rightChild(nullptr),code(""){}
};
template<typename T>
class Greater
{
public:
bool operator()(T a, T b){ return a->data>b->data; }
};
void CreateTree(priority_queue<shared_ptr<Node>,vector<shared_ptr<Node>>,Greater<shared_ptr<Node>>> &t)
{
int eleSize = t.size();
//存储两个最小的结点和新结点
shared_ptr<Node> lChild,rChild,newNode;
if (t.empty()) return;
//1.如果只有一个结点
if (!t.empty() && t.size() < 2){
lChild = t.top();
newNode->leftChild = lChild;
t.push(newNode);
return;
}
//2.找出最小的两个结点构造新的结点
for (int i = 0; i < eleSize-1; ++i){ //函数完成之后,heap中只存一个结点,为根结点
lChild = t.top(),t.pop();
rChild = t.top(),t.pop();
newNode=make_shared<Node>(); //注意新节点虽然同名,但是就是一个新的
newNode->leftChild = lChild,newNode->rightChild = rChild;
newNode->data = lChild->data+rChild->data;
//将新建的结点重新插入到堆
t.push(newNode);
}
return;
}
//创建赫夫曼编码
void CreateCode(shared_ptr<Node> t, unordered_map<int,string> &code){ //传入树根+不断递归
if (t == nullptr) return;
if (t->leftChild){
t->leftChild->code = t->code + "0";
CreateCode(t->leftChild,code);
}
if (t->rightChild){
t->rightChild->code = t->code + "1";
CreateCode(t->rightChild,code);
}
if (t->leftChild == nullptr && t->rightChild == nullptr) //只对叶子结点的编码进行存储
code[t->data]=t->code;
}
int main()
{
//小根堆来存储输入的结点
//这里heap存的是结点指针,必须用函数对象或者lamda表达式来确定比较方式
priority_queue<shared_ptr<Node>,vector<shared_ptr<Node>>,Greater<shared_ptr<Node>>> heap;
setbuf(stdout, NULL);
//用来确保没有重复输入
set<int> arr;
cout << "请输入需要构造的结点(用空格隔开,按回车结束):" << endl;
int e,n;
cin>>n;
while (n--){
cin>>e;
arr.insert(e);
}
//将输入的数据存入小根堆
for (auto ele : arr){
//构建结点放入小根堆
shared_ptr<Node> newNode = make_shared<Node>();
newNode->data = ele;
heap.push(newNode);
}
CreateTree(heap);
shared_ptr<Node> tree = heap.top();
//创建huffMan编码
unordered_map<int,string> code;
CreateCode(tree, code);
//查找相应的编码
e=6;
cout << e << "的编码为" << code[e];
return 0;
}