[信息论]Huffman编码的JAVA实现

[注:本文仅供学习和参考,拷贝等引起的后果自负!]

Huffman编码的JAVA实现

(这里算法就不给出了,有兴趣的读者可以参考相关书籍,这里只给出JAVA实现的思路,仅供参考,毕竟水平有限)。

该实验降低了复杂度,仅仅研究二元码,不考虑的编码,所以不存在引入虚拟符的问题;同时考虑到需要用到数据结构的知识且为了记录概率和编码Code,修改了Node节点中存放的信息(节点存放key, 左、右节点,概率和编码,具体修改方法见代码部分),在获得Code时,采用了前序遍历的策略。

对于二元Huffman码的编码如何获得,如何编写JAVA代码的流程如下:

1. 定义两个动态数组(ArrayList()类中的方法)来存放所将建立的树tree(这些节点存在着二叉树的关系)、节点node(该数组用来存放节点,这些节点之间不存在关系)

2. 将node中的节点进行sort排序(按照概率),之后选择最小的两个(与此同时生成一个root,也就是它两的根),并将其放入tree中,并将root放入node,中,并且在node中删除原有的两个节点。循环此步骤,直至node的长度为1(意味着概率之和已经为1);

3. 步骤2得到了一个tree,该数组中最后一个就是root,采用前序遍历的方法,对每个节点的Code进行赋值,前序遍历完就意味着码字生成了;

4. 对于tree中节点的key,若其有含义(是要进行编码的随机变量),则将其Code输出,也就是它的Huffman编码。

运行结果:

 


与预期结果一致;


参考文献

1. THOMAS M. COVER, JOY A. THOMAS. Element of Information Theory. Second Edition.

2. MICHAEL T. GOODRICH, ROBERTO TRMASSIA. Data Structures and Algorithms in Java. Fifth Edition.


参考程序如下。

Node.java

public class Node {
	private String key;
	private Node left, right;
	private double p;
	private String code;

	public Node(String key, double p) {
		this(key, null, null, p);
	}

	public Node(String key2, Node left, Node right, double p) {
		this(key2, left, right, p, "");
	}

	public Node(String key2, Node left, Node right, double p, String code) {
		this.key = key2;
		this.left = left;
		this.right = right;
		this.p = p;
		this.code = code;
	}

	public String getKey() {
		return key;
	}

	public String getCode() {
		return code;
	}

	public void setKey(String key) {
		this.key = key;
	}

	public void setCode(String code) {
		this.code = code;
	}

	public Node getLeft() {
		return left;
	}

	public void setLeft(Node left) {
		this.left = left;
	}

	public void setPro(double p) {
		this.p = p;
	}

	public Node getRight() {
		return right;
	}

	public double getPro() {
		return p;
	}

	public void setRight(Node right) {
		this.right = right;
	}
}


Huffman.java

import java.util.*;

public class Huffman {
	public static ArrayList<Node> tree = new ArrayList<Node>();// 用于建立树
	public static ArrayList<Node> node = new ArrayList<Node>();// 用于存放最初的点,且这些点之间不存在关系
	public static int N;// 取值空间元素的个数

	public void sort(ArrayList<Node> node2) {// 排序
		Node temp;
		int num = node2.size();
		for (int i = 0; i < num - 1; i++)
			for (int j = i + 1; j < num; j++) {
				if (node2.get(i).getPro() > node2.get(j).getPro()) {
					temp = node2.get(i);
					node2.set(i, node2.get(j));
					node2.set(j, temp);
				}
			}
	}

	/** 判断输入数据是否出错,概率之和等于1 */
	public boolean error(double[] pro) {
		double num = 0;
		for (int i = 0; i < N; i++)
			num = num + pro[i];
		if (num != 1)
			return false;
		else
			return true;
	}

	/** 访问节点 */
	public void visit(Node p) {
		// System.out.print(p.getKey() + " ");
		if (p.getLeft() != null) {
			p.getLeft().setCode(p.getCode().concat("0"));
			p.getRight().setCode(p.getCode().concat("1"));
		}
	}

	/** 递归实现前序遍历 */
	protected void preorder(Node p) {
		if (p != null) {
			visit(p);
			preorder(p.getLeft());
			preorder(p.getRight());
		}
	}

	public static void main(String[] args) {
		Huffman en = new Huffman();
		// 数据的输入
		Scanner input = new Scanner(System.in);
		System.out.print("请输入取值空间X中元素的个数:");
		N = input.nextInt();
		String[] str = new String[N];
		System.out.print("请输入取值空间X中的元素:");
		for (int i = 0; i < N; i++)
			str[i] = input.next();// 输入取值空间的数据
		double[] probability = new double[N];
		System.out.print("请输入各个元素的概率:");
		for (int i = 0; i < N; i++)
			probability[i] = input.nextDouble();// 输入对应的概率
		if (en.error(probability)) {
			Node[] ye = new Node[N];
			for (int i = 0; i < N; i++) {
				ye[i] = new Node(str[i], probability[i]);
				node.add(ye[i]);
			}

			/** 此过程建立tree */
			while (node.size() > 1) {
				en.sort(node);
				Node temp1 = node.get(0);
				Node temp2 = node.get(1);// 将要处理的两个点
				Node root = new Node("", temp1, temp2, temp1.getPro()
						+ temp2.getPro());
				tree.add(temp1);
				tree.add(temp2);
				tree.add(root);
				node.remove(0);
				node.remove(0);
				node.add(root);
			}
		} else {
			System.out.print("输入数据有误!");
		}

		/** 遍历树进行Huffman编码 */
		Node root = tree.get(tree.size() - 1);
		en.preorder(root);
		Iterator<Node> it1 = tree.iterator();

		System.out.println("Huffman编码结果如下:");
		/** 迭代器输出结果 */
		while (it1.hasNext()) {
			Node put = it1.next();
			if (!put.getKey().equals("")) {
				System.out.println("X为" + put.getKey() + "时:其Huffman编码:"
						+ put.getCode());
			}
		}
	}
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值