利用赫夫曼编码

利用赫夫曼编码

利用赫夫曼编码_第1张图片`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 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 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形式 32->01
 * b:在生成赫夫曼树编码表示,需要去拼接路径,定义一个StringBuilder,存储某个叶子节点的路径
 */
public static Map huffmanCode = new HashMap();
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 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 getNodes(byte[] bytes) {
	// 创建Array
	List nodes = new ArrayList();
	// 遍历bytes,统计每一个byte出现的次数 map
	Map counts = new HashMap();
	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 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();
	}
}

}

`

你可能感兴趣的:(数据结构)