哈夫曼编码和解码

在前一文中,介绍了根据权值进行哈夫曼树的构建(https://blog.csdn.net/m0_51384638/article/details/116278540)。本文,将对传入的字符串进行编码,得出一个哈夫曼编码表,并根据编码表解码,得到原来的数据。
要实现对字符串进行哈夫曼编码和解码,我认为需要解决的问题如下:
1如何统计频率.每一个字符如何与它的权值建立一一对应的关系。
2.搭建哈夫曼树之后,如何得到每一个字符的哈夫曼编码。
3.根据哈夫曼编码表,如何解码得到原来的字符串。

现在,问题依次来解决
1.将字符串转为字节数组,遍历字节数组,将每个字节出现的频率保存到一个新建的数组中,这个必须得保证两个数组的长度一致。比如说在字节数组中,第一个位置的字节的频率必须对应在第二个数组中的第一个位置。但是我不是特别推荐这种方法,在学过的数据结构中,map就是一个键和值一一对应的关系(不考虑有冲突),使用map存储,在后续的编码和解码可以方便很多。
2.依照左0右1的规则,给哈夫曼中的所有路径进行编码,最终的哈夫曼编码即为从根节点到叶子节点路径的编码拼接得到的字符串。使用上文最后得到的哈夫曼树
在这里插入图片描
3节点对应的哈夫曼编码即为:11000,越靠近根节点的哈夫曼编码越短。
3.从哈夫曼编码得到的字符串的第一位开始,一一与编码表对应,如果出现对应的编码即解码成功。例如:编码表为:{97=10, 98=111, 99=0, 107=110},编码字符串为:1010101111110000110,到了第二位数字就在编码表中找到10对应为97,下一步就是从第三位开始,按照上面的规则进行解码。

代码实现
一、编码
使用到的节点类

class Node3 implements Comparable<Node3> {
   
	Byte data;//数据域
	Node3 left,right;
	int weight;//权值域
	public Node3(byte data,int weight) {
   
		this.data = data;
		this.weight = weight;
	}
	public Node3(int weight) {
   
		this.weight = weight;
	}
	public int compareTo(Node3 o) {
   
		// TODO Auto-generated method stub
		return this.weight-o.weight;
	}
	@Override
	public String toString() {
   
		return "Node3 [data=" + data + ", weight=" + weight + "]";
	}
	//前序遍历
	public void preOrder() {
   
		System.out.println(this);
		if(this.left != null)
			this.left.preOrder();
		if(this.right != null)
			this.right.preOrder();
	}	
}

先统计字符串中每个字符出现的频率,并建立映射关系

/**
	 * 
	 * @param str 需要统计的字符串
	 * @return  保存了节点的队列
	 */
public static ArrayList<Node3> creatNode(String str) {
   
		byte[] data = str.getBytes();
		//array用于保存后续建立起来的节点
		ArrayList<Node3> array = new 
  • 2
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
编码是一种常用的数据压缩算法,它通过将出现频率较高的字符用较短的编码表示,而将出现频率较低的字符用较长的编码表示,从而实现对数据的压缩。以下是哈编码解码的基本步骤: 1. 统计字符频率:遍历待编码的文本,统计每个字符出现的频率。 2. 构建哈树:根据字符频率构建哈树。哈树是一种特殊的二叉树,其中每个叶子节点代表一个字符,而非叶子节点代表字符频率之和。 3. 生成编码表:从根节点开始,遍历哈树的路径,左子树路径标记为0,右子树路径标记为1,将每个字符对应的路径记录下来,形成编码表。 4. 进行编码:根据生成的编码表,将待编码的文本中的每个字符替换为对应的编码。 5. 进行解码:使用相同的哈树和编码表,将编码后的数据进行解码,恢复原始文本。 在C#中实现哈编码解码可以按照以下步骤进行: 1. 定义字符频率统计函数:遍历待编码的文本,统计每个字符出现的频率。 2. 构建哈树:根据字符频率构建哈树。可以使用优先队列(PriorityQueue)来实现。 3. 生成编码表:从根节点开始,遍历哈树的路径,左子树路径标记为0,右子树路径标记为1,将每个字符对应的路径记录下来,形成编码表。 4. 进行编码:根据生成的编码表,将待编码的文本中的每个字符替换为对应的编码。 5. 进行解码:使用相同的哈树和编码表,将编码后的数据进行解码,恢复原始文本。 以下是C#代码示例: ```csharp // 定义节点类 class Node { public char Character { get; set; } public int Frequency { get; set; } public Node Left { get; set; } public Node Right { get; set; } } // 构建哈树 private static Node BuildHuffmanTree(Dictionary<char, int> frequencies) { var priorityQueue = new PriorityQueue<Node>(Comparer<Node>.Create((a, b) => a.Frequency - b.Frequency)); foreach (var kvp in frequencies) { priorityQueue.Enqueue(new Node { Character = kvp.Key, Frequency = kvp.Value }); } while (priorityQueue.Count > 1) { var left = priorityQueue.Dequeue(); var right = priorityQueue.Dequeue(); var parent = new Node { Frequency = left.Frequency + right.Frequency, Left = left, Right = right }; priorityQueue.Enqueue(parent); } return priorityQueue.Dequeue(); } // 生成编码表 private static Dictionary<char, string> GenerateCodeTable(Node root) { var codeTable = new Dictionary<char, string>(); TraverseTree(root, "", codeTable); return codeTable; } // 遍历哈树,生成编码表 private static void TraverseTree(Node node, string code, Dictionary<char, string> codeTable) { if (node.Left == null && node.Right == null) { codeTable[node.Character] = code; return; } TraverseTree(node.Left, code + "0", codeTable); TraverseTree(node.Right, code + "1", codeTable); } // 进行编码 private static string Encode(string text, Dictionary<char, string> codeTable) { var encodedText = new StringBuilder(); foreach (var c in text) { encodedText.Append(codeTable[c]); } return encodedText.ToString(); } // 进行解码 private static string Decode(string encodedText, Node root) { var decodedText = new StringBuilder(); var currentNode = root; foreach (var bit in encodedText) { if (bit == '0') { currentNode = currentNode.Left; } else if (bit == '1') { currentNode = currentNode.Right; } if (currentNode.Left == null && currentNode.Right == null) { decodedText.Append(currentNode.Character); currentNode = root; } } return decodedText.ToString(); } // 示例用法 string text = "Hello, World!"; Dictionary<char, int> frequencies = new Dictionary<char, int>(); foreach (var c in text) { if (frequencies.ContainsKey(c)) { frequencies[c]++; } else { frequencies[c] = 1; } } Node root = BuildHuffmanTree(frequencies); Dictionary<char, string> codeTable = GenerateCodeTable(root); string encodedText = Encode(text, codeTable); string decodedText = Decode(encodedText, root); Console.WriteLine("Encoded Text: " + encodedText); Console.WriteLine("Decoded Text: " + decodedText); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值