java哈夫曼树--哈夫曼编码实现

我看大神们写的文章,每个人理解的角度都不一样,于是我决定自己写一写
跟别人的思路都不一样,我也不知道对不对

首先是结点类型的定义

package 哈弗曼树;

import static java.lang.System.out;

import java.util.List;

public class Node implements Comparable<Node> {
	private String name;
	public int parent;
	private int lchild;
	private int rchild;
	public double weight;
	public int index;
	public String code;

	public Node(String name, double weight, int index) {
		super();
		this.name = name;
		this.weight = weight;
		this.index = index;
		this.parent = -1; // 父节点初始化为-1,代表没有父节点
		this.lchild = -1; // 左孩子初始化为-1,代表没有左孩子
		this.rchild = -1; // 右结点初始化为-1,代表没有右孩子
		this.code = "";
	}
	/**
	 * Compares this object with the specified object for order. 
	 * Returns a negative integer, zero, or a positive integer 
	 * as this object is less than, equal to, or greater than the specified object
	 * */
	@Override
	public int compareTo(Node o) {
		if(this.weight < o.weight)
			return -1;
		else if(this.weight > o.weight)
			return 1;
		return 0;
	}

	public void show() {
		out.printf("name = %-2s lchild = %-2d	rchild = %-2d "
				+ "index = %-2d parent = %-2d weight = %.2f"
				+ "	code = %s\n", 
				name ,lchild ,rchild ,index ,parent ,weight,code);
	}

	public void setLchild(int lchild) {
		this.lchild = lchild;
	}

	public void setRchild(int rchild) {
		this.rchild = rchild;
	}

	public void setParent(int parent) {
		this.parent = parent;
	}
	/**
	 * 实现求该结点的哈夫曼编码
	 * @param list 以下标形式表示的哈夫曼树
     */
	public void huffmanCode(List<Node> list) {
		int parent = this.parent;
		int index = this.index;
		while (parent != -1) {	//结点的父节点为-1代表这个结点是根节点,树叶不断寻找父节点,由下向上求哈夫曼编码
			if (list.get(parent).lchild == index)
				code += "0";	//如果树叶是 树叶父节点 的左孩子
			else
				code += "1";
			
			index = list.get(parent).index;
			parent = list.get(parent).parent;
		}
		StringBuffer reverse = new StringBuffer();	//真正的哈夫曼编码是由根部到树叶,所以需要逆序
		for (int i = code.length() - 1; i >= 0; --i)
			reverse.append(code.charAt(i));

		code = reverse.toString();
	}
}

然后是在主函数实现

package 哈弗曼树;

import static java.lang.System.out;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
/*测试数据*/
/*a b c d
0.1 0.2 0.3 0.4

a b c d e f
45 13 12 16 9 5*/

public class HuffmanTree {
	public static int number;
	static List<Node> list;

	public static void main(String[] args) {

		list = new ArrayList<Node>();
		out.println("请输入字符的个数");
		Scanner scanner = new Scanner(System.in);
		number = scanner.nextInt();
		out.println("请输入" + number + "个字符");
		String[] c = new String[number];
		for (int i = 0; i < c.length; ++i)
			c[i] = scanner.next();

		out.println("请输入字符对应的频率");
		double[] freq = new double[number];
		for (int i = 0; i < freq.length; ++i)
			freq[i] = scanner.nextDouble();

		for (int i = 0; i < number; ++i) {
			Node node = new Node(c[i], freq[i], i);
			list.add(node);
		}
		Collections.sort(list);
		huffmanTree();
		scanner.close();
	}

	/**
	 * @return : 权重最大值和次大值所在下标
	 */
	private static ArrayList<Integer> selectTwoMin() {
		ArrayList<Integer> two = new ArrayList<Integer>();
		Integer first = 0, second = 0;/* 两个最小值都初始化为下表为0 */
		double small1, small2;
		small1 = small2 = Double.MAX_VALUE;/* 将最大值和最小值初始化为double类型的最大值 */
		for (int i = 0; i < list.size(); ++i) {
			if (list.get(i).parent == -1) {

				if (small1 > list.get(i).weight) {
					second = first;/* 更新次小的值 */
					small2 = small1;
					small1 = list.get(i).weight;/* 更新最小值 */
					first = i;
				} else if (small2 > list.get(i).weight) {
					small2 = list.get(i).weight;/* 更新次小值 */
					second = i;
				}
			}
		}
		two.add(first);
		two.add(second);
		return two;
	}

	/**
	 * 求哈夫曼树:通过selectTwoMin()找到两个最小结点在list中的下标first,second
	 * 形成新的结点node,权值为first.weight + first.weight 将first,second的父节点域更新为node的下标
	 * node.left = first , node.right = second
	 */
	public static void huffmanTree() {

		for (int i = number; i < 2 * number - 1; ++i) {
			ArrayList<Integer> two = selectTwoMin();
			Integer first = two.get(0);
			Integer second = two.get(1);
			Node left = list.get(first);
			Node right = list.get(second);
			left.setParent(i);
			right.setParent(i);
			Node parent = new Node("*", left.weight + right.weight, i);
			parent.setLchild(list.get(first).index);
			parent.setRchild(list.get(second).index);
			list.add(parent);

		}
		out.println("***************");
		for (Node node : list) {
			node.huffmanCode(list);
			node.show();
		}
	}
}

也不知道对不对,我测试的数据是对的
而且没有进行异常处理,比如数据类型不匹配之类的
我总觉得那是算法之外的
考虑起来挺麻烦的吼吼吼~~~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值