最优二叉树哈夫曼树

哈夫曼树的定义:

哈夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点的层数}。树的路径长度是从树根到每一结点的路径长度之和,记为WPL = (W1*L1+W2*L2+W3*L3+…+Wn*Ln),N个权值Wi(i=1,2,…n)构成一棵有N个叶结点的二叉树,相应的叶结点的路径长度为Li(i=1,2,…n)。可以证明哈夫曼树的WPL是最小的。

构建哈夫曼树:

 

代码实现:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct hnode {
	int weight; // 权重
	int parent;
	int lchild;
	int rchild; 
}HuffmanTree, *HuffmanTreePtr;
typedef char** HuffmanCode;
 
// 选择权值最小的两个下标 
void Select(HuffmanTreePtr HT, int len, int &s1, int &s2) {
	int min1 = 32367;
	int min2 = 32367;
	int i;
	for(i = 1; i <= len; i ++) {
		if(HT[i].weight < min1 && HT[i].parent == 0) {
			s2 = s1;
			min2 = min1;
			min1 = HT[i].weight;
			s1 = i;
		}else if(HT[i].weight < min2 && HT[i].parent == 0) {
			s2 = i;
			min2 = HT[i].weight;
		}
	}
}
 
// 创建哈夫曼树 
void CreatHuffman_Tree(HuffmanTreePtr &HT, int n) {
	int m = 2 * n - 1; // 节点总数
	int s1 = 0, s2 = 0; // 对应节点的下标
	int i;
	HT = (HuffmanTreePtr)malloc(sizeof(HuffmanTree) * (m + 1));
	for(i = 1; i <= n; i ++) { // 0号设为哨兵 
		scanf("%d", &HT[i].weight);
		HT[i].parent = 0;
		HT[i].lchild = 0;
		HT[i].rchild = 0; 
	} // 初始化 
	
	for(i = n + 1; i <= m; i ++) {
		HT[i].parent = 0;
		HT[i].lchild = 0;
		HT[i].rchild = 0;
	} // 初始化 
	
	for(i = n + 1; i <=m; i ++) {
		Select(HT, i - 1, s1, s2);
		HT[s1].parent = HT[s2].parent = i;
		HT[i].lchild = s1;
		HT[i].rchild = s2;
		HT[i].weight = HT[s1].weight + HT[s2].weight;
		
		// 跟踪代码 
		printf("%d 和 %d 的parent是%d\r\n", s1, s2, i);
		printf("%d 的权值是%d\r\n", s1, HT[s1].weight);
		printf("%d 的权值是%d\r\n", s2, HT[s2].weight);
		printf("%d 的权值是%d\r\n", i, HT[i].weight);
	}
}
 
 
// 进行哈夫曼编码 
void Huffman_Code(HuffmanTreePtr HT, HuffmanCode &HC, int n) {
	int i, k, m;
	char* code; // 临时储存编码
	HC = (HuffmanCode)malloc(sizeof(char*) * (n + 1));
	code = (char*)malloc(sizeof(char) * n);
	code[n - 1] = '\0';
	for(i = 1; i <= n; i ++) {
		k = n -1;
		m = i;
		while(HT[m].parent != 0) {
			k --;
			if(HT[HT[m].parent].lchild == m) {
				code[k] = '0';
			}else if(HT[HT[m].parent].rchild == m) {
				code[k] = '1';
			}
			m = HT[m].parent;
		}
		HC[i] = (char*)malloc(sizeof(char) * (n - k));
		strcpy(HC[i], &code[k]);
	} 
}
int main() {
	int n; // 节点数
	scanf("%d", &n);
	HuffmanTreePtr HT;
	HuffmanCode HC;
	CreatHuffman_Tree(HT, n);
	Huffman_Code(HT, HC, n);
	for(int i = 1; i <= n; i ++) {
		printf("%d 的编码是%s\r\n", i, HC[i]);
	}
	return 0;
}

运行结果:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值