利用了优先队列,实现了对哈夫曼树的创建,基于已经建好的哈夫曼树,对其进行编码,解码。
算法步骤:
1、初始化每个叶节点,n个叶节点就初始化为n棵树,构成森林;
2、利用优先队列,每次从森林中pop出两个权重最小的节点,生成新的节点,新节点的权重是它们俩的权重和,把新节点加入到森林里面(优先队列中);
3、重复以上过程n-1次,直到最后队列中只剩下一个节点;
结点结构:
typedef struct HTNode{
char data;//结点的值
struct HTNode* left,*right;//左右子树
Wi weight;//权重
bool operator < (const HTNode &other){
return weight > other.weight;
}
};
建树代码
HTNode* CreateHuffman(CharFreq charFreq[],int n) //创建哈夫曼树
{
int i,j;
HTNode* huffmanTree = nullptr; //根据n个权值声明n个二叉树的森林,二级指针表示森林(二叉树的集合)
priority_queue<HTNode*, vector<HTNode*>, cmp> trees;
//实现第一步,创建n颗二叉树,左右子树为空
for(int i = 0;i < n;i++){
HTNode* tree = (HTNode*)new HTNode;
tree->data = charFreq[i].first;
tree->weight = charFreq[i].second;
tree->left = tree->right= nullptr;
trees.push(tree);
}
for(int i = 1;i < n;i++){
//第二部,选择权值最小的根节点二叉树下标为第一个和第二个
HTNode* min1 = trees.top();
trees.pop();
HTNode* min2 = trees.top();
trees.pop();
HTNode* newNode = new HTNode;
newNode->weight = min1->weight + min2->weight;
newNode->left = min1;
newNode->right = min2;
trees.push(newNode);
huffmanTree = newNode;
}
cout<< endl;
return huffmanTree;
}
所有代码:
头文件:
#include <iostream>
using namespace std;
typedef int Wi; //
typedef pair<char,int> CharFreq;
typedef struct HTNode{
char data;//结点的值
struct HTNode* left,*right;//左右子树
Wi weight;//权重
};
//优先队列默认是大根堆,本次使用的优先队列,队头元素是最小的,队里元素升序排列
struct cmp {
bool operator()(HTNode* a, HTNode* b){
// 定义的比较方法
//返回true 时,a的节点优先级比b的小
return a->weight > b->weight;
}
};
void PrintHuffman(HTNode *HuffmanTree); //输出哈夫曼树
HTNode* CreateHuffman(Wi a[],int n); //创建哈夫曼树
void HuffmanCode(HTNode* HuffmanTree,string codeStr);//哈夫曼编码
string HuffmanDecode(HTNode* huffmanTree,string codeStr);//哈夫曼解码
string HuffmanExpress(string txt);//压缩文本
#include "stdafx.h"
#include"huffman.h"
#include<iostream>
#include<queue>
#include<string>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
return 0;
}
string s[1000] = {""};
bool isLeave(HTNode* root);
HTNode* CreateHuffman(CharFreq charFreq[],int n) //创建哈夫曼树
{
int i,j;
HTNode* huffmanTree = nullptr; //根据n个权值声明n个二叉树的森林,二级指针表示森林(二叉树的集合)
priority_queue<HTNode*, vector<HTNode*>, cmp> trees;
//实现第一步,创建n颗二叉树,左右子树为空
for(int i = 0;i < n;i++){
HTNode* tree = (HTNode*)new HTNode;
tree->data = charFreq[i].first;
tree->weight = charFreq[i].second;
tree->left = tree->right= nullptr;
trees.push(tree);
}
for(int i = 1;i < n;i++){
//第二步,选择权值最小的根节点二叉树下标为第一个和第二个
HTNode* min1 = trees.top();
trees.pop();
//c++的优先队列,每次pop完以后,新的队头元素会覆盖原来的队头元素;队头指针没有变;
HTNode* min2 = trees.top();
trees.pop();
HTNode* newNode = new HTNode;
newNode->weight = min1->weight + min2->weight;
newNode->left = min1;
newNode->right = min2;
trees.push(newNode);
huffmanTree = newNode;
}
cout<< endl;
return huffmanTree;
}
//先序遍历哈夫曼树
void PrintHuffman(HTNode* huffmanTree){
if(huffmanTree == nullptr){
return;
}
cout<<huffmanTree->weight << " ";
if(huffmanTree->left != nullptr) PrintHuffman(huffmanTree->left);
if(huffmanTree->right != nullptr)PrintHuffman(huffmanTree->right);
}
void HuffmanCode(HTNode* huffmanTree,string codeStr) {
if(isLeave(huffmanTree)) {
s[huffmanTree->data] = codeStr;
return;
}
HuffmanCode(huffmanTree->left,codeStr+'0');
HuffmanCode(huffmanTree->right,codeStr+'1');
}
bool isLeave(HTNode* root) {
return (root != nullptr) &&(root->left == nullptr) && (root->right == nullptr);
}
string HuffmanDecode(HTNode* huffmanTree,string codeString) {
string res;
for(int i = 0;i < codeString.length();) {
if(codeString[i] == '\0'){
break;
}
HTNode* p = huffmanTree;
while(!isLeave(p)) {
if(i >= codeString.length()) break;
if(i < codeString.length() && codeString[i] == '0') p = p->left;
else if(i < codeString.length() && codeString[i] == '1') p = p->right;
i++;
}
res += p->data;
}
return res;
}
string HuffmanExpress(string txt) {
string res;
for(int i = 0;i < txt.length();i++) {
res += s[txt[i]];
}
return res;
}
int main(){
int n;
cin >> n;
CharFreq *charFreq = new CharFreq[n];
string codeStr = "";
for(int i = 0;i < n;i++) {
cin >> charFreq[i].first >> charFreq[i].second ;
}
HTNode* huffmanTree = CreateHuffman(charFreq,n);
PrintHuffman(huffmanTree);
cout << endl;
HuffmanCode(huffmanTree,codeStr);
for(int i = 0;i < n;i++){
cout <<charFreq[i].first << ":"<<s[charFreq[i].first]<<endl;
}
string decodeStr = HuffmanDecode(huffmanTree,"10011");
cout << decodeStr<< endl;
string txt = "abc";
cout<<HuffmanExpress(txt) << endl;
cin >> n;
}