[数据结构]哈夫曼编码树 编码 解码

学习记录~

#include<iostream>
#include<ctime>
#include<cmath>
using namespace std;


typedef char ElemType;
struct HfNode
{
	int weight;
	int lchild, rchild, parent;
	ElemType data;
	ElemType* hc;
};
class HuffManTree
{
private:
	HfNode* root;
	int num;
	
	void Select(int n, int& i1, int& i2);
public:
	HuffManTree(int* w,ElemType c[], int n);
	void PrintfHfmanTree();
	void GreatHuffManCode();
	void DeCoding(char *c);
	void PrintfHfCode();
};
int main()
{
	int w[] = { 35,25,15,15,10};
	char p[] = "110110100100100001010111";
	ElemType c[] = { 'A','B','C','D','E'};
	HuffManTree h(w,c, 5);
	cout << "哈夫曼编码树为\n";
	h.PrintfHfmanTree();
	cout << endl;
	h.GreatHuffManCode();
	cout << "字符编码表为\n";
	h.PrintfHfCode();
	cout << "对以下编码串进行解码为\n";
	cout << p << endl;
	h.DeCoding(p);
	return 0;
}

void HuffManTree::Select(int n, int& i1, int& i2)
{
	int i;
	for (i = 0; i < n; i++)
	{
		if (root[i].parent == -1)
		{
			i1 = i;
			break;
		}
	}
	for (i = 0; i < n; i++)
	{
		if (root[i].parent == -1 && root[i].weight < root[i1].weight)
		{
			i1 = i;
		}
	}
	for (i = 0; i < n; i++)
	{
		if (root[i].parent == -1 && i != i1)
		{
			i2 = i;
			break;
		}
	}
	for (i = 0; i < n; i++)
	{
		if (root[i].parent == -1 && root[i].weight < root[i2].weight && i1 != i)
			i2 = i;
	}
}

HuffManTree::HuffManTree(int* w,ElemType c[], int n)
{
	int i,i1,i2;
	root = new HfNode[2 * n - 1];
	num = n;
	for (i = 0; i < 2 * n-1; i++)
		root[i].lchild = root[i].parent = root[i].rchild = -1;
	for (i = 0; i < num; i++)
	{
		root[i].weight = w[i];
		root[i].data = c[i];
	}
		
	for (i = num; i < 2 * num - 1; i++)
	{
		Select(i, i1, i2);
		root[i].weight = root[i1].weight + root[i2].weight;
		root[i].lchild = i1; root[i].rchild = i2;
		root[i1].parent = i; root[i2].parent = i;
	}
}

void HuffManTree::PrintfHfmanTree()
{
	for (int i = 0; i < 2 * num - 1; i++)
	{
		cout << i << " ";
		if(i>=0&&i<num)
		cout << root[i].data << " ";
		if (i >=num)
			cout << "  ";
		cout << root[i].weight << " " << root[i].parent << " ";
		cout << root[i].lchild << " " << root[i].rchild << endl;
	}
}

void HuffManTree::GreatHuffManCode()
{
	int i;
	for(i=0;i<num;i++)
		root[i].hc = new ElemType[num];
	ElemType* cd = new ElemType[num];
	cd[num-1] = 0;
	int start,f,c;
	for (i = 0; i < num; i++)
	{
		start = num - 1;
		c = i;//当前结点下标
		f = root[i].parent;//双亲下标
		while (f != -1)
		{
			--start;
			if (root[f].lchild == c)cd[start] = '0';
			else cd[start] = '1';
			c = f; f = root[f].parent;
		}
		strcpy(root[i].hc,&cd[start]);
	}
	delete cd;
}

void HuffManTree::DeCoding(char *c)
{
	int i = 0,j=0;
	while (c[i])
	{
		j = 2*num-1-1;//每次从根结点开始j表示下表
		while (root[j].lchild != -1 || root[j].rchild != -1)
		{
			if (c[i] == '0')
			{
				j = root[j].lchild; i++;
			}
			else
			{
				j = root[j].rchild; i++;
			}
		}
		cout << root[j].data;
	}
}

void HuffManTree::PrintfHfCode()
{
	for (int i = 0; i < num; i++)
	{
		cout << i << " ";
		cout << root[i].data << " " << root[i].weight << " ";
		cout << root[i].hc << endl;
	}
}

 

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编码是一种用于数据压缩的方法,它基于字符出现频率来构建最优的编码表。下面是哈编码的译码和编码过程: 1. 哈编码: - 统计字符出现频率,并根据频率构建哈。频率较高的字符位于的较低层。 - 通过从根到叶子节点的路径上的0和1来表示字符,构建编码表。 - 使用编码表将输入文本中的字符替换为对应的哈编码。 2. 哈译码: - 使用相同的哈编码表,读取编码后的二进制数据。 - 从根节点开始,按照读取到的0或1依次向左或向右移动,直到达到叶子节点。每次到达叶子节点后,输出对应的字符,并重新回到根节点继续读取。 下面是一个示例,展示如何使用哈编码和译码来进行数据压缩和解压缩: 假设我们有以下文本:C知道 编程是很有趣的! 1. 统计字符频率并构建哈: 字符频率:{空格: 4, C: 2, 知: 2, !: 1, 程: 1, 译: 1, 是: 1, 有: 1, 趣: 1, 的: 1, 编: 1, 码: 1} 构建的哈如下: [11] / \ / \ / \ / \ / \ / \ / \ C 知 ␣ ! 程 译 \ \ / \ 是 有 \ \ \ / \ 趣 的 构建的编码表如下: C: 00 知: 01 ␣: 100 !: 1010 程: 1011 译: 1100 是: 11010 有: 11011 趣: 11100 的: 11110 编: 111110 码: 111111 2. 编码: 将输入文本中的字符替换为对应的哈编码,得到编码后的二进制数据:00 01 100 111110 1011 1100 11010 11011 11100! 3. 解码: 根据相同的哈编码表,读取编码后的二进制数据进行译码,得到原始文本:C知道 编程是很有趣的!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值