哈夫曼树实现

利用了优先队列,实现了对哈夫曼树的创建,基于已经建好的哈夫曼树,对其进行编码,解码。
算法步骤:
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;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值