哈夫曼编码大全

题目: 哈夫曼编码大全

描述:

关于哈夫曼树的建立,编码,解码。

输入

第一行输入数字N,代表总共有多少个字符以及权值

第二第三行分别是一行字符串,以及每个字符对应的权值

接下来输入一个数M,表示接下来有M行字符串,要求你对每个字符串进行编码

再输入一个数X,表示接下来有X行编码,要求你对每行编码进行解码

输出

第一行输出所有节点的权重

接下来输出N行,每行以 “a:001”的格式输出每个字符对应的编码

接着输出M行,对输入的字符串的编码结果

最后,输出X行的解码结果

输入样例

6
abcdef
50 10 5 5 20 10
2
abcdef
defabaabbc
2
011001100100110110101101100
1100011000110101100101100

输出样例

 

50 10 5 5 20 10 10 20 30 50 100
a:0
b:100
c:1100
d:1101
e:111
f:101
010011001101111101
11011111010100001001001100
accbdfadb
cacadacfb

import java.util.Scanner;


/**
 * 哈弗曼编码大全
 * @author 邹龄晋
6
abcdef
50 10 5 5 20 10
 *
 */
public class Demo {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int j;
        HFMTree ht = new HFMTree(n);
        int data[] = new int[n];
        Code code[] = new Code[n];
        String str = sc.next();
        for(int i=0;i<n;i++){
            j = sc.nextInt();
            data[i] = j;
        }
        ht.init(data);
        ht.create();
        //ht.PrintTree();
        ht.Quan();
        for(int i=0;i<n;i++){
            System.out.print(str.charAt(i)+":");
            //ht.PrintCode(i);
            //System.out.println();
            String fff=ht.PrintCode3(i,"");
            code[i] = new Code(str.charAt(i),fff);
            System.out.println(fff);
        }
        //编码
        int k=sc.nextInt();
        while(k>0){
            String s = sc.next();
            for(int i=0;i<s.length();i++){
                int m = str.indexOf(s.charAt(i));
                ht.PrintCode(m);
            }
            k--;
        }
        
        k = sc.nextInt();
        String st;
        int d;
        String ss = sc.nextLine();
        while(k>0){
            int q = 0;
            ss = sc.nextLine();
            for(int m=1;m<=ss.length();m++){
                st = ss.substring(q,m);
                for(d=0;d<code.length;d++){
                    if(st.equals(code[d].getCode())){
                        System.out.print(code[d].getCh());
                        break;
                    }
                }
                if(d < code.length){
                    q = m;
                    //System.out.println(m);
                }
            }
            System.out.println();
            k --;
        }
    }

}
class HFMTree{
    //属性
    private int n;//结点数
    private HN[] hn;//结点数组
    public int getN() {
        return n;
    }
    public void setN(int n) {
        this.n = n;
    }
    public HN[] getHn() {
        return hn;
    }
    public void setHn(HN[] hn) {
        this.hn = hn;
    }
    public HFMTree(int n){
        this.n = n;
        this.hn = new HN[2*n-1];//有n个结点,创建2*n-1个数组空间
        for(int i=0;i<2*n-1;i++){
            hn[i] = new HN();//创建2*n-1个HN的对象
        }
    }
    
    public void init(int data[]){
        for(int i=0;i<data.length;i++){
            hn[i].setWeight(data[i]);
        }
    }
    //创建哈弗曼树
    public void create(){
        int min1=0,min2=0,i,j,temp;
        for(i=n;i<2*n-1;i++){
            for(j=0;j<i;j++){
                if(hn[j].getParent()==0){
                    min1=j;
                    break;
                }
            }
            j++;
            for(;j<i;j++){
                if(hn[j].getParent()==0){
                    min2=j;
                    break;
                }
            }
            if(hn[min1].getWeight()>hn[min2].getWeight()){
                temp = min1;
                min1 = min2;
                min2 = temp;
            }
            j++;
            for(;j<i;j++){
                if(hn[j].getParent()==0){
                    if(hn[j].getWeight()<hn[min1].getWeight()){
                        min2 = min1;
                        min1 = j;
                    }else{
                        if(hn[j].getWeight()<hn[min2].getWeight()){
                            min2 = j;
                        }
                        
                    }
                }
            }
            
            //上面的代码找到两个最小的,写到作为第i个左右孩子
            hn[i].setWeight(hn[min1].getWeight()+hn[min2].getWeight());
            hn[i].setLeft(min1);
            hn[i].setRight(min2);
            hn[min1].setParent(i);
            hn[min2].setParent(i);
            hn[i].setParent(0);
        }
    }
    
    //输出哈弗曼树
    public void PrintTree(){
        for(int i=0;i<2*n-1;i++){
            System.out.println(i+"	"+hn[i].getWeight()+"	"+hn[i].getLeft()+"	"+hn[i].getRight()+"	"+hn[i].getParent());
        }
    }
    //输出权数
    public void Quan(){
        for(int i=0;i<2*n-1;i++){
            System.out.print(hn[i].getWeight()+" ");
        }
        System.out.println();
    }
    //输出字符对应的代码方法一:
    public void PrintCode(int i){
        if(hn[i].getParent()==0)
            return;
        int p = hn[i].getParent();
        
        PrintCode(p);
        if(hn[p].getLeft()==i){
            System.out.print(0);
        }else{
            System.out.print(1);
        }
    }
    //输出字符对应的代码方法二:
    public String PrintCode2(int i){
        String codes="";
        if(hn[i].getParent()==0)
            return "";
        int p = hn[i].getParent();
        
        PrintCode(p);
        if(hn[p].getLeft()==i){
            codes+="0";
        }else{
            codes+="1";
        }
        return codes;
    }
    //方法三:
    public String PrintCode3(int i,String codes){
        while(hn[i].getParent() != 0){
            if(hn[hn[i].getParent()].getLeft() == i){
                codes = codes + "0";
            }
            if(hn[hn[i].getParent()].getRight() == i){
                codes = codes + "1";
            }
            i = hn[i].getParent();
        }
        String codes1 = "";
        for(int j=codes.length()-1;j>=0;j--){
            codes1 = codes1 + codes.charAt(j);
        }
        return codes1;
    }
    
    
}
class HN{
    private int weight;
    private int left;
    private int right;
    private int parent;
    public int getWeight() {
        return weight;
    }
    public void setWeight(int weight) {
        this.weight = weight;
    }
    public int getLeft() {
        return left;
    }
    public void setLeft(int left) {
        this.left = left;
    }
    public int getRight() {
        return right;
    }
    public void setRight(int right) {
        this.right = right;
    }
    public int getParent() {
        return parent;
    }
    public void setParent(int parent) {
        this.parent = parent;
    }
    public HN(int weight){
        this.weight = weight;
        this.left = 0;
        this.right = 0;
        this.parent = 0;
    }
    public HN(){
        this.weight = 0;
        this.left = 0;
        this.right = 0;
        this.parent = 0;
    }
}
class Code{
    private char ch;
    private String code;
    public char getCh() {
        return ch;
    }
    public void setCh(char ch) {
        this.ch = ch;
    }
    public String getCode() {
        return code;
    }
    public void setCode(String code) {
        this.code = code;
    }
    public Code(char ch,String code){
        this.ch = ch;
        this.code = code;
    }
}
原文地址:https://www.cnblogs.com/zoulingjin/p/8677061.html