【PTA数据结构 | C语言版】哈夫曼树的实现
本专栏持续输出数据结构题目集,欢迎订阅。
文章目录
- 题目
- 代码
题目
请根据给定的 n 个权重,建立哈夫曼树,并计算带权路径长度 WPL。
输入格式:
每组测试第 1 行包含正整数 n (2<n≤10^4),为权重的个数。随后一行中给出 n 个不超过 10^
4 的正整数权重,数字间以空格分隔。
输出格式:
在一行中输出根据给定的 n 个权重建立的哈夫曼树所对应的带权路径长度 WPL。
输入样例:
5
3 2 5 1 4
输出样例:
33
代码
#include <stdio.h>
#include <stdlib.h>#define MAXN 10001
#define INF 0x7FFFFFFFtypedef struct {int *data; // 存储元素的数组int size; // 当前堆的大小int capacity; // 堆的最大容量
} MinHeap;// 创建最小堆
MinHeap* CreateHeap(int capacity) {MinHeap* heap = (MinHeap*)malloc(sizeof(MinHeap));heap->data = (int*)malloc((capacity + 1) * sizeof(int));heap->size = 0;heap->capacity = capacity;heap->data[0] = -INF; // 哨兵,小于所有可能的元素值return heap;
}// 插入元素到最小堆
void Insert(MinHeap* heap, int x) {int i;for (i = ++heap->size; heap->data[i/2] > x; i /= 2) {heap->data[i] = heap->data[i/2]; // 上滤}heap->data[i] = x;
}// 删除最小堆的根节点(最小值)
int DeleteMin(MinHeap* heap) {int parent, child;int minItem, x;if (heap->size == 0) return -1;minItem = heap->data[1];x = heap->data[heap->size--];for (parent = 1; parent * 2 <= heap->size; parent = child) {child = parent * 2;if ((child != heap->size) && (heap->data[child] > heap->data[child+1]))child++; // 选择较小的子节点if (x <= heap->data[child]) break;else heap->data[parent] = heap->data[child]; // 下滤}heap->data[parent] = x;return minItem;
}// 构建最小堆
void BuildHeap(MinHeap* heap, int n) {int i;for (i = n/2; i > 0; i--) {int parent, child;int x = heap->data[i];for (parent = i; parent * 2 <= heap->size; parent = child) {child = parent * 2;if ((child != heap->size) && (heap->data[child] > heap->data[child+1]))child++;if (x <= heap->data[child]) break;else heap->data[parent] = heap->data[child];}heap->data[parent] = x;}
}// 计算哈夫曼树的WPL
int CalculateWPL(int weights[], int n) {MinHeap* heap = CreateHeap(n);int i, wpl = 0;// 初始化堆heap->size = n;for (i = 1; i <= n; i++) {heap->data[i] = weights[i-1];}BuildHeap(heap, n);// 构建哈夫曼树并计算WPLfor (i = 1; i < n; i++) {int x = DeleteMin(heap);int y = DeleteMin(heap);wpl += x + y; // 每次合并两个最小值,累加权重和Insert(heap, x + y); // 合并后的新节点插入堆中}free(heap->data);free(heap);return wpl;
}int main() {int n, i;int weights[MAXN];// 读取输入scanf("%d", &n);for (i = 0; i < n; i++) {scanf("%d", &weights[i]);}// 计算并输出WPLprintf("%d\n", CalculateWPL(weights, n));return 0;
}