news 2026/9/24 1:39:02

哈夫曼树的实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
哈夫曼树的实现

HuffmanTree.h

#ifndef HUFFMAN_TREE_H #define HUFFMAN_TREE_H /* Huffman树通过待编码的节点数量,计算出总共的节点个数 m = 2*n -1个 * 用数组0的单元表示无效节点,从1号单元开始进行填充,那么申请2*n个空间 */ typedef struct { int weight; // 节点的权值 int parent; // 该节点的父节点编号,0值表示该节点就是根 int lChild, rChild; // 指向该节点的左右孩子节点的编号 } HuffmanNode, *HuffmanTree; HuffmanTree createHuffmanTree(const int *w, int n); void releaseHuffmanTree(HuffmanTree tree); /* Huffman编码,用一个字符数组空间来保存每个符号的编码字符串 * char *codes[n]; HuffmanCode codes[n]; */ typedef char *HuffmanCode; HuffmanCode *createHuffmanCodes(HuffmanTree tree, int n); void releaseHuffmanCodes(HuffmanCode *codes, int n); #endif //HUFFMAN_TREE_H

HuffmanTree.c

#include <stdio.h> #include <stdlib.h> #include <string.h> #include "HuffmanTree.h" static void selectTwoMin(HuffmanTree tree, int n, int *s1, int *s2) { *s1 = *s2 = 0; for (int i = 1; i <= n; ++i) { if (tree[i].parent == 0) { if (*s1 == 0) { *s1 = i; } else if (*s2 == 0) { *s2 = i; if (tree[*s1].weight > tree[*s2].weight) { int t = *s1; *s1 = *s2; *s2 = t; } } else { // 比较权值大小,更新最小的2个节点下标 if (tree[i].weight < tree[*s1].weight) { *s2 = *s1; *s1 = i; } else if (tree[i].weight < tree[*s2].weight) { *s2 = i; } } } } } HuffmanTree createHuffmanTree(const int *w, int n) { int m = 2*n - 1; // 1. 申请2n个空间,预留一个0号位置 HuffmanTree tree = malloc(sizeof(HuffmanNode) * (m + 1)); if (tree == NULL) { return NULL; } // 2.1 初始化1 ~ 2n - 1个节点 for (int i = 1; i <= m; ++i) { tree[i].parent = tree[i].lChild = tree[i].rChild = 0; tree[i].weight = 0; } // 2.2 初始化权值 1 ~ n for (int i = 1; i <= n; ++i) { tree[i].weight = w[i - 1]; } // 初始化结束,开始构建HuffmanTree // 填充从n+1下标到m下标的空间 int s1, s2; // 没有parent约束的两个最小的权值 for (int i = n + 1; i <= m; ++i) { // 在[1...i-1]范围内,父节点为0,权值最小的两个 selectTwoMin(tree, i - 1, &s1, &s2); // 将这2个权值最小的节点,组合到第i个位置 tree[s1].parent = tree[s2].parent = i; tree[i].lChild = s1; tree[i].rChild = s2; tree[i].weight = tree[s1].weight + tree[s2].weight; } return tree; } void releaseHuffmanTree(HuffmanTree tree) { if (tree) { free(tree); } } // 从n个叶子节点找到根节点,逆向求每个叶子的对应的编码 HuffmanCode* createHuffmanCodes(HuffmanTree tree, int n) { // 申请了一个数组空间,每个元素都保存一个地址,这个地址指向了对应元素的编码结果 HuffmanCode* codes = malloc(sizeof(HuffmanCode) * n); if (codes == NULL) { return NULL; } memset(codes, 0, sizeof(HuffmanCode) * n); // 生成每个符号对应的编码结果 // n个节点,树的高度最大为n,而HuffmanTree要低于任意树的最大值 char *temp = malloc(sizeof(char) * (n + 1)); for (int i = 1; i <= n; ++i) { int start = n - 1; // 标识temp空间的编码起始位置,从后往前编码,编码临时结果从后往前 temp[start] = '\0'; int pos = i; // 当前正在编码的位置 int p = tree[i].parent; // 存放当前节点的父节点信息 while (p) { --start; temp[start] = (tree[p].lChild == pos) ? '0' : '1'; pos = p; p = tree[p].parent; } // 将第i个字符编码进行填充 codes[i - 1] = malloc(sizeof(char) * (n - start)); strcpy(codes[i - 1], &temp[start]); } free(temp); return codes; } void releaseHuffmanCodes(HuffmanCode*codes, int n) { if (codes) { for (int i = 0; i < n; ++i) { if (codes[i]) { free(codes[i]); } } free(codes); } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/24 1:34:26

魔百盒CM311-5短接强刷救砖全攻略:从原理到实操

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/24 1:30:05

校园网IPv4/IPv6平滑过渡三大实战方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/24 1:24:53

agent科研方向前沿探索与应用实践研究

每次找到心仪的外国文献&#xff0c;却被付费墙冷冷地挡在外面&#xff0c;是不是感觉科研的热情瞬间被浇灭&#xff1f;作为学生党&#xff0c;我太懂这种无力感了。但好消息是&#xff0c;通过几个合法且免费的“通道”和技巧&#xff0c;我们完全能实现“文献自由”。今天分…

作者头像 李华
网站建设 2026/9/24 1:19:42

户外监控摄像头起雾结露怎么办?电解除湿膜全天候控湿方案解析

一、户外监控的隐形敌人&#xff1a;内部起雾与凝露智慧城市建设推进至今&#xff0c;户外监控探头已经遍布道路、园区、山区、海岸。但一线运维人员都清楚一个顽疾 ——摄像头内部起雾。昼夜温差大、雨雾频繁的环境下&#xff0c;密闭的摄像头防护罩内极易产生结露。水汽附着在…

作者头像 李华