哈夫曼树

目录

基本概念

算法实现

一.哈夫曼树的构成

二.创建哈夫曼树

 三.为哈夫曼树编码


基本概念

1、权:赋予某个实体的一个量
2、路径:从树中的一个结点到另一个结点之间的分支构成这两个结点间的路径

1)路径长度:路径上的分支数                
2)树的路径长度:从树根到每个结点的路径长度之和

 3)结点的带权路径长度:从该结点到树根之间的路径长度与结点上权的乘积
 4)树的带权路径长度:树中所有带权结点的路径长度之和

3、哈夫曼树:带权路径长度最小的树
 

算法实现

一.哈夫曼树的构成

一棵有n个叶子结点的哈夫曼树中,度为2的结点有n-1个,则共有2n-1个,可以用大小为2n-1的一维数组来存储

每个数组元素是这样的结构体:

 结构体  

typedef struct HuffmanTreeNode {
	int lChild, rChlid, parent;  
	int weight;		
}*HuffmanTree;

二.创建哈夫曼树

1.初始化 

1)为HT开辟2n-1(total)个存储单元 

 2)初始化每个单元,0~n个单元,左右孩子、双亲初始化为-1,第 i 个的权值为传进来的数组元素weight[i]       

 n~total个单元,左右孩子、双亲初始化为-1,第 i 个的权值为0

2.创建树

n~total是新添加的数,在n~total循环,把其前边最小的数和第二小的数变成它的左右孩子下标,左右孩子的parent下标变成它的下标,它的权值为左右孩子之和

void CreatHuffmanTree(HuffmanTree& HT, int* weight, int n) {
	int total = 2 * n - 1;    //remember
	HT = new HuffmanTreeNode[total];  //给传进来的赫夫曼树分配空间,一共有total个结构体
	if (!HT)
		exit(OVERFLOW);
	//给每个结构体初始化
	for (int i = 0; i < n; i++) {
		HT[i].lChild = HT[i].rChlid = HT[i].parent = -1;
		HT[i].weight = weight[i];
	}
	for (int i = n; i < total; i++) {
		HT[i].lChild = HT[i].rChlid = HT[i].parent = -1;
		HT[i].weight = 0;
	}
	for (int i = n; i < total; i++) {
		//先找的min1,所以min1一定是小于min2的,它在前边
		int min1 = Min(HT, i);
		int min2 = Min(HT, i);

		HT[min1].parent = HT[min2].parent = i;
		//给HT[i]的各种成员赋值
		HT[i].weight = HT[min1].weight + HT[min2].weight;
		HT[i].lChild = min1;
		HT[i].rChlid = min2;
	}
}

 三.为哈夫曼树编码

1、基本思想:概率大的字母用短码,小的用长码,构造哈夫曼树,概率越大,路径越短。
2、哈夫曼编码:在哈夫曼的每个分支上标上0或1
——结点的左分支标0,右分支标1
——把从根到每个叶子的路径上的标号连接起来,构成一个二进制串,该二进制串就成为该叶子代表的哈夫曼编码

编码

1)二维数组code存放n个叶结点的编码 

2)tempCoding是一个在结尾放了空字符的临时字符串指针

3)从0~n,cur为当前数据的下标,parent为其双亲,start用于指向编码在tempCoding中的位置,初始时指向最后一个(n-1)

4)当不是根结点时,左0右1进行赋值,再把当前数据改为其双亲数据,继续向上编码

5)tempCoding+start是当前开始有编码的位置,把编码copy给code[i]

void HuffmanCoding(HuffmanTree T, char**& code, int n) {
	code = new char* [n];
	if (!code)
		exit(OVERFLOW);
	char* tempCoding = (char*)malloc(n * sizeof(char));
	if (!tempCoding)
		exit(OVERFLOW);
	tempCoding[n - 1] = '\0';

	for (int i = 0; i < n; i++) {
		int cur = i;
		int parent = T[i].parent;
		int start = n - 1;
		//当未到根结点时
		while (parent != -1) {
			//左0右1
			if (T[parent].lChild == cur)
				tempCoding[--start] = '0';
			else if (T[parent].rChlid == cur)
				tempCoding[--start] = '1';
			cur = parent;
			parent = T[cur].parent;
		}
		code[i] = (char*)malloc((n - start) * sizeof(char));
		if (!code[i])
			exit(OVERFLOW);
		strcpy(code[i], tempCoding + start);
	}
	for (int i = 0; i < n; i++)
		cout << code[i] << endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值