字符串利用贪心算法实现哈夫曼编码过程
时间: 2024-05-21 18:02:19 浏览: 86
哈夫曼编码是一种基于贪心算法的编码方式,它可以将一个字符串中的字符转换为二进制编码,从而实现压缩存储。下面是一个利用贪心算法实现哈夫曼编码的过程:
1. 统计字符串中每个字符出现的次数,得到一个字符频率表。
2. 将字符频率表中的每个字符及其出现频率构建成一个森林,每个字符作为一个独立的树。
3. 在森林中找到两个根节点的权值最小的树,将它们合并成一棵新树,新树的权值为两个树的权值之和。
4. 将新树插入到森林中,并删除原来的两个树。
5. 重复步骤3和步骤4,直到森林中只有一棵树为止。
6. 对于每个字符,从根节点开始遍历哈夫曼树,每次向左走为0,向右走为1,得到该字符的二进制编码。
7. 将字符串中的每个字符都转换成对应的二进制编码,得到压缩后的字符串。
在上述过程中,每次找到权值最小的两个树进行合并,就是哈夫曼编码的贪心策略。这样,生成的哈夫曼树满足最优性,即树的带权路径长度最小,从而得到了最优的编码方式。
相关问题
BBCAADDDCCACACAC对以上asc码字符串写出利用贪心算法实现哈夫曼编码的过程
首先,我们需要统计每个字符出现的频率,得到如下表:
| 字符 | 频率 |
|------|------|
| A | 2 |
| B | 2 |
| C | 5 |
| D | 4 |
接下来,我们将频率从小到大排序,得到:
| 字符 | 频率 |
|------|------|
| A | 2 |
| B | 2 |
| D | 4 |
| C | 5 |
然后,我们将频率最小的两个字符合并成一个新的节点,它们的权值为它们频率的和。如图所示,我们将 A 和 B 合并成一个新节点 1,它的权值为 4。
```
(A,2) (B,2)
\ /
\ /
\ /
(1,4)
```
再次排序,得到:
| 字符 | 频率 |
|------|------|
| D | 4 |
| 1 | 4 |
| C | 5 |
合并权值最小的两个节点,得到新的节点 2,它的权值为 8。
```
(1,4) (D,4)
\ /
\ /
\ /
(2,8)
|
|
(C,5)
```
排序后得到:
| 字符 | 频率 |
|------|------|
| 2 | 8 |
| C | 5 |
合并节点 2 和 C,得到根节点,它的权值为 13。
```
(2,8)
/ \
/ \
/ \
(C,5) (D,4)
```
接下来,我们分别给左边和右边的节点赋值 0 和 1,得到哈夫曼编码:
| 字符 | 频率 | 编码 |
|------|------|------|
| A | 2 | 00 |
| B | 2 | 01 |
| C | 5 | 1 |
| D | 4 | 10 |
最终,将字符串 BBCAADDDCCACACAC 转换为哈夫曼编码为 01001000010111111100101010。
贪心算法实现哈夫曼编码java
哈夫曼编码是一种常用的压缩算法,使用贪心算法可以比较简单地实现。
首先需要构建哈夫曼树,然后根据哈夫曼树生成对应的哈夫曼编码。具体实现步骤如下:
1. 定义一个节点类Node,包含字符ch、权值weight、左右子节点left和right等属性。
2. 定义一个哈夫曼树类HuffmanTree,包含根节点root,以及构建哈夫曼树的方法buildTree。
3. 构建哈夫曼树的方法buildTree,接收一个字符数组chars,返回一个哈夫曼树。
a. 计算每个字符出现的频率,并将每个字符和其对应的频率保存在一个Map中。
b. 将Map中的所有节点按照权值从小到大排序,并将节点放入一个优先队列中。
c. 从优先队列中取出两个权值最小的节点作为左右子节点,生成一个新的父节点,并将其放回优先队列中。
d. 重复c的操作,直到优先队列只剩下一个节点,此节点即为哈夫曼树的根节点。
4. 定义一个编码类HuffmanCode,包含一个编码表Map,以及生成编码的方法generateCodes。
5. 生成编码的方法generateCodes,接收一个哈夫曼树,并返回一个编码表。
a. 如果节点是叶子节点,则将其编码加入编码表中。
b. 如果节点有左右子节点,则将左子节点的编码加上字符'0',将右子节点的编码加上字符'1',并分别递归处理左右子节点。
6. 最后可以使用生成的编码表对原始字符串进行编码,将每个字符替换为对应的编码即可。
下面是Java代码实现:
```
import java.util.*;
class Node {
char ch;
int weight;
Node left;
Node right;
public Node(char ch, int weight) {
this.ch = ch;
this.weight = weight;
}
}
class HuffmanTree {
Node root;
public HuffmanTree(Node root) {
this.root = root;
}
public static HuffmanTree buildTree(char[] chars) {
Map<Character, Integer> freq = new HashMap<>();
for (char ch : chars) {
freq.put(ch, freq.getOrDefault(ch, 0) + 1);
}
PriorityQueue<Node> pq = new PriorityQueue<>((a, b) -> a.weight - b.weight);
for (Map.Entry<Character, Integer> entry : freq.entrySet()) {
pq.offer(new Node(entry.getKey(), entry.getValue()));
}
while (pq.size() > 1) {
Node left = pq.poll();
Node right = pq.poll();
Node parent = new Node('\0', left.weight + right.weight);
parent.left = left;
parent.right = right;
pq.offer(parent);
}
return new HuffmanTree(pq.poll());
}
}
class HuffmanCode {
Map<Character, String> codes = new HashMap<>();
public HuffmanCode(HuffmanTree tree) {
generateCodes(tree.root, "");
}
private void generateCodes(Node node, String code) {
if (node.left == null && node.right == null) {
codes.put(node.ch, code);
return;
}
generateCodes(node.left, code + "0");
generateCodes(node.right, code + "1");
}
public String encode(String str) {
StringBuilder sb = new StringBuilder();
for (char ch : str.toCharArray()) {
sb.append(codes.get(ch));
}
return sb.toString();
}
public String decode(String code) {
StringBuilder sb = new StringBuilder();
Node node = HuffmanTree.root;
for (char bit : code.toCharArray()) {
node = (bit == '0') ? node.left : node.right;
if (node.left == null && node.right == null) {
sb.append(node.ch);
node = HuffmanTree.root;
}
}
return sb.toString();
}
}
public class Main {
public static void main(String[] args) {
char[] chars = "ABRACADABRA".toCharArray();
HuffmanTree tree = HuffmanTree.buildTree(chars);
HuffmanCode code = new HuffmanCode(tree);
String encoded = code.encode("ABRACADABRA");
System.out.println(encoded);
System.out.println(code.decode(encoded));
}
}
```
阅读全文