二叉树算法笔记:赫夫曼树(最优二叉树) in java

二叉树结点类,注:包含toArray()方法和toList()方法:
public class BinaryTreeNode {
	
	private BinaryTreeNode leftChild;
	private BinaryTreeNode rightChild;
	private BinaryTreeNode parent;
	private int value;
	private String name;
	
	public BinaryTreeNode(){
	}

	public BinaryTreeNode( int value ){
		this.value = value;
	}
	public BinaryTreeNode( String name , int value ){
		this.name = name;
		this.value = value;
	}
	
	public BinaryTreeNode getLeftChild() {
		return leftChild;
	}

	public void setLeftChild(BinaryTreeNode leftChild) {
		this.leftChild = leftChild;
	}

	public BinaryTreeNode getRightChild() {
		return rightChild;
	}

	public void setRightChild(BinaryTreeNode rightChild) {
		this.rightChild = rightChild;
	}

	public int getValue() {
		return value;
	}

	public void setValue(int value) {
		this.value = value;
	}

	public BinaryTreeNode getParent() {
		return parent;
	}

	public void setParent(BinaryTreeNode parent) {
		this.parent = parent;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	public LinkedList<BinaryTreeNode> toList(){
		LinkedList<BinaryTreeNode> list = new LinkedList<BinaryTreeNode>();
		toList( this , list );
		return list;
	}
	
	private void toList( BinaryTreeNode root , List<BinaryTreeNode> list ){
		if( root != null ){
			list.add( root );
			toList( root , list );
			toList( root , list );
		}
	}
	
	public int[] toArray(){
		int[] array = new int[BinaryTree2Links.getSubNodeNum(this) + 1 ];
		toArray( this , array , 0 );
		return array;
	}
	
	private void toArray( BinaryTreeNode root , int[] array, int i ){
		if( root != null ){
			array[i++] = root.getValue();
			toArray( root , array , i );
			toArray( root , array , i );
		}
	}

}

 

 

 

 

Huffman树操作类:

/**
 * 赫夫曼树(最有二叉树):权值最大的叶子离根较近,权值小的结点离根较远。总的来讲就是,常用的能较快找到,难用的稍微麻烦点。
 * 注:其定义符合国际上对满二叉树的定义,即要么有俩孩子,要么没孩子。但是不符合国内对满二叉树的定义(一片神奇的国土)。
 * @author CheN
 *
 */
public class HuffmanTree{
	
	/**
	 * 将一棵树转化为赫夫曼树
	 * @param list
	 * @return
	 */
	public static BinaryTreeNode buildHuffmanTree( BinaryTreeNode root ){
		return buildHuffmanTree(root.toList());
	}
	
	/**
	 * 建立赫夫曼树
	 * @param list
	 * @return
	 */
	public static BinaryTreeNode buildHuffmanTree( List<BinaryTreeNode> list ){
		// 1.n个有权值结点,要求左右子树均为空
		for( BinaryTreeNode node : list ){
			if( node.getLeftChild() != null || node.getRightChild() != null || node.getParent() != null )
				return null;
		}
		//4.重复步骤2-3,直至list中只剩下一棵树,即root。
		while( list.size() > 1 ){
			//2.找出值最小的两个结点,并且创建他们的父结点,权值为两个结点的和
			//3.将两个旧结点抛除在外,将新建立的结点加入至list
			int min1 = findMinNode(list);
			BinaryTreeNode rightChild = list.remove( min1 );
			int min2 = findMinNode(list);
			BinaryTreeNode leftChild = list.remove( min2 );
			BinaryTreeNode newNode = buildNewNode(leftChild, rightChild);
			list.add(newNode);
		}
		return list.get(0);
	}
	
	/**
	 * 查找权值最小的结点(运行两次,分别找出最小的两个)
	 * @param list
	 * @return
	 */
	private static int findMinNode( List<BinaryTreeNode> list ){
		int index = 0;
		int min = list.get(0).getValue();
		for( int i = 1 ; i < list.size(); i++ ){
			if( list.get(i).getValue() < min ){
				min = list.get(i).getValue();
				index = i;
			}
		}
		return index;
	}
	
	/**
	 * 创建新结点
	 * @param leftChild
	 * @param rightChild
	 * @return
	 */
	private static BinaryTreeNode buildNewNode( BinaryTreeNode leftChild , BinaryTreeNode rightChild ){
		BinaryTreeNode newNode = new BinaryTreeNode();
		newNode.setLeftChild(leftChild);
		newNode.setRightChild(rightChild);
		newNode.setValue(leftChild.getValue() + rightChild.getValue());
		return newNode;
	}
		
	//////////////////赫夫曼编码//////////////////////
	
	/**
	 * 获取赫夫曼编码
	 */
	public static Map<String,String> getHuffmanCoding( BinaryTreeNode root ){
		Map<String,String> map = new HashMap<String,String>();
		buildHuffmanCoding( root , map , "" );
		return map;
	}
	
	/**
	 * 生成每个内容对应的编码
	 * @param node
	 * @param map
	 * @param content
	 */
	private static void buildHuffmanCoding(BinaryTreeNode node, Map<String, String> map, String content) {
		if (node.getLeftChild() == null) {
			map.put(node.getName(), content);
//			注意啦!!!下面这一行是为了让代码可解码,所以将map中设置成key/value + value/key的形式。如果不需要就注释掉即可(正常情况下不会造成bug,除非极特殊情况下)。
			map.put(content, node.getName());
			return;
		}
		// 对左子树分配代码"0"
		buildHuffmanCoding(node.getLeftChild(), map, content + "0");
		// 对右子树分配代码"1"
		buildHuffmanCoding(node.getRightChild(), map, content + "1");
	}
	
	/**
	 * 用赫夫曼编码对内容进行编码
	 * @param str
	 * @param map
	 * @return
	 */
	public static String encoding( String str , Map<String,String> map ){
		StringBuffer sb = new StringBuffer();
		for( int i = 0 ; i < str.length() ; i++ ){
			sb.append(map.get(str.substring(i, i+1)));
		}
		return sb.toString();
	}
	
	/**
	 * 用赫夫曼编码对编码过的内容进行解码(map中须包含解码信息,请注意buildHuffmanCoding方法中第4-5行)
	 * @param str
	 * @param map
	 * @return
	 */
	public static String decoding( String str , Map<String,String> map ){
		StringBuffer sb = new StringBuffer();
		for( int i = 1 , j = 0 ; i < str.length() ; i++ ){
			String code = str.substring( j , i );
			boolean tag = map.containsValue(code);
			if( tag ){
				j = i;
				sb.append(map.get(code));
			}
		}
		return sb.toString();
	}
}

 

 

 

你可能感兴趣的:(二叉树,Huffman,HuffmanCoding,赫夫曼编码,赫夫曼树,最优二叉树)