霍夫曼树和霍夫曼编码

#include <stdio.h>
#include <stdlib.h>
#include <cstring>
using namespace std;

typedef struct HuffNode
{
	int weight;
	int parent, lchild, rchild;
}HuffNode, HuffTree;

void select(HuffTree* H, int m, int* s1, int* s2)
//在索引为0~m的元素中找到**parent为0**且权重最小的两个元素的索引s1,s2
{
	//初始化两个最小的元素min1,与min2, 且min1<min2
	int min1 = 500;
	int min2 = 1000;
	int min1_index, min2_index = 1000;
	for(int i = 0; i<=m; i++)
	{
		if(H[i].parent==0)    //这个条件很重要!!它使得前一次被选中的根节点在这次选择中不会被选中
		{
			if(H[i].weight < min1)  //则当前元素<min1<min2, 应将min2用min1赋值, 再将当前元素赋给min1
			{
			min2 = min1;
			min2_index = min1_index;
			min1 = H[i].weight;
			min1_index = i;
			continue;
			}
			if(H[i].weight < min2)   //则min1<当前元素<min2, 应将当前元素赋给min2
			{
			min2 = H[i].weight;
			min2_index = i;
			}
		}

	}
	*s1 = min1_index;
	*s2 = min2_index;

}

void display(HuffTree* H, int n)
{
	for(int i = 0; i<=n-1; i++)
	{
		printf("%d, weight:%d, parent:%d, lchild:%d, rchild:%d\n", i, H[i].weight, H[i].parent, H[i].lchild, H[i].rchild);
	}
}


void HuffmanCoding(int n, HuffTree* H, char** HuffCode, int w[])
{
	//n个叶子结点, n-1个非叶子结点.共2n-1个结点
	int m = 2*n-1;
	//为线性存储结构分配空间
	H = (HuffNode *)malloc(sizeof(HuffNode)*m);  
	HuffNode* p = H;
	int * p_w = w;
	//对前n个叶子结点,其权重等于w[]中的元素值
	for(int i = 0; i<=n-1; i++)
	{
		//*p = {*p_w, 0,0,0};//这句话的作用等价于下面四句:
		H[i].weight = *p_w;
		H[i].parent = 0;
		H[i].lchild = 0;
		H[i].rchild = 0;

		p++;
		p_w++;
	}

	//对后n-1个非叶子结点,其权重0
	for(int i = n; i<=m-1; i++)
	{
		//*p = {0,0,0,0};

		H[i].weight = 0;
		H[i].parent = 0;
		H[i].lchild = 0;
		H[i].rchild = 0;
		p++;
	}
	//对n-1个非叶子结点
	for(int i = n; i<=m-1; i++)
	{
		int s1, s2 = 0;
		select(H, i-1, &s1, &s2);//在前i-1个元素中找到parent为0且权重最小的两个元素的索引s1,s2
		H[i].lchild = s1;
		H[i].rchild = s2;
		H[i].weight = H[s1].weight + H[s2].weight;
		H[s1].parent = i;
		H[s2].parent = i;
		display(H, m);
	}

	display(H, m);

	//为二维霍夫曼编码结构分配空间, 共n个元素, 每个元素是一个char*类型的指针
	HuffCode = (char**)malloc(sizeof(char*)*(n));
    	if(!HuffCode)
		printf("error to malloc for HUffCode.");

	//为每一个字符编码首先预分配长度为n的空间,	
	char * codestring = (char*)malloc(sizeof(char)*n);
	codestring[n-1] = '\0';
	//从叶子结点到根逆向求每个字符的Huffmancode
	for(int i = 0; i<=n-1; i++)
	{
		int start_index = n-2;

		int c = i;   //initialize index of current node to index of the first leaf node
		int f = H[c].parent;  //initialize the inde of current parent
		while(f!=0)
		{
			if(H[f].lchild == c)
				codestring[start_index--] = '0';
			if(H[f].rchild == c)
				codestring[start_index--] = '1';
			c = f;
			f = H[c].parent;
		}

		//由于HuffCode的每一维都是一个指针, 因此, 这里对每个指针分配长度为n-1-start_index的空间
		HuffCode[i]=(char *)malloc((n-1-start_index)*sizeof(char));
		strcpy(HuffCode[i], &(codestring[start_index+1]));

		printf("code string[%d] is:%s\n",i, &(codestring[start_index+1]));
	}
	free(codestring);
	codestring=NULL;

}




int main()

{
	int w[] = {5,29,7,8,14,23,3,11};
	HuffTree H;
	char **HuffCode;
	HuffmanCoding(8, &H, HuffCode, w);
}

运行结果:


注意:

霍夫曼编码并不是唯一的,只要平均带权路径长度最小就OK.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值