生成哈夫曼树 - 华为OD统一考试(C卷)

OD统一考试(C卷)

分值: 100分

题解: Java / Python / C++

alt

题目描述

给定长度为 n 的无序的数字数组,每个数字代表二叉树的叶子节点的权值,数字数组的值均大于等于 1 。

请完成一个函数,根据输入的数字数组,生成哈夫曼树,并将哈夫曼树按照中序遍历输出。

为了保证输出的二叉树中序遍历结果统一,增加以下限制:

  • 在树节点中,左节点权值小于等于右节点权值,根节点权值为左右节点权值之和。
  • 当左右节点权值相同时,左子树高度高度小于等于右子树。

注意: 所有用例保证有效,并能生成哈夫曼树提醒:哈夫曼树又称最优二叉树,是一种带权路径长度最短的一叉树。

所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为 0 层,叶结点到根结点的路径长度为叶结点的层数)

输入描述

例如:由叶子节点 5 15 40 30 10 生成的最优二叉树如下图所示,该树的最短带权路径长度为 40∗1+30∗2+15∗3+5∗4+10∗4=205。

### 生成哈夫曼的C语言实现 在C语言中,可以通过贪心算法构建哈夫曼,并实现中序遍历输出。以下是具体的实现方法和代码示例。 #### 1. 数据结构定义 为了构建哈夫曼,需要定义一个节点结构体,包含节点权值、左右子节点指针以及父节点指针(可选)。此外,还需要定义一个最小堆来辅助排序操作[^1]。 ```c typedef struct HuffmanNode { int weight; // 权值 struct HuffmanNode *left; // 左子节点 struct HuffmanNode *right; // 右子节点 } HuffmanNode; ``` #### 2. 最小堆的实现 构建哈夫曼时,需要不断从节点集合中选取两个权值最小的节点进行合并。因此,可以使用最小堆来优化这一过程[^3]。 ```c #define MAX_NODES 1000 HuffmanNode heap[MAX_NODES]; int heapSize = 0; // 插入节点到最小堆 void insertHeap(HuffmanNode* node) { int i = heapSize++; while (i > 0) { int parent = (i - 1) / 2; if (heap[parent].weight <= node->weight) break; heap[i] = heap[parent]; i = parent; } heap[i] = *node; } // 提取最小节点 HuffmanNode* extractMin() { HuffmanNode* minNode = &heap[0]; heap[0] = heap[--heapSize]; int i = 0; while (i < heapSize) { int left = 2 * i + 1, right = 2 * i + 2, smallest = i; if (left < heapSize && heap[left].weight < heap[smallest].weight) smallest = left; if (right < heapSize && heap[right].weight < heap[smallest].weight) smallest = right; if (smallest == i) break; HuffmanNode temp = heap[i]; heap[i] = heap[smallest]; heap[smallest] = temp; i = smallest; } return minNode; } ``` #### 3. 构建哈夫曼 根据输入的叶子节点权值数组,逐步构建哈夫曼。每次从堆中取出两个权值最小的节点,生成一个新的父节点,并将其重新插入堆中[^3]。 ```c HuffmanNode* buildHuffmanTree(int weights[], int n) { for (int i = 0; i < n; i++) { HuffmanNode* node = (HuffmanNode*)malloc(sizeof(HuffmanNode)); node->weight = weights[i]; node->left = node->right = NULL; insertHeap(node); } while (heapSize > 1) { HuffmanNode* left = extractMin(); HuffmanNode* right = extractMin(); HuffmanNode* parent = (HuffmanNode*)malloc(sizeof(HuffmanNode)); parent->weight = left->weight + right->weight; parent->left = left; parent->right = right; insertHeap(parent); } return extractMin(); } ``` #### 4. 中序遍历输出 按照题目要求,需要对生成哈夫曼进行中序遍历并输出结果。中序遍历遵循“左--右”的顺序[^3]。 ```c void inorderTraversal(HuffmanNode* root) { if (root == NULL) return; inorderTraversal(root->left); if (root->left == NULL && root->right == NULL) { printf("%d ", root->weight); } inorderTraversal(root->right); } ``` #### 5. 主函数实现 将上述功能整合到主函数中,完成整个程序的实现。 ```c #include <stdio.h> #include <stdlib.h> int main() { int n; printf("请输入叶子节点数量: "); scanf("%d", &n); int weights[n]; printf("请输入叶子节点权值: "); for (int i = 0; i < n; i++) { scanf("%d", &weights[i]); } HuffmanNode* root = buildHuffmanTree(weights, n); printf("中序遍历结果: "); inorderTraversal(root); printf("\n"); return 0; } ``` ### 注意事项 1. 在构建哈夫曼时,确保输入的权值数组均大于等于1。 2. 中序遍历输出时,仅输出叶子节点的权值。 3. 如果需要进一步扩展功能,可以添加释放内存的操作以避免内存泄漏[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

什码情况

你的鼓励就是我最大的动力。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值