获取字符串内的每个字符及其出现次数(权值),然后根据权值大小进行排序,构建哈夫曼树;根据哈夫曼树进行对字符编码(从根节点出发,往左走为0,往右走为1进行编码);解码过程输入哈夫曼树和压缩码,输出为字符。
package Tree;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
public class MyHaFuMann {
static class Node
{
Character data;//数据域
int weight;//权值
Node left;//左节点
Node right;//右节点
public Node(Character data)
{
this.data=data;
}
public Node(Character data,int weight)
{
this.data=data;
this.weight=weight;
}
public Node()
{
}
}
public Node CreateMyHaFuMannTree(String inputString)
{
//获取字符并排序
HashMap<Character, Integer>map=new HashMap<Character, Integer>();
for(int i=0;i<inputString.length();i++)
{
if(map.containsKey(inputString.charAt(i)))
{
map.put(inputString.charAt(i),map.get(inputString.charAt(i))+1);
}
else {
map.put(inputString.charAt(i), 1);
}
}
List<Map.Entry<Character, Integer>>list=new ArrayList<Map.Entry<Character,Integer>>(map.entrySet());
Collections.sort(list,new Comparator<Map.Entry<Character, Integer>>() {
//升序排序
public int compare(Entry<Character, Integer>o1,Entry<Character, Integer>o2) {
return o1.getValue().compareTo(o2.getValue());
}
});
//已对字符排好序,下面将创建赫夫曼树
List<Node> nodelistList=new ArrayList<MyHaFuMann.Node>();
for(int i=0;i<list.size();i++)
{
Node nodetempNode=new Node(list.get(i).getKey(),list.get(i).getValue());
nodelistList.add(nodetempNode);
}
while (nodelistList.size()>1) {
//排序
ListSort(nodelistList);
Node lefNode=nodelistList.get(0);
Node rightNode =nodelistList.get(1);
Node parentNode=new Node(null,lefNode.weight+rightNode.weight);
parentNode.left=lefNode;
parentNode.right=rightNode;
//移除前两个节点
nodelistList.remove(0);
nodelistList.remove(0);
//将parentnode加进去
nodelistList.add(parentNode);
}
//while循环结束后第一个元素就是根结点
return nodelistList.get(0);
}
//对list<node>中的数据根据权重进行排序,从小到大
public void ListSort(List<Node>nodes) {
//冒泡法
for(int i=0;i<nodes.size()-1;i++)
{
for(int j=nodes.size()-1;j>i;j--)
{
if(nodes.get(j-1).weight>nodes.get(j).weight)
{
Node tempNode=nodes.get(j);
nodes.set(j,nodes.get(j-1));
nodes.set(j-1,tempNode );
}
}
}
}
//哈夫曼树编码,输出为hashmap,key为字符,value为压缩码,此处用到了递归
public HashMap<Character, String> MyHaFuMannEncode(Node nodeTree,String codeString, HashMap<Character, String>hfmmap) {
if(nodeTree!=null)
{
if(nodeTree.left==null&& nodeTree.right==null)
{
hfmmap.put(nodeTree.data, codeString);
}
MyHaFuMannEncode(nodeTree.left, codeString+"0",hfmmap);
MyHaFuMannEncode(nodeTree.right, codeString+"1",hfmmap);
}
return hfmmap;
}
//哈夫曼解码,输入树和压缩码,输出为字符
public Character MyHaFuMannDecode (Node nodeTree,String coding) {
for(int i=0;i<coding.length();i++)
{
if(coding.charAt(i)=='0')
{
if (nodeTree.left!=null) {
nodeTree=nodeTree.left;
}
else {
throw new RuntimeException("编码错误!");
}
}
if(coding.charAt(i)=='1')
{
if (nodeTree.right!=null) {
nodeTree=nodeTree.right;
}
else {
throw new RuntimeException("编码错误!");
}
}
}
return nodeTree.data;
}
}
主函数测试
package Tree;
import java.util.HashMap;
import Tree.ThreadBinaryTree.Node;
public class program {
public static void main(String[] args) {
MyHaFuMann testFuMann=new MyHaFuMann();
Tree.MyHaFuMann.Node treeNode= testFuMann.CreateMyHaFuMannTree("abbbcccccddddddeeeeeeeee");
HashMap<Character, String>hfmmap=new HashMap<Character, String>();
Map<Character, String>map=testFuMann.MyHaFuMannEncode(treeNode, "", hfmmap) ;
//编码结果
for (Character keyString : map.keySet()) {
System.out.println(keyString+" "+map.get(keyString));
}
//解码
System.out.print(testFuMann.MyHaFuMannDecode(treeNode, "000"));
}
}
测试结果