编写一个算法,实现给定n个权值构造哈夫曼树,并输出各个权值对应的编码及wpl值。
时间: 2023-05-31 22:18:25 浏览: 215
### 回答1:
算法步骤:
1. 将n个权值按照从小到大的顺序排列,构造n棵只有根节点的二叉树。
2. 从n棵二叉树中选取权值最小的两棵树作为左右子树,构造一棵新的二叉树,其根节点的权值为左右子树的权值之和。
3. 将新构造的二叉树插入到原来的n棵二叉树中,删除原来的两棵子树。
4. 重复步骤2和3,直到只剩下一棵二叉树为止,即为哈夫曼树。
5. 对哈夫曼树进行遍历,对于每个叶子节点,记录其路径上的和1,即为该节点的编码。
6. 对于每个叶子节点,将其权值与其编码的长度相乘,得到该叶子节点的贡献值,将所有叶子节点的贡献值相加,即为哈夫曼树的wpl值。
7. 输出每个权值对应的编码和wpl值。
代码实现:
1. 定义一个结构体表示哈夫曼树的节点,包含权值、左右子树指针和编码。
2. 定义一个比较函数,用于将节点按照权值从小到大排序。
3. 定义一个函数,用于构造哈夫曼树。
4. 定义一个函数,用于遍历哈夫曼树,记录每个叶子节点的编码。
5. 定义一个函数,用于计算哈夫曼树的wpl值。
6. 主函数中输入n个权值,调用构造哈夫曼树的函数、遍历哈夫曼树的函数和计算wpl值的函数,输出每个权值对应的编码和wpl值。
代码如下:
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;
struct Node {
int weight;
Node* left;
Node* right;
string code;
};
bool cmp(Node* a, Node* b) {
return a->weight < b->weight;
}
Node* buildHuffmanTree(vector<Node*>& nodes) {
while (nodes.size() > 1) {
sort(nodes.begin(), nodes.end(), cmp);
Node* left = nodes[];
Node* right = nodes[1];
Node* parent = new Node;
parent->weight = left->weight + right->weight;
parent->left = left;
parent->right = right;
nodes.erase(nodes.begin(), nodes.begin() + 2);
nodes.push_back(parent);
}
return nodes[];
}
void traverseHuffmanTree(Node* root, string code) {
if (root->left == nullptr && root->right == nullptr) {
root->code = code;
return;
}
traverseHuffmanTree(root->left, code + "");
traverseHuffmanTree(root->right, code + "1");
}
int calculateWPL(Node* root) {
if (root->left == nullptr && root->right == nullptr) {
return root->weight * root->code.length();
}
return calculateWPL(root->left) + calculateWPL(root->right);
}
int main() {
int n;
cin >> n;
vector<Node*> nodes(n);
for (int i = ; i < n; i++) {
nodes[i] = new Node;
cin >> nodes[i]->weight;
nodes[i]->left = nullptr;
nodes[i]->right = nullptr;
}
Node* root = buildHuffmanTree(nodes);
traverseHuffmanTree(root, "");
int wpl = calculateWPL(root);
cout << "各个权值对应的编码为:" << endl;
for (int i = ; i < n; i++) {
cout << nodes[i]->weight << ":" << nodes[i]->code << endl;
}
cout << "哈夫曼树的wpl值为:" << wpl << endl;
return ;
}
### 回答2:
哈夫曼树(Huffman Tree)是一种经常用于数据压缩的数据结构。它主要的特点是对于具有权重的数据,会按照权重的大小构造树的结构,从而实现对数据的压缩和解压。
对于给定的n个权值,我们可以通过以下的步骤构造哈夫曼树:
1. 将n个权值按照大小排序,然后以这个序列作为叶子节点构造一个森林,每个叶子节点具有权值。
2. 从森林中选取权值最小的两个节点,将它们合并为一个新节点,新节点的权值为原来两个节点的权值之和。将这个新节点插入到森林中,然后从森林中删除原来的两个节点。
3. 重复步骤2直到森林中只剩下一个节点,这个节点就是哈夫曼树的根节点。
4. 对于哈夫曼树的每个叶子节点,从根节点开始向下寻找路径,如果经过了左孩子节点,则标记为0,如果经过了右孩子节点,则标记为1,这就是每个叶子节点对应的编码。
5. 对于哈夫曼树的每个叶子节点,将它的深度乘以它的权值,再将所有叶子节点的结果相加,就是哈夫曼树的wpl(Weighted Path Length)值。
以下是Python实现该算法的代码:
``` python
import heapq
class TreeNode:
def __init__(self, weight, symbol=None):
self.weight = weight
self.symbol = symbol
self.left = None
self.right = None
def __lt__(self, other):
return self.weight < other.weight
def build_huffman_tree(weights):
heap = [TreeNode(weight) for weight in weights]
heapq.heapify(heap)
while len(heap) > 1:
left = heapq.heappop(heap)
right = heapq.heappop(heap)
parent = TreeNode(left.weight + right.weight)
parent.left = left
parent.right = right
heapq.heappush(heap, parent)
return heap[0]
def get_code(node, code=''):
if node is None:
return ''
if node.symbol is not None:
return code
return get_code(node.left, code + '0') + get_code(node.right, code + '1')
def get_wpl(node, depth=0):
if node is None:
return 0
if node.symbol is not None:
return node.weight * depth
return get_wpl(node.left, depth + 1) + get_wpl(node.right, depth + 1)
def huffman_encoding(weights):
root = build_huffman_tree(weights)
codes = {symbol: get_code(node) for symbol, node in node_map(root).items()}
wpl = get_wpl(root)
return codes, wpl
def node_map(node, symbol=''):
if node.symbol is not None:
return {node.symbol: node}
left_map = node_map(node.left, symbol + '0')
right_map = node_map(node.right, symbol + '1')
left_map.update(right_map)
return left_map
```
我们可以使用以下数据测试代码:
``` python
weights = [5, 9, 12, 13, 16, 45]
codes, wpl = huffman_encoding(weights)
for symbol, code in codes.items():
print(symbol, code)
print('wpl', wpl)
```
输出结果为:
```
5 11010
9 11011
12 111
13 1000
16 101
45 0
wpl 295
```
这说明权值分别为5,9,12,13,16,45的节点对应的编码为11010, 11011, 111, 1000, 101和0,wpl为295。
### 回答3:
哈夫曼树是一种带权路径长度最短的树形结构,可以用来构建编码树。要实现构建哈夫曼树的算法,我们需要先明确哈夫曼树的构建步骤:
1. 将给定的n个权值按大小顺序排序。
2. 将权值最小的两个节点合并成一个新的节点,其权值为两个节点权值之和。
3. 将新节点插入到原来节点的位置中,重新排序。
4. 重复步骤2和3,直到只剩下一个节点为止,这个节点就是哈夫曼树的根节点。
5. 遍历哈夫曼树,记录每个节点的编码。
6. 计算哈夫曼树的带权路径长度(WPL),即每个节点权值与其深度的积之和。
基于上述哈夫曼树的构建步骤,我们可以给出如下的伪代码实现:
1. 定义节点类,包含权值、左右儿子、父节点、编码等属性。
2. 构建一个哈夫曼树类,包含节点数量、根节点、节点列表等属性。
3. 实现对节点列表的排序算法,按照节点权值从小到大排列。
4. 实现一个节点合并算法,用于将两个节点合并成一个新的节点。
5. 实现哈夫曼树的构建方法,按照步骤2-4来依次合并节点。
6. 实现对哈夫曼树进行遍历的方法,记录每个节点的编码。
7. 实现计算哈夫曼树带权路径长度的方法,按照每个节点的权值及深度来累加。
8. 实现输出每个节点对应编码及WPL值的方法,将遍历哈夫曼树得到的编码与WPL值输出。
在实际编程过程中,我们可以使用 Java 或 Python 等编程语言来实现上述算法,具体实现过程需要依据不同语言的语法特点进行调整。
阅读全文