【C++】哈夫曼树编码的实现(使用string)

本文介绍了一种使用C++实现的哈夫曼编码与解码的方法,通过构建哈夫曼树并生成对应的编码表,实现了对输入的英文字符串进行高效编码与解码的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

主要使用string,实现输入任意一串英文字符进行哈夫曼编码解码打印。

#include<iostream>
#include<string>
#include<iomanip>
using namespace std;

//静态三叉链表节点
struct HNode {
	int weight;//权重
	int parent;//双亲指针
	int LChild;//左孩子指针
	int RChild;//右孩子指针
};
//编码表节点
struct HCode {
	char data;
	string code;
};
//最小和次小选取
void Select(HNode* &HTree, int n, int &min1, int &min2) {
	struct TempNode {
		int tweight;//储存权重
		int p;//储存位置
	};
	TempNode *tempTree = new TempNode[n];
	int j = 0;
	for (int i = 0; i < n; i++) {
		if (HTree[i].parent == -1 && HTree->weight != 0) {
			tempTree[j].tweight = HTree[i].weight;
			tempTree[j].p = i;
			j++;
		}
	}//将HTree中无双亲的节点存储到tempTree中
	int m1 = 0, m2 = 0;
	for (int i = 0; i < j; i++) {
		if (tempTree[i].tweight < tempTree[m1].tweight)//不取等号,权值相等时m1取前面的
			m1 = i;
	}
	for (int i = 0; i < j; i++) {
		if (m1 == m2)
			m2++;//m1在位置1时,m2后移一位
		if (tempTree[i].tweight <= tempTree[m2].tweight)//取等号,权值相等时m2取后面的
			m2 = i;
	}
	min1 = tempTree[m1].p;
	min2 = tempTree[m2].p;
}
//建立哈夫曼树
void CreateHTree(HNode* &HTree, int weight[], int n) {
	HTree = new HNode[2 * n - 1];
	for (int i = 0; i < n; i++) {//根据权重初始化Huffman树
		HTree[i].weight = weight[i];
		HTree[i].LChild = -1;
		HTree[i].RChild = -1;
		HTree[i].parent = -1;
	}
	if (n <= 1)//错误处理
		throw"The data error,can not creat a huffman tree.";

	int min1, min2;
	for (int i = n; i < 2 * n - 1; i++) {
		Select(HTree, i, min1, min2);
		HTree[min1].parent = HTree[min2].parent = i;
		HTree[i].weight = HTree[min1].weight + HTree[min2].weight;
		HTree[i].LChild = min1;
		HTree[i].RChild = min2;
		HTree[i].parent = -1;
	}
	//输出哈夫曼树的表格形式
	cout << "The HuffmanTree is created." << endl;
	for (int i = 0; i < 2 * n - 1; i++) {
		cout << "┌" << "-----------------------" << "┐" << endl;
		cout << setiosflags(ios::left) << '[' << ' ' << setw(3) << i << "│" << ' ' << setw(3) << HTree[i].weight << "│" << ' ' << setw(3) << HTree[i].LChild << "│" << ' ' << setw(3) << HTree[i].RChild << "│" << ' ' << setw(3) << HTree[i].parent << ']' << endl;
		cout << "└" << "-----------------------" << "┘" << endl;

	}
}
//逆置编码函数
void Reverse(string &s) {
	int length = s.size();
	char temp;
	for (int i = 0; i < length / 2; i++) {
		temp = s[i];
		s[i] = s[length - i - 1];
		s[length - i - 1] = temp;
	}
}
//哈夫曼编码表
void CreateCodeTable(HNode* &HTree, HCode* &HCodeTable, string b, int n) {
	HCodeTable = new HCode[n];//生成编码表
	cout << "The code table is: " << endl;
	for (int i = 0; i < n; i++) {
		HCodeTable[i].data = b[i];
		int child = i;
		int parent = HTree[i].parent;
		int k = 0;
		while (parent != -1) {
			if (child == HTree[parent].LChild)
				HCodeTable[i].code += '0';
			else
				HCodeTable[i].code += '1';
			child = parent;
			parent = HTree[child].parent;
		}
		Reverse(HCodeTable[i].code);//逆置
									//输出编码表
		cout << "┌" << "------------" << "┐" << endl;
		cout << setiosflags(ios::left) << '[' << ' ' << setw(5) << HCodeTable[i].data << "│" << ' ' << setw(5) << HCodeTable[i].code << ']' << endl;//打印编码表
		cout << "└" << "------------" << "┘" << endl;
	}
	cout << endl << endl;
}
//编码
string Encode(HCode* &HCodeTable, string s, int n) {
	string encodedString;//编码串
	int length = s.size();
	for (int i = 0; i < length; i++) {
		for (int j = 0; j < n; j++) {
			if (s[i] == HCodeTable[j].data)
				encodedString += HCodeTable[j].code;
		}
	}
	return encodedString;
}
//解码
string Decode(HNode* &HTree, HCode* &HCodeTable, string s, int n) {
	string decodedString;
	int length = s.size();
	for (int i = 0; i<length; i++) {
		int parent = 2 * n - 1 - 1;//根节点在哈夫曼树中的下标
		int j = 0;
		while (HTree[parent].LChild != -1) {
			if (s[i + j] == '0')
				parent = HTree[parent].LChild;
			else
				parent = HTree[parent].RChild;
			j++;
		}
		i += j - 1;
		decodedString += HCodeTable[parent].data;
	}
	return decodedString;
}
//释放指针
void Delete(HNode* &HTree, HCode* &HCodeTable) {

	delete[]HTree;
	cout << "HTree is deleted." << endl;
	delete[]HCodeTable;
	cout << "HCodeTable is deleted." << endl;
}


int main() {
	cout << " please enter a string :" << endl;
	char a[100];
	cin.get(a, 100);
	char d[50] = { '\0' };//字符
	int w[50] = { 0 };//字符权值
	for (int i = 0; a[i] != '\0'; i++) {//统计输入字符
		for (int j = 0; j <= 50; j++) {
			if (j == 50) {//若d中不存在此字符,新存入
				int h = -1;
				while (w[++h] != 0);//寻找存入位置
				d[h] = a[i];
				w[h]++;
			}
			if (d[j] == a[i]) {
				w[j]++;
				break;
			}
		}
	}
	HNode *HTree;
	HCode *HCodeTable;
	string data, s;
	s = a;//输入字符串转为string
	int n = 0;//统计编码表中字符个数
	while (d[n] != '\0') {
		data += d[n];
		n++;
	}

	//测试部分
	CreateHTree(HTree, w, n);
	CreateCodeTable(HTree, HCodeTable, data, n);
	string encodeString;
	encodeString = Encode(HCodeTable, s, n);
	cout << "encode over:" << encodeString << endl;
	cout << "decode over:" << Decode(HTree, HCodeTable, encodeString, n) << endl;
	Delete(HTree, HCodeTable);//释放指针
	return 0;
}

结果:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值