利用赫夫曼编码

利用赫夫曼编码

在这里插入图片描述`package mzy.tree_c;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class HuffmanCode {
public static void main(String[] args) {
String context = “the sky is so beautiful”;

	byte[] conArr = context.getBytes();

	System.out.println(Arrays.toString(huffmanZip(conArr)));
}

private static byte[] huffmanZip(byte[] conArr) {

	List<Node> nodes = getNodes(conArr);
	// System.out.println("node:" + nodes);

	// 测试一把
	System.out.println("赫夫曼树");
	Node huffmanNodeTreeRoot = createHuffmanTree(nodes);
	// System.out.println("前序遍历" + huffmanNodeTreeRoot);
	// huffmanNodeTreeRoot.preOrder();
	getCodes(huffmanNodeTreeRoot);
	System.out.println(huffmanCode);

	byte[] zip = zip(conArr, huffmanCode);
	return zip;
}

/**
 * 编写一个方法,将字符串对应的byte[]数组,通过生成的赫夫曼编码表
 * 
 * @param bytes      这是原始的字符对应的byte[]
 * @param humanCodes 生成的赫夫曼编码map
 * @return 返回赫夫曼编码处理后的byte[]
 */
private static byte[] zip(byte[] bytes, Map<Byte, String> humanCodes) {
	StringBuilder sumBuilder = new StringBuilder();
	for (byte b : bytes) {
		sumBuilder.append(huffmanCode.get(b));
	}

	System.out.println(sumBuilder.toString());

	int index = 0;
	int len;
	if (sumBuilder.length() % 8 == 0) {
		len = sumBuilder.length() / 8;
	} else {
		len = sumBuilder.length() / 8 + 1;
	}
	// 创建数组
	byte[] huffmanCodeByte = new byte[len];
	for (int i = 0; i < sumBuilder.length(); i += 8) {// 步长为8
		String tempByte;
		if (i + 8 < sumBuilder.length()) {
			tempByte = sumBuilder.substring(i, i + 8);
		} else {
			tempByte = sumBuilder.substring(i);
		}
		// 将tempByte转成一个byte,放入到huffmanCodeBytes
		huffmanCodeByte[index] = (byte) Integer.parseInt(tempByte);
		index++;

	}

	return huffmanCodeByte;

}

/*
 * 生成赫夫曼树对应的赫夫曼编码 思路 a:将赫夫曼编码存放在Map<Byte,String>形式 32->01
 * b:在生成赫夫曼树编码表示,需要去拼接路径,定义一个StringBuilder,存储某个叶子节点的路径
 */
public static Map<Byte, String> huffmanCode = new HashMap<Byte, String>();
public static StringBuilder builder = new StringBuilder();
// 为了调用方便,冲在一下
public static void getCodes(Node node) {
	getcodes(node, "", builder);
}

/**
 * 将传入的Node节点的叶子节点赫夫曼编码得到并放入到哈夫曼集合中
 * @param node    节点,根节点
 * @param code    代表路径 左0右1;
 * @param builder 用于拼接路径
 */
private static void getcodes(Node node, String code, StringBuilder builder) {
	StringBuilder stringBuilder2 = new StringBuilder(builder);
	stringBuilder2.append(code);
	if (node != null) {
		if (node.date == null) {// 非叶子节点
			// 递归处理,向左递归
			getcodes(node.left, "0", stringBuilder2);
			// 向右递归
			getcodes(node.right, "1", stringBuilder2);
		} else {
			huffmanCode.put(node.date, stringBuilder2.toString());
		}
	}
}

// 通过List,创建赫夫曼树
public static Node createHuffmanTree(List<Node> nodes) {
	while (nodes.size() > 1) {
		// 排序
		Collections.sort(nodes);
		// 取出第一颗最小的二叉树
		Node liftNode = nodes.get(0);
		// 取出第二颗最小的二叉树
		Node rightNode = nodes.get(1);
		// 创建新的一个二叉树
		Node newTree = new Node(null, liftNode.weight + rightNode.weight);
		newTree.left = liftNode;
		newTree.right = rightNode;
		// 删除这两个二叉树
		nodes.remove(rightNode);
		nodes.remove(liftNode);
		nodes.add(newTree);
	}
	return nodes.get(0);
}
// 前序遍历
public static void preOrder(Node rootNode) {
	if (rootNode != null) {
		rootNode.preOrder();
	} else {
		System.out.println("赫夫曼树为空!");
	}
}
// 获取List
public static List<Node> getNodes(byte[] bytes) {
	// 创建Array
	List<Node> nodes = new ArrayList<Node>();
	// 遍历bytes,统计每一个byte出现的次数 map<key,value>
	Map<Byte, Integer> counts = new HashMap<Byte, Integer>();
	for (byte b : bytes) {
		Integer count = counts.get(b);
		if (count == null) {
			counts.put(b, 1);
		} else {
			counts.put(b, count + 1);
		}
	}
	// 把每一个键值对转成一个Node对象,并加入nodes集合
	// 遍历
	for (Map.Entry<Byte, Integer> entry : counts.entrySet()) {
		nodes.add(new Node(entry.getKey(), entry.getValue()));
	}
	return nodes;
}

}

// 创建节点,数据和权值
class Node implements Comparable {
Byte date;// 存放数据(字符)本身,比如‘b’ 98
int weight; // 权值 表示字符出现的次数
Node left;
Node right;
public Node(Byte date, int weight) {
super();
this.date = date;
this.weight = weight;
}
@Override
public String toString() {
return “Node [date=” + date + “, weight=” + weight + “]”;
}
public int compareTo(Node o) {
return this.weight - o.weight;
}

// 前序遍历
public void preOrder() {
	System.out.println(this);
	if (this.left != null) {
		this.left.preOrder();
	}
	if (this.right != null) {
		this.right.preOrder();
	}
}

}

`

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

理想艺术!马

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值