哈夫曼树及编码


一、哈夫曼树的概念

1、哈夫曼树:假设有m个权值,可以构造一棵含n个叶子结点的二叉树,若该树的带权路径长度达到最小,则称这样的二叉树为哈夫曼树。
2、结点的带权路径长度:根节点到任意结点的路径长度与该节点的权值的乘积
3、路径长度:路径上的分支数目
4、树的带权路径长度:树中所有叶子结点的带权路径长度之和
在这里插入图片描述

离根结点越远,权值越小

二、相关功能实现

1、结构体的定义

typedef struct wordcnt{
   
     // 统计字符和对应的次数 
	char ch;
	int cnt = 0;
}Count;

typedef struct NumCount{
   
     // 统计次数的外部封装 
	Count count[MaxSize];
	int length = 0;
}NumCount;

typedef struct HTree{
   
     // 哈夫曼树结构 
	char data; 
	int weight;//结点的权值 
	int parent,lchild,rchild;//结点的双亲、左孩子和右孩子的下标 
}HTNode,*HuffmanTree; 

typedef struct HCode{
   
    // 编码结构 
	char data;
	char* str; 
}*HuffmanCode;

2、读入文件
将需要压缩的字符读入数组

void ReadData(char *source)
{
   
   
	//打开文件读入数据 
	ifstream infile;
	infile.open("in.txt");
	cout<<"Reading..."<<endl;
	cout<<"the input file is:"<<endl;
	infile.getline(source,MaxSize);
	cout<<source<<endl;
	infile.close();
	cout<<endl;
}

3、统计字符出现次数

void WordCount(char *data,NumCount *paraCnt)
{
   
   
	int flag;// 标识是否已经记录 
	int len = strlen(data);
	for(int i = 0;i < len;++i)
	{
   
   
		flag = 0;
		for(int j = 0;j < paraCnt->length;++j)
		{
   
   
			if(paraCnt->count[j].ch == data[i]) // 若已有记录,直接++ 
			{
   
   
				++paraCnt->count[j].cnt;
				flag = 1;
				break;
			}
			
		}
		if(!flag)//没有记录,则新增 
		{
   
   
			paraCnt->count[paraCnt->length].ch = data[i];
			++paraCnt->count[paraCnt->length].cnt;
			++paraCnt->length;
		}
	}
}

4、展示次数

void Show(NumCount *paraCnt)
{
   
   
	cout<<"the length is "<<paraCnt->length<<endl;
	for(int i = 0;i < paraCnt->length;++i)
	{
   
   
		cout<<"The character "<<paraCnt->count[i].ch<<"  appears  "<<paraCnt->count[i].cnt<<endl;
	}
	cout<<endl;
}

5、选择权重最小的两个节点

void select(HuffmanTree HT,int top,int *s1,int *s2)
{
   
   
	int min = INT_MAX;
	for(int i = 1;i <= top;++i)  // 选择没有双亲的节点中,权重最小的节点 
	{
   
   
		if(HT[i].weight < min && HT[i].parent == 0)
		{
   
   
			min = HT[i].weight;
			*s1 = i;
		}
	}
	
	min = INT_MAX;
	for(int i = 1;i <= top;++i)  // 选择没有双亲的节点中,权重次小的节点 
	{
   
   
		if(HT[i].weight < min && i != *s1 && HT[i].parent == 0)
		{
   
   
			min = HT[i].weight;
			*s2 = i;
		}
	}	
}

6、创建哈夫曼树
(1)根据给定的n个权值{W1, W2,…, Wn},构造n棵只有根结点的二叉树,这n棵二叉树构成一个森林 F。

(2)在森林F中选取两棵根结点的权值最小的树作为左右子树构造一棵新的二叉树,且置新的二叉树的根结点的权值为其左、右子树上根结点的权值之和。

(3)在森林F中删除这两棵树,同时将新得到的二叉树加入F中。

(4)重复(2)和(3),直到F只含一棵树为止。这棵树便是哈夫曼树。

void CreateHuffmanTree(HuffmanTree &HT,int length,NumCount cntarray)
{
   
   
	if
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小白123**

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值