补充未提交的实验代码

This commit is contained in:
2025-12-18 22:00:27 +08:00
parent e361373ed4
commit 9911e1b60e
3 changed files with 568 additions and 156 deletions

View File

@@ -0,0 +1,126 @@
#include<stdio.h>
int inf = 1000;
typedef struct{
int weight; //结点权值
int parent,lchild,rchild; //结点的双亲、左孩子、右孩子的下标
char ch; //字符
}HTNode,*HuffmanTree;
//查找
int Find(HuffmanTree HT, int n)
{
int min = 0;
for (int i = 1; i <= n; i++)
{
if (HT[i].weight<HT[min].weight && HT[i].parent == 0)
min = i;
}
return min;
}
//选择
void select(HuffmanTree HT, int n, int &s1, int &s2) //传入参数n=k-1
{
s1 = Find(HT, n); //a、在HT[k](1≤k≤i-1)中选择两个其双亲域为0 且权值最小的结点并返回它们在HT中的序号s1和s2
HT[s1].parent = n + 1; //b、得到新结点n + 1从森林中删除s1,s2将s1,s2的双亲域由0改为k (即n+1)
s2 = Find(HT, n);
HT[s2].parent = n + 1; //b、得到新结点n + 1从森林中删除s1,s2将s1,s2的双亲域由0改为k (即n+1)
}
//构造
void CreatHuffmanTree (HuffmanTree &HT, int weight[], char c[], int n) //char c[100];
{
if(n<=1) return;
int m = 2 * n - 1; //数组存储2n-1个元素
HT=new HTNode[m+1]; //0号单元未用所以需要开辟m+1个单元HT[m]表示根结点
for (int i = 1; i <= m; ++i) //将2n-1个元素的lch、 rch、 parent初始化为0, ch字符全部初始化为#
{
//todo list 处理parent 、lchild 、rchild
HT[i].parent = 0;
HT[i].lchild = 0;
HT[i].rchild = 0;
HT[i].ch = '#';
}
HT[0].weight = inf; //int inf = 1000;
for (int j = 1; j <= n; ++j)
{
//todo list //获取 前n个单元中叶子节点的 weight值
HT[j].weight = weight[j];
HT[j].ch = c[j]; //获取 前n个单元中叶子节点的 字符
}
for (int k = n + 1; k <= m; ++k) //合并产生n-1个结点——构造Huffman树
{
int s1, s2;
select(HT, k - 1, s1, s2); //选择两个需要求和的下标
//todo list //c、s1,s2分别作为k的左右孩子
HT[k].lchild = s1;
HT[k].rchild = s2;
//todo list //c、k 的权值为左右孩子权值之和
HT[k].weight = HT[s1].weight + HT[s2].weight;
}
}
//输出哈夫曼树
void DisplayHF(HuffmanTree HT, int r)
{
printf("%c %d\n",HT[r].ch,HT[r].weight);
int s1 = HT[r].lchild;
int s2 = HT[r].rchild;
if (s1 != 0)
DisplayHF(HT, s1);
if (s2 != 0)
DisplayHF(HT, s2);
}
//输出哈夫曼编码
void DisplayHFCode(HuffmanTree HT, int r,int arr[], int top)
{
int s1 = HT[r].lchild; // 获取当前节点的左孩子索引赋值给s1
int s2 = HT[r].rchild; // 获取当前节点的右孩子索引赋值给s2
if (HT[r].lchild != 0) { //左孩子存在
arr[top] = 0; // 在路径数组arr的当前位置top存入0表示走向左孩子
DisplayHFCode(HT, s1, arr, top + 1); // 递归调用DisplayHFCode函数处理左孩子节点同时top加1
}
if (HT[r].rchild != 0) { //右孩子存在
arr[top] = 1; // 在路径数组arr的当前位置top存入1表示走向右孩子
DisplayHFCode(HT, s2, arr, top + 1); // 递归调用DisplayHFCode函数处理右孩子节点同时top加1
}
if (HT[r].lchild==0 && HT[r].rchild==0) { //叶子节点
printf("字符 %c 的编码: ", HT[r].ch); // 打印当前叶子节点对应的字符
for (int i = 0; i < top; ++i) { // 遍历路径数组arr从0到top-1
printf("%d", arr[i]); // 打印路径数组中的每个元素,即字符的哈夫曼编码
}
printf("\n");
}
}
int main()
{
HuffmanTree HT;
int a[100]; //权值
char c[100]; //字母
int arr[100]; //arr:用于存储从根结点到当前结点的路径上的0和1的数组
int top = 0; //top: arr数组的当前索引表示已经存储到的路径的长度
printf("请输入七组数据!(字母 权值)\n");
for (int i = 1; i <= 7; i++) {
scanf("%c %d",&c[i],&a[i]);
getchar();
}
CreatHuffmanTree (HT, a, c, 7);
printf("哈夫曼树先序遍历序列为(字母 权值):\n");
printf("新生成结点用‘#’标记\n");
DisplayHF(HT, 7 * 2 - 1);
printf("哈夫曼编码为:\n");
DisplayHFCode(HT,7 * 2 - 1, arr, top);
// 释放动态分配的内存(补充内存释放,避免内存泄漏,不影响原有逻辑)
delete[] HT;
return 0;
}