贪心算法解决哈夫曼编码问题

霍夫曼(Huffman)编码

1952年为文本文件而建立,是一种统计编码。属于无损压缩编码。
霍夫曼编码的码长是变化的,对于出现频率高的信息,编码的长度较短;而对于出现频率低的信息,编码长度较长。这样,处理全部信息的总码长一定小于实际信息的符号长度。

步骤进行:
l)将信号源的符号按照出现概率递减的顺序排列。
2)将两个最小出现概率进行合并相加,得到的结果作为新符号的出现概率。
3)重复进行步骤1和2直到概率相加的结果等于1为止。
4)在合并运算时,概率大的符号用编码0表示,概率小的符号用编码1表示。
5)记录下概率为1处到当前信号源符号之间的0,l序列,从而得到每个符号的编码

package test;

import java.util.Collections;
import java.util.LinkedList;
import java.util.Scanner;

class HuffNode implements Comparable<HuffNode> {
	/** 权值 */
	int value;
	String name;
	/** 左孩子节点 */
	HuffNode lChild = null;
	/** 右孩子节点 */
	HuffNode rChild = null;
	
public HuffNode(int value, String name) {
		this.value = value;
		this.name = name;
	}
	
public HuffNode(HuffNode lChild, HuffNode rChild) {
		this.lChild = lChild;
		this.rChild = rChild;
		// 权值之和,即合并两个叶子节点
		this.value = lChild.value + rChild.value;
	}
	
/**
	 * 按照权值大小非递减序列
	 * @param o
	 * @return
	 */
	@Override
    public int compareTo(HuffNode o) {
    	if (this.value < o.value) {
    		return -1;
    	} else if (this.value == o.value) {
    		return 0;
    	} else {
    		return 1;
    	}
    }
}
public class Demo_03 {
	/** 用来存放节点值 */
	private static LinkedList<HuffNode> huffList = 
new LinkedList<HuffNode>();
	public static void main(String[] args) {
		System.out.println("Please input: ");
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		for (int i = 0; i < n; i++) {
			huffList.add(new HuffNode(sc.nextInt(), sc.next()));
		}
		huffmanCode();
		decode(huffList.get(0), "");
	}

	
	
/**
	 * 哈夫曼编码
	 */
	public static void huffmanCode() {
		if (huffList.size() == 1) {
			return ;
		}
		while (huffList.size() > 1) {
			// 排序
			Collections.sort(huffList);
			// 将前两个节点进行合并
			HuffNode node =new HuffNode(huffList.get(0), huffList.get(1));
			// 删除前两个节点
			huffList.remove();
			huffList.remove();
			// 将新生成的节点添加到列表中
			huffList.add(node);
		}
		// 编码完成后,此时huffList中只剩一个根节点
	}
	

/**
	 * 解码
	 * @param n
	 * @param code
	 */
	public static void decode(HuffNode n, String code) {
		if ((n.lChild == null) && (n.rChild == null)) {
			// 叶子节点, 此时输出其对应编码
			System.out.print(n.name + "--->" + code);
			System.out.println();
			return ;
		}
		// 遍历左子树
		decode(n.lChild, code + "0");
		// 遍历右子树
		decode(n.rChild, code + "1");
		return ;
	}
	
}

(来源:网络,如有侵权联系删除)

你可能感兴趣的:(贪心算法,算法)