哈夫曼树(Huffman Three)编码

哈夫曼树
概念:带权路径最短的二叉树,也为最优二叉树;
特点:所有的数据都存放在叶子节点,父节点的权值等于左右子节点的和。
构建:输入的结点数为8,其结点为a、b、c、d、e、f、g、h,其出现的频率(权重)分别为:0.07、0.19、0.02、0.06、0.32、0.03、0.21、0.10。

  1. 将一组权值(频率)用数组队列存储,并从小到大排序;
  2. 创建一个父节点,将最小的权值作为作为父节点的左子节点,次小的权值作为父节点的右子节点,父节点的权值=左子节点权值+右子节点权值;并删除数组中的左右子节点的权值
  3. 将父节点权值加入数组;重复1-3,直到数组仅剩下一个权值,即根节点。

在这里插入图片描述
哈弗曼编码:当构建出哈夫曼树之后,得到根节点往下遍历,往左子节点走编为0,右子节点为1,直到遍历到叶子节点,因为我们最终的目的是需要对叶子节点编码的,常常应用在压缩。
在这里插入图片描述
这样的编码之后,平均的码长最短短,所以同样的信息传输,所需要的传输时间就最少。
下面有个代码,已经实现Huffman树的构建与编码的,供大家参考。
思路:输入一串字符,首先计算频次,然后排序,建树(结果就会剩下根节点),进行中序遍历,然后进行编码。注意看看,编码,我是自上而下编。

public class HaffumanThree {
	
	public static void main(String[] args) {
		String s="";
		HaffumanThree haffumantree=new HaffumanThree();
		
		Scanner sc=new Scanner(System.in);
		String str=sc.nextLine();
		
		int[] array=haffumantree.count(str);
		LinkedList<Node> list=haffumantree.nodelist(array);
		//haffumantree.sort(list);
		haffumantree.CreatTree(list);
		haffumantree.traverse(list.getFirst());
		haffumantree.code(s, list.getFirst());
		//System.out.println(str.toString());
	}
	
	public int[] count(String str)
	{
		int[] array=new int[256];
		for(int i=0;i<str.length();i++)
		{
			int ascii=str.charAt(i);
			array[ascii]++;
		}	
		return array;
	}
	public LinkedList<Node> nodelist(int[] array)
	{
		LinkedList<Node> list=new LinkedList<Node>();
		String s;
		
		//System.out.println(Arrays.toString(array));
		for(int i=0;i<array.length;i++)
		{
			if(array[i]>0)
			{
				s=(char)i+"";
				Data data=new Data(s, array[i]);
				Node node=new Node(data);
				list.add(node);
			}
			
		}
		//System.out.println(list.get(0));
		return list;
	}
	public  void sort(LinkedList<Node> list)
	{
		int min=0,count=list.size();
		while(count>0)
		{
			min=0;
			for(int i=0;i<count;i++)
			{
				if(list.get(min).data.count>list.get(i).data.count)
					min=i;
			}
			Node node=list.remove(min);
			list.add(node);
			count--;
		}
	}
	public void CreatTree(LinkedList<Node> list)
	{
		while(list.size()>1)
		{
			sort(list);
			Node node1=list.removeFirst();
			Node node2=list.removeFirst();
			Data data=new Data(node1.data.str+node2.data.str, node1.data.count+node2.data.count);
			Node Parents=new Node(data);
			Parents.left=node1;
			Parents.right=node2;
			list.add(Parents);	
		}
	}
	public void traverse(Node node)
	{
		if(node.left==null&&node.right==null)
			System.out.println("节点符号:"+node.data.str+" 权值:"+node.data.count);
		
		if(node.left!=null)
		{
			traverse(node.left);
		}
		if(node.right!=null)
		{
			traverse(node.right);
		}
	}
	public void code(String s,Node node)
	{
		if(node!=null)
		{
			code(s+"0",node.left);
			if(node.left==null&&node.right==null)
			{
				System.out.println("节点编码:"+node.data.str+" "+s);
			}
			
			code(s+"1",node.right);
			
		}
	}
}

测试:
aabbbccddddd
节点符号:d 权值:5
节点符号:b 权值:3
节点符号:a 权值:2
节点符号:c 权值:2
节点编码:d 0
节点编码:b 10
节点编码:a 110
节点编码:c 111

猜你喜欢

转载自blog.csdn.net/chan_fan/article/details/87928331