构建哈夫曼树和权值计算

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

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

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

思路:

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 };

posted @   zpchcbd  阅读(1052)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
点击右上角即可分享
微信分享提示