数据结构-哈弗曼树的创建

  1. 哈弗曼树的创建
  2. 带权路径长度的计算
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include <iomanip>
using namespace std;

typedef struct{
	//定义节点的结构体 
	int weight;//权重 
	int parent, lChild, rChild;//双亲节点的下标、左孩子下标、右孩子下标 
}HTNode, *HuffmanTree;

//选择所有节点中权重最小的两个节点的下标 
void SelectMin(HuffmanTree hT, int n, int &s1, int &s2)
{
	s1 = s2 = 0;
	int i;
	for(i = 1; i < n; i++)
	{
		// 首先找到两个没有双亲节点的节点下标 
		if(hT[i].parent == 0)
		{
			if(0 == s1)
			{
	            s1 = i;
	        }
	        else
			{
				s2 = i;
				break;
			}
		}
	}
	if(hT[s1].weight > hT[s2].weight) 
	{
		// 保证s1所指节点的权重小于s2所指节点的权重 
		int t = s1;
		s1 = s2;
		s2 = t;
	}
	for(i+=1; i < n; i++)
	{
		if(hT[i].parent == 0)
		{
			/*
				遍历没有双亲节点的所有节点
				找到的节点权重如果比s1所指节点权重小,则更新s1节点让其指向当前节点
				保证s1指向的权重最小的节点 
			*/ 
			if(hT[i].weight < hT[s1].weight)
			{
				s2 = s1;
				s1 = i;
			}
			else if(hT[i].weight < hT[s2].weight)
			{
				/*
					如果当前节点的权重大于s1所指节点的权重,但是小于s2所指节点的权重
					那么更新s2节点,让其指向当前节点
					保证s2指向的除了s1之外最小的节点 
				*/ 
				s2 = i; 
			}
		}
	}
}

void CreateHuffmanTree(HuffmanTree &ht)
{
	// 8 5 29 7 8 14 23 3 11
	
	// n:表示要构造的哈夫曼树的叶子节点个数 
	// m:表示所有节点的个数 
	int n, m;
	// 输入叶子节点的个数 
	cin>>n; 
	m = 2 * n - 1; 
	// 构造m+1个节点,其中下标为0的不用 
	ht = (HuffmanTree)malloc((m+1) * sizeof(HTNode));
	for(int i = 1; i <= m; i++)
	{
		/*
			初始化所有节点的孩子节点和双亲节点为0 
		*/ 
		ht[i].parent = 0;
		ht[i].lChild = 0;
		ht[i].rChild = 0;
	 } 
	 for(int i = 1; i <= n; i++)
	 {
	 	cin>>ht[i].weight;
	 }
	 // 第一个节点的权重存储所有节点的个数 
	 ht[0].weight = m;
	 
	 /***********初始化完成,开始构建哈夫曼树**********/
	 for(int i = n + 1; i <= m; i++)
	 {
	 	// i表示现已有节点个数+1 ,新合成的节点就放在i的位置上 
	 	int s1, s2;
	 	SelectMin(ht, i, s1, s2);
	 	
	 	/*
		 	s1和s2所指节点构成新的节点放在i的位置上
			更新i的左孩子为s1,右孩子为s2,权重为s1的权重加上s2的权重 
			更新s1和s2的双亲节点为i 	
		*/ 
	 	ht[s1].parent = ht[s2].parent = i; 
		ht[i].lChild = s1;
		ht[i].rChild = s2;
		ht[i].weight = ht[s1].weight + ht[s2].weight; 
	 }
}

int HuffmanTreeWPL_(HuffmanTree hT, int i, int deepth) 
{
	/*
		递归计算某个节点的带权路径 
	*/ 
	if(hT[i].lChild == 0 && hT[i].rChild == 0)
	{
		return hT[i].weight * deepth;
	}
	else
	{
		return HuffmanTreeWPL_(hT, hT[i].lChild, deepth+1) + HuffmanTreeWPL_(hT, hT[i].rChild, deepth+1) ;
	}
}
int HuffmanTreeWPL(HuffmanTree hT)
{
	// 返回整棵树的带权路径长度 WPL 
    return HuffmanTreeWPL_(hT, hT[0].weight, 0);
}
void Print(HuffmanTree hT)
{
    cout << "index weight parent lChild rChild" << endl;
    cout << left;    // 左对齐输出 
    for(int i = 1, m = hT[0].weight; i <= m; ++ i){
    	//setw()函数表示固定输出字符的长度 
        cout << setw(5) << i << " ";
        cout << setw(6) << hT[i].weight << " ";
        cout << setw(6) << hT[i].parent << " ";
        cout << setw(6) << hT[i].lChild << " ";
        cout << setw(6) << hT[i].rChild << endl;
    }
}
void DestoryHuffmanTree(HuffmanTree &hT)
{
	//销毁哈夫曼树 
    free(hT);
}
int main()
{
    HuffmanTree hT;
    CreateHuffmanTree(hT);
    Print(hT); 
    cout << "WPL = " << HuffmanTreeWPL(hT) << endl;
    DestoryHuffmanTree(hT);
    return 0;	
}

 

运行结果如下:

《数据结构-哈弗曼树的创建》

参考:https://blog.csdn.net/luoluozlb/article/details/52122874

    原文作者:哈夫曼树
    原文地址: https://blog.csdn.net/LiuKe369/article/details/81294599
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞