- 首先找到每一個字母出現的次數作爲該字母的權重
- 然後每一次找權重最小的兩個構建哈夫曼樹,把新生成的節點加到原列表中
- 再選擇兩個最小值的形成新的數
構建好了之後按照左0右1的原則給字符串進行編碼,由此編碼可以讀出該字符串
package com.qcby.Tree;
public class Node {
private String ch;
private int num;
private Node left;
private Node right;
public Node(String ch, int num) {
this.ch = ch;
this.num = num;
}
public Node() {
}
public String getCh() {
return ch;
}
public void setCh(String ch) {
this.ch = ch;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public Node getLeft() {
return left;
}
public void setLeft(Node left) {
this.left = left;
}
public Node getRight() {
return right;
}
public void setRight(Node right) {
this.right = right;
}
@Override
public String toString() {
return "Node{" +
"ch='" + ch + '\'' +
", num=" + num +
", left=" + left +
", right=" + right +
'}';
}
}
package com.qcby.Tree;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class MyHuffman {
public static void main(String[] args) {
String str="ajsfhsdhfasdfkjhsdfhsalkdjsfhdsfhjsklasjfjksfdghkslkdahjfjhsdgasjfhsdjfjshhfg";
//統計每個字母出現的次數
HashMap<String ,Integer> map=new HashMap<>();
for(int i=0; i<str.length();i++){
String ch=str.charAt(i)+"";
if(map.get(ch)==null){
map.put(ch,1);
}else {
map.put(ch,map.get(ch)+1);
}
}
//把這些節點加入一個集合中
ArrayList<Node> arr=new ArrayList<>();
for(Map.Entry<String ,Integer> en:map.entrySet()){
System.out.println("key: "+en.getKey()+" value:"+en.getValue());
Node node=new Node(en.getKey(),en.getValue());
arr.add(node);
}
for (;;){
if(arr.size()>1){
Node[] data=getNode(arr);
Node root=new Node(null,data[0].getNum()+data[1].getNum());
root.setLeft(data[0]);
root.setRight(data[1]);
arr.add(root);
}else
break;
}
Node tree = arr.get(0); //TREE就是最終的哈夫曼樹
Map<String,String> charMaps = new HashMap<>();//key是字符
Map<String,String> codeMaps = new HashMap<>();
allShow(tree,"", charMaps, codeMaps);
String hafucode = "";
for(int i = 0; i < str.length(); i++) {
String ch = str.charAt(i) + "";
hafucode += charMaps.get(ch);
}
System.out.println( hafucode.length() + "||" + str.length() );
System.out.println( hafucode );
String res="";
while (hafucode.length()>0){
for(Map.Entry< String,String> entry:codeMaps.entrySet()){
if(hafucode.startsWith(entry.getKey())){
res+=entry.getValue();
hafucode=hafucode.substring(entry.getKey().length());
}
}
}
System.out.println(res);
}
//找到這個集合中最小的兩個值
public static Node[] getNode(ArrayList<Node> arr){
Node[] nos=new Node[2];
int index1;
int index2;
index1=arr.get(0).getNum()<=arr.get(1).getNum()?0:1;
index2=arr.get(0).getNum()<=arr.get(1).getNum()?1:0;
for(int i=2;i<arr.size();i++){
if(arr.get(i).getNum()<arr.get(index1).getNum()){
index2=index1;
index1=i;
}else if(arr.get(i).getNum()<arr.get(index2).getNum() && arr.get(i).getNum()>=arr.get(index1).getNum()){
index2=i;
}
}
nos[0]=arr.get(index1);
nos[1]=arr.get(index2);
arr.remove(index1);
if(index1<index2){
arr.remove(index2-1);
}else {
arr.remove(index2);
}
return nos;
}
public static void allShow(Node tree,String code, Map<String,String> charMaps , Map<String,String> codeMaps){
if(tree.getLeft()==null){
System.out.println(tree.getNum()+"-------->code"+code);
charMaps.put(tree.getCh(), code);
codeMaps.put(code, tree.getCh());
}else {
allShow(tree.getLeft(),code+"0",charMaps,codeMaps);
allShow(tree.getRight(),code+"1",charMaps,codeMaps);
}
/*if(tree==null){
return;
}else {
/*先序遍歷
System.out.println(tree.getNum());
allShow(tree.getLeft());
allShow(tree.getRight());*/
//輸出葉子節點
/*if(tree.getLeft()==null&&tree.getRight()==null){
System.out.println(tree.getNum());
}else {
allShow(tree.getLeft());
allShow(tree.getRight());
}
}*/
}
}