Files
studycode/datastructure/2025301205+施光甲+实验七.cpp
2025-12-18 22:00:27 +08:00

127 lines
3.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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;
}