已知输入一串正整数,正整数之间用空格键分开,请建立一个哈夫曼树,以输入的数字为叶节点,求这棵哈夫曼树的带权路径长度
时间: 2023-05-31 21:19:09 浏览: 300
哈夫曼树的建立(根据输入的权值,建立一棵哈夫曼树)
### 回答1:
题目描述:已知输入一个串正整数,正整数之间用空格键分开,请建立一个哈夫曼树,以输入的数字为叶节点,求这棵哈夫曼树的带权路径长度。
解析:首先使用输入的数字作为叶节点,建立哈夫曼树。建立方式如下:
- 将所有数字看做一个节点,按照权值从小到大排序。
- 选择权值最小的两个节点合并为一个父节点,权值为两个子节点的权值之和。将这个父节点放入排序后的队列中。
- 重复以上步骤直到队列只剩一个节点,这个节点为哈夫曼树的根节点。
哈夫曼树建立完成后,计算带权路径长度(WPL)即可。带权路径长度定义为:每个叶子节点的权值乘以它到根节点路径上的边数,再将所有叶子节点的WPL相加。具体计算方法如下:
- 对于每一个叶子节点,记录它到根节点路径的长度(通过从叶子节点开始往上遍历,并记录遍历路径的长度,可以使用递归方式实现)。
- 对于每一个叶子节点,计算它的WPL,即该节点的值(即输入的数字)乘以它到根节点的路径长度。
- 将所有叶子节点的WPL相加,得到哈夫曼树的带权路径长度。
完成上述计算即可得到所求答案。
### 回答2:
哈夫曼树主要用于数据压缩,其本质是一种二叉树,每个叶结点代表一个字符,而其它非叶结点则不代表字符。哈夫曼树的带权路径长度(WPL)是指所有叶子结点的权值乘上其到根结点路径长度之和。
建立哈夫曼树的步骤如下:
1.将输入的正整数从小到大排序,作为哈夫曼树的初始叶节点;
2.选取权值最小的两个叶子节点,通过合并得到一个新的父节点,其权值为这两个叶子节点的权值之和;
3.将这个新的父节点插入到叶子节点的集合中,保证集合中的叶子节点依然有序;
4.重复步骤2和3,直到只有一个节点为止,此节点为哈夫曼树的根节点。
计算哈夫曼树的带权路径长度则是通过遍历哈夫曼树的所有叶子节点,将每个叶节点权值乘上其到根节点的路径长度,将所有乘积相加即可。具体实现可以采用递归或者迭代的方式进行。
例如,输入正整数序列为:2 3 4 6,通过建立哈夫曼树,可以得到如下的二叉树:
15
/ \
7 8
/ \ / \
2 3 4 6
其中,叶子节点2、3、4、6分别代表输入的正整数。此时,根节点到每个叶子节点的路径长度分别为1、1、2、2,叶子节点的权值分别为2、3、4、6,带权路径长度即为:
2*1 + 3*1 + 4*2 + 6*2 = 20
因此,建立的哈夫曼树的带权路径长度为20。
### 回答3:
哈夫曼树是一种特殊的二叉树,它的叶子节点为输入的数字,每个数字出现的次数为该数字所代表的权值,构建哈夫曼树的过程就是将这些数字的权值按照从小到大排列,取出两个权值最小的数字,以它们的权值之和为父节点的权值,然后用这个父节点取代两个子节点,重复以上步骤,直到所有数字构成一颗二叉树。
哈夫曼树的带权路径长度是指每个叶节点的权值乘以其路径长度的和,所以我们需要先计算出每个叶节点的路径长度,再将其权值与路径长度相乘并累加起来。
构建哈夫曼树的步骤如下:
1. 读入一串正整数,并将它们存储在一个数组中。
2. 对数组中的数字进行排序,按照从小到大的顺序排列。
3. 创建一个空的哈夫曼树,将权值最小的两个数字作为叶子节点插入到该树中。
4. 将这两个叶子节点的权值之和作为它们的父节点的权值,并用这个父节点取代这两个子节点。
5. 重复步骤3和4,直到只剩下一个父节点,这个父节点就是哈夫曼树的根节点。
6. 计算每个叶节点的路径长度,方法是从该节点一直向上走到根节点,每经过一个节点就将路径长度加1,直到到达根节点为止。
7. 计算哈夫曼树的带权路径长度,方法是将每个叶节点的权值乘以其路径长度,再将结果相加。
8. 输出带权路径长度的结果。
由于哈夫曼树的构建过程需要不断找到权值最小的数字,所以可以使用优先队列来实现。对于每个数字,可以将它的权值和对应的节点放在一个结构体中存储,然后将这些结构体插入到优先队列中,每次从队列中取出两个权值最小的数字,构建出一个新的父节点,并将它插入到队列中。
示例代码如下:(C++)
#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
struct Node{
int num; // 数字
int weight; // 权值
int path_len; // 路径长度
Node *left, *right; // 左右子节点
Node(int num, int weight){
this->num = num;
this->weight = weight;
left = nullptr;
right = nullptr;
path_len = 0;
}
};
// 比较两个节点的权值大小
struct cmp{
bool operator()(const Node *a, const Node *b){
return a->weight > b->weight;
}
};
int main(){
vector<int> arr;
int num;
while(cin >> num){
arr.push_back(num);
}
sort(arr.begin(), arr.end());
priority_queue<Node*, vector<Node*>, cmp> pq;
for(int i = 0; i < arr.size(); ++i){
Node *node = new Node(arr[i], 1);
pq.push(node);
}
while(pq.size() > 1){
Node *left = pq.top();
pq.pop();
Node *right = pq.top();
pq.pop();
Node *parent = new Node(-1, left->weight + right->weight);
parent->left = left;
parent->right = right;
pq.push(parent);
}
Node *root = pq.top();
root->path_len = 0;
int sum = 0;
queue<Node*> q;
q.push(root);
while(!q.empty()){
Node *node = q.front();
q.pop();
if(node->num != -1){ // 叶子节点
sum += node->weight * node->path_len;
continue;
}
if(node->left != nullptr){
node->left->path_len = node->path_len + 1;
q.push(node->left);
}
if(node->right != nullptr){
node->right->path_len = node->path_len + 1;
q.push(node->right);
}
}
cout << sum << endl;
return 0;
}
阅读全文