哈夫曼编码是一种基于字符出现频率的最优前缀编码方式,广泛应用于数据压缩领域。下面我将给出一个简单的C#实现哈夫曼编码(压缩)和解压缩的示例,包括构建哈夫曼树、编码和解码过程:
Csharp
1using System;
2using System.Collections.Generic;
3
4// 定义节点类
5public class Node : IComparable<Node>
6{
7 public char Value { get; set; } // 节点值,如果是叶子节点则是字符
8 public int Frequency { get; set; } // 字符出现频率
9 public Node Left { get; set; }
10 public Node Right { get; set; }
11
12 public Node(char value, int frequency)
13 {
14 Value = value;
15 Frequency = frequency;
16 }
17
18 public int CompareTo(Node other)
19 {
20 return this.Frequency.CompareTo(other.Frequency);
21 }
22}
23
24public static class HuffmanCoding
25{
26 // 构建哈夫曼树
27 public static Node BuildHuffmanTree(Dictionary<char, int> frequencies)
28 {
29 var queue = new PriorityQueue<Node>(new List<Node>(frequencies.Select(x => new Node(x.Key, x.Value))));
30 while (queue.Count > 1)
31 {
32 var left = queue.Dequeue();
33 var right = queue.Dequeue();
34
35 var newNode = new Node('\0', left.Frequency + right.Frequency);
36 newNode.Left = left;
37 newNode.Right = right;
38
39 queue.Enqueue(newNode);
40 }
41 return queue.Dequeue();
42 }
43
44 // 从哈夫曼树生成编码字典
45 public static Dictionary<char, string> GenerateCodes(Node node, string codeSoFar = "", Dictionary<char, string> codes = null)
46 {
47 if (codes == null) codes = new Dictionary<char, string>();
48
49 if (node.Left == null && node.Right == null) // 叶子节点
50 {
51 codes[node.Value] = codeSoFar;
52 return codes;
53 }
54
55 GenerateCodes(node.Left, codeSoFar + "0", codes);
56 GenerateCodes(node.Right, codeSoFar + "1", codes);
57
58 return codes;
59 }
60
61 // 压缩方法
62 public static string Compress(string input, Dictionary<char, string> huffmanCodes)
63 {
64 var compressedData = new StringBuilder();
65 foreach (char c in input)
66 {
67 compressedData.Append(huffmanCodes[c]);
68 }
69 return compressedData.ToString();
70 }
71
72 // 解压缩方法
73 public static string Decompress(string compressedData, Node huffmanTree)
74 {
75 var decompressedData = new StringBuilder();
76 var currentNode = huffmanTree;
77 foreach (char bit in compressedData)
78 {
79 if (bit == '0')
80 {
81 currentNode = currentNode.Left ?? throw new ArgumentException("Invalid Huffman tree or data");
82 }
83 else if (bit == '1')
84 {
85 currentNode = currentNode.Right ?? throw new ArgumentException("Invalid Huffman tree or data");
86 }
87
88 if (currentNode.Left == null && currentNode.Right == null)
89 {
90 decompressedData.Append(currentNode.Value);
91 currentNode = huffmanTree;
92 }
93 }
94 return decompressedData.ToString();
95 }
96}
97
98// 需要自定义优先队列PriorityQueue,这里仅示意,你可以自己实现或使用.NET中的堆结构
99public class PriorityQueue<T> where T : IComparable<T>
100{
101 // ... 实现优先队列相关方法 ...
102}
103
104// 使用:
105var frequencies = new Dictionary<char, int>();
106// 假设已统计好字符串中各字符频率并填充到frequencies中
107var huffmanTree = HuffmanCoding.BuildHuffmanTree(frequencies);
108var huffmanCodes = HuffmanCoding.GenerateCodes(huffmanTree);
109var inputString = "Your input string";
110var compressed = HuffmanCoding.Compress(inputString, huffmanCodes);
111var decompressed = HuffmanCoding.Decompress(compressed, huffmanTree);
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
- 111.
注意上述代码未包含优先队列PriorityQueue<T>
的完整实现,您需要自行补充或使用现有的.NET库实现。在实际应用中,为了便于存储和传输,压缩后的比特流通常会转化为二进制或Base64格式。