构建哈夫曼树和权值计算
前言:哈夫曼树(最优二叉树)的笔记
到这里树的基本相关的数据结构都撸了一遍,接下来一个星期继续来撸图的结构,之前没有时间,现在有时间都来写一遍,为什么要写呢,我自己感觉其实还是跟逆向相关,因为有些东西数据结构会占比多,所以对经典的数据结构的了解,同样对逆向的水平会有长进!
哈夫曼树的构建比较简单,不过我查了相关的资料都是涉及到什么二叉堆的,我没有学过,按照自己的理解来创建了一棵哈夫曼树,同样能实现构建哈夫曼树和权值的计算
思路:
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 };
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异