构建哈夫曼树和权值计算


前言:哈夫曼树(最优二叉树)的笔记

到这里树的基本相关的数据结构都撸了一遍,接下来一个星期继续来撸图的结构,之前没有时间,现在有时间都来写一遍,为什么要写呢,我自己感觉其实还是跟逆向相关,因为有些东西数据结构会占比多,所以对经典的数据结构的了解,同样对逆向的水平会有长进!

哈夫曼树的构建比较简单,不过我查了相关的资料都是涉及到什么二叉堆的,我没有学过,按照自己的理解来创建了一棵哈夫曼树,同样能实现构建哈夫曼树和权值的计算

思路:

1、在两个节点每次创建父节点的时候,都事先先进行排序一次,然后再进行闯将

2、创建完的父节点重新插入到节点数组中,然后一次进行这两步即可

对于权值的计算,其实主要需要知道路径的条数(其实也就是树的高度),并且权值的计算都是针对于叶子节点的,所以我的想法就是递归把计算计算出来即可,然后通过标志来区分是否是叶子节点即可进行相关树的权值

代码实现如下

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define OK 1
#define ERROR 0
/*
@author zpchcbd
@time 2022.4.07
实现哈夫曼树
*/
typedef int ElemType;
typedef int Status;
typedef struct _TreeNode{
	struct _TreeNode* pLeftTreeNode;
	struct _TreeNode* pRightTreeNode;
	ElemType weightValue;
	ElemType flag;
	struct _TreeNode* parent;
}TreeNode, *PTreeNode;

// 排序
void sortNodeArray(TreeNode* iArray[], int m)
{
	int i = 0, j = 0;
	TreeNode* tmp = 0;
	for (i = 0;i<m-1;i++)
	{
		for (j = 0; j<m-i-1; j++)
		{
			if (iArray[j]->weightValue < iArray[j+1]->weightValue)
			{
				tmp = iArray[j];
				iArray[j] = iArray[j + 1];
				iArray[j + 1] = tmp;
			}
		}
	}
	
	for (i = 0; i< m; i++)
		printf("%d ", iArray[i]->weightValue);
	printf("\n");
}

// 计算树中的带权路径长度
ElemType getAllWeight(TreeNode* pTreeNode, ElemType iHeight)
{
	int iLength = 0;
	if (pTreeNode!=NULL)
	{
		printf("%d ", pTreeNode->weightValue);
		iLength += getLength(pTreeNode->pLeftTreeNode, iHeight + 1);
		iLength += getLength(pTreeNode->pRightTreeNode, iHeight + 1);
		if (pTreeNode->flag == 1 || pTreeNode->flag == 0)
		{
			iLength += pTreeNode->weightValue*iHeight;
		}
	}
	return iLength;
}

TreeNode* createHuffmanTreeNode(TreeNode* pT1, TreeNode* pT2)
{
	TreeNode* pTreeNode = NULL;
	if (pTreeNode == NULL)
	{
		pTreeNode = malloc(sizeof(TreeNode));
		pTreeNode->pLeftTreeNode = NULL;
		pTreeNode->pRightTreeNode = NULL;
		pTreeNode->weightValue = 0;
		pTreeNode->flag = -1;
		if (pTreeNode == NULL)
			return NULL;
	}
	if (pT1->weightValue < pT2->weightValue)
	{
		pTreeNode->pLeftTreeNode = pT1;
		pTreeNode->pRightTreeNode = pT2;
		if (pT1->flag == 2)
			pT1->flag = 0;
		if (pT2->flag == 2)
			pT2->flag = 1;
	}
	else
	{
		pTreeNode->pRightTreeNode = pT2;
		pTreeNode->pLeftTreeNode = pT1;
		if (pT2->flag == 2)
			pT2->flag = 0;
		if (pT1->flag == 2)
			pT1->flag = 1;
	}
	pT1->parent = pTreeNode;
	pT2->parent = pTreeNode;
	// 新建的节点的value是左节点右节点的value之和
	pTreeNode->weightValue = pT1->weightValue + pT2->weightValue;
	return pTreeNode;
}

int main()
{
	TreeNode* pTreeNode = NULL;
	TreeNode* pTreeNodeArray[7] = { 0 };
	ElemType pNodeValue[5] = { 1,2,3,4,5 };
	int i, j;
	// 初始化完降序排列的栈,该栈中保存的都是TreeNode节点
	for (i = 0;i<5;i++)
	{
		pTreeNodeArray[i] = malloc(sizeof(TreeNode));
		pTreeNodeArray[i]->weightValue = pNodeValue[i];
		pTreeNodeArray[i]->pLeftTreeNode = NULL;
		pTreeNodeArray[i]->pRightTreeNode = NULL;
		pTreeNodeArray[i]->flag = 2;
	}
	
	sortNodeArray(pTreeNodeArray, i);
	for (j = 4; j >= 0; j--)
	{
		pTreeNode = createHuffmanTreeNode(pTreeNodeArray[j], pTreeNodeArray[j - 1]);
		pTreeNodeArray[j] = pTreeNodeArray[j - 1] = NULL;
		pTreeNodeArray[j - 1] = pTreeNode;
		sortNodeArray(pTreeNodeArray, j);
		if (pTreeNodeArray[1] == NULL)
			break;
	}
	printf("=======preOrer=======\n");
	//preOrder(pTreeNodeArray[0]);
	printf("--%d--", getAllWeight(pTreeNodeArray[0], 0));
	return 0;
}

测试数据:ElemType pNodeValue[5] = { 1,2,3,4,5 };


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM