pytest 在 CI 环境中的自动检测与短摘要输出行为详解
2026/9/15 20:15:36
一、哈夫曼树译码函数(Decoding)
该函数通过哈夫曼编码串和已构建的哈夫曼树,还原出原始字符序列。其核心逻辑如下:
2*n - 1,其中n是叶子节点数量)。'0',则跳转到当前节点的左孩子;'1',则跳转到当前节点的右孩子。示例代码(C语言风格结构体与数组实现):
#include<stdio.h>#include<string.h>#defineMAX_NODE100typedefstruct{charch;// 存储字符intweight;// 权重intparent,lchild,rchild;// 双亲、左孩子、右孩子下标}HTNode;voidHuffmanDecode(HTNode ht[],introot,char*code,intn){inti=0;intcurrent=root;intlen=strlen(code);while(i<len){if(code[i]=='0'){current=ht[current].lchild;// 走左子树}elseif(code[i]=='1'){current=ht[current].rchild;// 走右子树}// 判断是否为叶子节点(左右孩子都为0)if(ht[current].lchild==0&&ht[current].rchild==0){printf("%c",ht[current].ch);// 输出对应字符current=root;// 回到根节点}i++;}printf("\n");}二、树的存储结构
双亲表示法:
孩子表示法:
孩子兄弟表示法(左孩子-右兄弟表示法):
这些存储方式广泛应用于数据压缩(如哈夫曼编码)、操作系统目录管理、编译器语法树构建等领域。
构建哈夫曼树并生成编码表是数据压缩中的核心步骤,主要包括两个阶段:建树和编码生成。以下是详细过程与实现方法。
采用贪心算法,每次从所有节点中选取权值最小的两个节点,合并成一个新的内部节点,其权值为两者之和,直到只剩一棵树。
使用结构体数组HTNode ht[2*n],索引从 1 开始:
typedefstruct{charch;// 字符intweight;// 权重intparent;// 双亲下标intlchild;// 左孩子下标intrchild;// 右孩子下标}HTNode;初始化时,前 n 个节点为叶子节点(字符+权重),parent 初始为 0;后续 n-1 个节点用于存储合并后的非叶节点。
voidCreateHuffmanTree(HTNode ht[],intn){intm=2*n-1;for(inti=1;i<=m;i++){ht[i].parent=ht[i].lchild=ht[i].rchild=0;}for(intk=n+1;k<=m;k++){intmin1=9999,min2=9999;intx1=0,x2=0;// 找两个无父节点且权值最小的节点for(intj=1;j<k;j++){if(ht[j].parent==0&&ht[j].weight<min1){min2=min1;x2=x1;min1=ht[j].weight;x1=j;}elseif(ht[j].parent==0&&ht[j].weight<min2){min2=ht[j].weight;x2=j;}}// 合并两个节点ht[k].weight=min1+min2;ht[k].lchild=x1;ht[k].rchild=x2;ht[x1].parent=k;ht[x2].parent=k;}}从每个叶子节点出发,逆向回溯到根节点,路径上每一步:
'0';'1';#include<string.h>voidGenerateHuffmanCode(HTNode ht[],charhcode[][20],intn){chartemp[20];inttop=0;for(inti=1;i<=n;i++){intcurrent=i;intparent=ht[i].parent;top=0;// 从叶子向上遍历至根while(parent!=0){if(ht[parent].lchild==current)temp[top++]='0';elsetemp[top++]='1';current=parent;parent=ht[parent].parent;}// 反转字符串并存入编码表temp[top]='\0';for(intj=0;j<top;j++){hcode[i][j]=temp[top-1-j];}hcode[i][top]='\0';}}使用二维字符数组hcode[i][20]存储第 i 个字符的哈夫曼编码。
| 字符 | 频率 | 哈夫曼编码 |
|---|---|---|
| A | 5 | 1100 |
| B | 9 | 1101 |
| C | 12 | 111 |
| D | 13 | 100 |
| E | 16 | 101 |
| F | 45 | 0 |
注意:编码不唯一(左右子树可互换),但总带权路径长度 WPL 是最优的。