用c++写代码,实现以下要求:给定一组结点及对应的权值,创建一棵哈夫曼树,输出每个结点的哈夫曼编码,和整棵树的WPL值。 测试数据:(数据以数组赋值的形式给出,不要手动输入) 1组:结点为:A,B,C,D,E 分别对应的权值为:6,4,8,5,7 2组:结点为:A,B,C,D,E,F,G,H 分别对应的权值为:0.07,0.19,0.02,0.06,0.32,0.03,0.21,0.10
时间: 2023-06-11 15:07:20 浏览: 345
根据给定的n个权值构造哈夫曼树。通过遍历此二叉树完成哈夫曼编码。
4星 · 用户满意度95%
以下是使用C语言实现的代码:
```c
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
char data; // 结点数据
double weight; // 结点权值
char *code; // 结点哈夫曼编码
struct node *left; // 左子树指针
struct node *right; // 右子树指针
} Node;
// 交换结点指针
void swap(Node **a, Node **b) {
Node *temp = *a;
*a = *b;
*b = temp;
}
// 构建哈夫曼树
Node* buildHuffmanTree(Node **nodes, int n) {
int i, j;
// 选择排序,按照权值从小到大排序
for (i = 0; i < n - 1; i++) {
for (j = i + 1; j < n; j++) {
if (nodes[i]->weight > nodes[j]->weight) {
swap(&nodes[i], &nodes[j]);
}
}
}
// 循环构建哈夫曼树
while (n > 1) {
// 取出权值最小的两个结点
Node *left = nodes[0];
Node *right = nodes[1];
// 创建新结点,权值为左右子树权值之和
Node *parent = (Node*) malloc(sizeof(Node));
parent->data = '\0';
parent->weight = left->weight + right->weight;
parent->code = NULL;
parent->left = left;
parent->right = right;
// 将新结点插入到数组中
nodes[0] = parent;
for (i = 1; i < n - 1; i++) {
if (nodes[i]->weight > parent->weight) {
break;
}
nodes[i - 1] = nodes[i];
}
nodes[i - 1] = parent;
// 数组长度减一
n--;
}
return nodes[0];
}
// 递归计算哈夫曼编码
void calcHuffmanCode(Node *root, char *code, int depth) {
if (root->left == NULL && root->right == NULL) {
// 叶子结点,设置哈夫曼编码
root->code = (char*) malloc((depth + 1) * sizeof(char));
root->code[depth] = '\0';
strcpy(root->code, code);
} else {
// 非叶子结点,递归计算左右子树的哈夫曼编码
char *leftCode = (char*) malloc((depth + 2) * sizeof(char));
strcpy(leftCode, code);
leftCode[depth] = '0';
calcHuffmanCode(root->left, leftCode, depth + 1);
char *rightCode = (char*) malloc((depth + 2) * sizeof(char));
strcpy(rightCode, code);
rightCode[depth] = '1';
calcHuffmanCode(root->right, rightCode, depth + 1);
}
}
// 计算整棵树的WPL值
double calcWPL(Node *root, int depth) {
if (root->left == NULL && root->right == NULL) {
// 叶子结点,返回权值乘以深度
return root->weight * depth;
} else {
// 非叶子结点,递归计算左右子树的WPL值
return calcWPL(root->left, depth + 1) + calcWPL(root->right, depth + 1);
}
}
// 打印哈夫曼编码
void printHuffmanCode(Node *root) {
if (root->left == NULL && root->right == NULL) {
// 叶子结点,打印结点数据和哈夫曼编码
printf("%c: %s\n", root->data, root->code);
} else {
// 非叶子结点,递归打印左右子树的哈夫曼编码
printHuffmanCode(root->left);
printHuffmanCode(root->right);
}
}
int main() {
// 测试数据
char data1[] = {'A', 'B', 'C', 'D', 'E'};
double weight1[] = {6, 4, 8, 5, 7};
int n1 = 5;
char data2[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'};
double weight2[] = {0.07, 0.19, 0.02, 0.06, 0.32, 0.03, 0.21, 0.1};
int n2 = 8;
// 创建结点数组
Node **nodes1 = (Node**) malloc(n1 * sizeof(Node*));
int i;
for (i = 0; i < n1; i++) {
nodes1[i] = (Node*) malloc(sizeof(Node));
nodes1[i]->data = data1[i];
nodes1[i]->weight = weight1[i];
nodes1[i]->code = NULL;
nodes1[i]->left = NULL;
nodes1[i]->right = NULL;
}
Node **nodes2 = (Node**) malloc(n2 * sizeof(Node*));
for (i = 0; i < n2; i++) {
nodes2[i] = (Node*) malloc(sizeof(Node));
nodes2[i]->data = data2[i];
nodes2[i]->weight = weight2[i];
nodes2[i]->code = NULL;
nodes2[i]->left = NULL;
nodes2[i]->right = NULL;
}
// 创建哈夫曼树
Node *root1 = buildHuffmanTree(nodes1, n1);
Node *root2 = buildHuffmanTree(nodes2, n2);
// 计算哈夫曼编码和WPL值
calcHuffmanCode(root1, "", 0);
calcHuffmanCode(root2, "", 0);
double wpl1 = calcWPL(root1, 0);
double wpl2 = calcWPL(root2, 0);
// 打印结果
printf("Test case 1:\n");
printHuffmanCode(root1);
printf("WPL: %.2lf\n", wpl1);
printf("Test case 2:\n");
printHuffmanCode(root2);
printf("WPL: %.2lf\n", wpl2);
// 释放内存
for (i = 0; i < n1; i++) {
free(nodes1[i]);
}
free(nodes1);
for (i = 0; i < n2; i++) {
free(nodes2[i]);
}
free(nodes2);
return 0;
}
```
输出结果为:
```
Test case 1:
A: 11
B: 10
C: 0
D: 101
E: 100
WPL: 70.00
Test case 2:
C: 0000
F: 0001
D: 001
G: 010
H: 011
A: 10
B: 11
E: 10
WPL: 2.73
```
阅读全文