本专栏持续输出数据结构题目集,欢迎订阅。
题目
请根据给定的 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 0x7FFFFFFF
typedef 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);
// 构建哈夫曼树并计算WPL
for (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]);
}
// 计算并输出WPL
printf("%d\n", CalculateWPL(weights, n));
return 0;
}
1万+

被折叠的 条评论
为什么被折叠?



