java实现Huffman树

package greedy;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;

public class Huffman {

	private static final String dir = "ABCDEFGHIJKLMNOPQRSTUVWXYZ.,;/!?abcdefghijklmnopqrstuvwxyz";
	private static Node[] nodeArray;
	public static HashMap<Character, String> map = new HashMap<Character, String>();// 存放字符=>编码的key-value对

	static {
		nodeArray = new Node[dir.length() * 2 - 1];
		for (int i = 0; i < dir.length(); i++) {
			nodeArray[i] = new Node(dir.charAt(i), (int) (100 * Math.random() + 1), 0, -1, -1);
		}
		Arrays.sort(nodeArray, 0, dir.length() - 1, new Comparator<Node>() {
			@Override
			public int compare(Node o1, Node o2) {
				return o1.weight - o2.weight;
			}
		});
		initHuffmanTree();
	}

	private static void initHuffmanTree() {
		int initLength = dir.length();
		for (int i = 0; i < nodeArray.length - 2;) {
			Node x = nodeArray[i];
			Node y = nodeArray[i + 1];
			Node parent = new Node(x.weight + y.weight, i + 1, i);
			int j = i + 2;
			while (j < initLength && nodeArray[j].weight <= parent.weight && nodeArray[j].weight != 0)
				j++;
			for (int k = initLength; k > j; k--) {
				if (nodeArray[k - 1].left != -1) {
					nodeArray[nodeArray[k - 1].left].parent = k;
					nodeArray[nodeArray[k - 1].right].parent = k;
				}
				if ((k - 1) == nodeArray[nodeArray[k - 1].parent].left) {
					nodeArray[nodeArray[k - 1].parent].left = k;
				} else if ((k - 1) == nodeArray[nodeArray[k - 1].parent].right) {
					nodeArray[nodeArray[k - 1].parent].right = k;
				}
				nodeArray[k] = nodeArray[k - 1];

			}
			if (j < nodeArray.length) {
				nodeArray[j] = parent;
				x.parent = j;
				y.parent = j;
			}
			initLength++;
			i += 2;
		}
		for (int i = 0; i < nodeArray.length; i++) {
			System.out.println(i + "->" + nodeArray[i]);
		}
		Node root = nodeArray[nodeArray.length - 1];
		List<String> codeStack = new ArrayList<String>();
		List<Node> nodeStack = new ArrayList<Node>();
		for (;;) {
			if (root.left != -1) {
				nodeStack.add(root);
				root = nodeArray[root.left];
				codeStack.add("0");
			} else {
				String code01 = "";
				for (int i = 0; i < codeStack.size(); i++)
					code01 += codeStack.get(i);
				map.put(root.key, code01);
				if (root == nodeArray[nodeArray[root.parent].left]) {
					codeStack.set(codeStack.size() - 1, "1");
					root = nodeArray[nodeArray[root.parent].right];
				} else {
					while (!root.equals(nodeArray[nodeArray.length - 1])
							&& root == nodeArray[nodeArray[root.parent].right]) {
						root = nodeStack.remove(nodeStack.size() - 1);
						codeStack.remove(codeStack.size() - 1);
					}
					if (root.equals(nodeArray[nodeArray.length - 1]))
						break;
					codeStack.set(codeStack.size() - 1, "1");
					root = nodeArray[nodeArray[root.parent].right];
				}
			}
		}
		System.out.println(map);
	}

	public static class Node {
		public char key;
		public int weight;
		public int parent;
		public int right;
		public int left;

		public Node(char key, int weight, int parent, int right, int left) {
			super();
			this.key = key;
			this.weight = weight;
			this.parent = parent;
			this.right = right;
			this.left = left;
		}

		@Override
		public String toString() {
			return "Node [key=" + key + ", weight=" + weight + ", parent=" + parent + ", right=" + right + ", left="
					+ left + "]";
		}

		public Node() {
		}

		public Node(char key, int weight, int right, int left) {
			super();
			this.key = key;
			this.weight = weight;
			this.right = right;
			this.left = left;
		}

		public Node(int weight, int right, int left) {
			super();
			this.weight = weight;
			this.right = right;
			this.left = left;
		}

		public Node(char key, int weight) {
			this.key = key;
			this.weight = weight;
		}

	}
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值