基于Java实现的huffman编码

Huffman的应用背景:

在信息的编码中,由于信息表示使用的每个字母的使用频率不一样,若是每个字母都使用相同长度的编码,对于那些用的不多的字符,但是占据空间又较大的字符,就会造成很大的空间浪费,由此,想出了一种新的编码方式,根据字符的使用频率,平率较大的使用较短的编码,反之,使用较大的编码,但是,就又会出现一种新的问题,若是有的字符的编码是另外一个字符的前缀怎么办?例如a的编码是“001”,而b的编码是“0010”,对于这种情况,计算机怎么能辨别是a还是b呢,就此,就提出了Huffman编码。

Huffman的实现:

Huffman编码基于贪心思想,每次挑选权值最小的两个值进行组合成新的权值,参与下一轮的挑选,一次一次自底向上形成一棵树,根据占据树的左右填写对应的Huffman编码

为了方便实现每次选择最小值,自己定义了一个排序算法,实现了Comparable接口

public class MyPoint implements Comparable<MyPoint> {
	private int freq ;
	private String tag;
	
	public int getFreq() {
		return freq;
	}

	public void setFreq(int freq) {
		this.freq = freq;
	}

	public String getTag() {
		return tag;
	}

	public void setTag(String tag) {
		this.tag = tag;
	}

	public int compareTo(MyPoint o) {
		if(freq>o.freq){
			return 1;
		}
		else if (freq<o.freq) {
			return -1;
		}
		return 0;
	}
}

Huffman测试程序:

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;



public class Huffman {
	public static void main(String []args){
		
		//每个节点的权值(频率)
		int freq[] = new int[]{16,9,5,13,12,45};
		//每个节点的标记
		String tg[] = {"A","B","C","D","E","F"};
		List<MyPoint> points =new ArrayList<MyPoint>();
		//初始化每个节点,使其加在list中
		for(int i=0;i<tg.length;i++){
			MyPoint point = new MyPoint();
			point.setFreq(freq[i]);
			point.setTag(tg[i]);
			points.add(point);
		}
		Collections.sort(points);
		huffman(points);
	
	}
	public static void huffman(List<MyPoint> points){
		//存放每个节点的Huffman编码
	    Map<String,String> map = new HashMap<String, String>();
	    map.put("A", "");
	    map.put("B", "");
	    map.put("C", "");
	    map.put("D", "");
	    map.put("E", "");
	    map.put("F", "");
		int newfreq = 0;
		String newtag = "";
		while(points.size()>1){
			MyPoint newpoint = new MyPoint();
			int minfreq = points.get(0).getFreq();
			for(char c : points.get(0).getTag().toCharArray()){
				if(map.containsKey(c+"")){
					String value =map.get(c+"");
					map.put(c+"", "0"+value);
				}
			}
			int minfreq2 = points.get(1).getFreq();
			for(char c : points.get(1).getTag().toCharArray()){
				if(map.containsKey(c+"")){
					String value =map.get(c+"");
					map.put(c+"", "1"+value);
				}
			}
			System.out.println(points.get(0).getTag()+"和"+points.get(1).getTag()+"合并成"+points.get(0).getTag()+points.get(1).getTag());
			newfreq = minfreq + minfreq2;
			newtag = points.get(0).getTag()+points.get(1).getTag();
			newpoint.setFreq(newfreq);
			newpoint.setTag(newtag);
			//移除后第二个就变成第一个
			points.remove(0);
			points.remove(0);
			points.add(newpoint);
			//重新进行排序,保证每次循环时使得List中第一和第二个的权值都是最小的
			Collections.sort(points);
		}
		for(Map.Entry<String, String>entry:map.entrySet()){
			System.out.println(entry.getKey()+"--->"+entry.getValue());
		}
	}
	
}

运行结果:

C和B合并成CB
E和D合并成ED
CB和A合并成CBA
ED和CBA合并成EDCBA
F和EDCBA合并成FEDCBA
A--->111
B--->1101
C--->1100
D--->101
E--->100
F--->0



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值