哈弗曼树(顺序表实现)

带权路径最小的二叉树称为哈弗曼树。哈弗曼树是一棵二叉树。

由于哈弗曼树中没有度为1的结点,所以有n个叶子结点的哈弗曼树有2n-1个结点,可以存储在大小为2n-1的一维数组中。每个结点要包含结点的权重、双亲结点的信息、孩子结点的信息。

wightparentlchildrchild

                                                                                           哈弗曼树的结点形式

哈夫曼树的存储结构定义如下:

typedef struct{
	int weight;//结点的权重
	int parent, lchild, rchild;//结点的双亲,左孩子,右孩子下标 
}HTNode, *HuffmanTree;

 

哈夫曼树的构造算法及实现:

#include<stdio.h>
#include<stack> 
#define MAXSIZE 100
using namespace std;

typedef struct{
	int weight;//结点的权重
	int parent, lchild, rchild;//结点的双亲,左孩子,右孩子下标 
}HTNode, *HuffmanTree;

//当前森林中选择双亲为0且权值最小的两个树根结点s1,s2;
void SelectNode(HuffmanTree &HT, int t, int &s1, int &s2){
	int mins1=HT[t].weight;
	s1=t;
	int mins2=HT[t].weight;
	s2=t;
	for(int k=1;k<=t;k++){
		if(HT[k].weight<mins1 && HT[k].parent==0){
			mins1=HT[k].weight;
			s1=k;
		}
	}
	//HT[s1].parent=1;
	for(int k=1;k<=t;k++){
		if(HT[k].weight<mins2 && k!=s1 && HT[k].parent==0){
			mins2=HT[k].weight;
			s2=k;
		}
	}
} 

/*
哈弗曼树的构造步骤:
1.首先动态申请2n个存储单元,然后循环2n-1次,从1号单元开始,一次将1至2n-1所有单元中的
双亲、左孩子、右孩子的下标都初始化为0;最后循环n此,输入前n个单元中叶子结点的权重值;
2.循环n-1次,通过n-1次的选择、删除与合并来创建哈弗曼树。
选择是从当前森林中选择双亲为0且权值最小的两个树根结点s1,s2;
删除是指将s1,s2的双亲改为非0;
合并就是将s1,s2的权值之和作为新结点的权值一次存入数组的第n+1之后的单元中,同时记录这个
新结点左孩子的下标为s1,右孩子的下标为s2。 
*/ 
void CreateHuffmanTree(HuffmanTree &HT, int n){
	//构造哈弗曼树HT
	if(n<1){
		return;
	} 
	int m=2*n-1;
	//这里我们不使用数组的0号位,所以需要分配m+1个单元 
	HT=new HTNode[m+1];
	for(int i=1;i<=m;i++){
		HT[i].parent=0;
		HT[i].lchild=0;
		HT[i].rchild=0;
	}
	for(int i=1;i<=n;i++){
		printf("请输入第%d个叶子结点的权重:",i);
		scanf("%d", &HT[i].weight);
	}
	for(int i=n+1; i<=m; i++){
		//当前森林中选择双亲为0且权值最小的两个树根结点s1,s2
		int s1, s2;
		//在 HT[k] (1<=k<=i-1) 中选择两个其双亲域为 0 且权值最小的结点,并返回它们在 HT中的序号 s1 和 s2
		SelectNode(HT, i-1, s1, s2);
		//从森林中删除s1和s2,将s1和s2的结点的双亲置为i 
		HT[s1].parent=i;
		HT[s2].parent=i;
		//s1和s2分别作为HT[i]的左孩子和右孩子
		HT[i].lchild=s1;
		HT[i].rchild=s2;
		//i的权值为s1和s2权值之和 
		HT[i].weight=HT[s1].weight+HT[s2].weight; 
	}
} 

int main(){
	HuffmanTree HT;
	printf("请输入哈夫曼树叶子结点数:");
	int n;
	scanf("%d", &n);
	CreateHuffmanTree(HT, n);
	for(int i=1;i<=2*n;i++){
		printf("哈夫曼树各个结点的下标%d和权重%d:\n", i, HT[i].weight); 
	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值