奇妙的算法【4】-漢諾塔&哈夫曼編碼

 

1,漢諾塔問題【仍是看了源碼才記起來的,記憶逐漸清晰】

  漢諾塔:漢諾塔(又稱河內塔)問題是源於印度一個古老傳說的益智玩具。大梵天創造世界的時候作了三根金剛石柱子,在一根柱子上從下往上按照大小順序摞着64片黃金圓盤。大梵天命令婆羅門把圓盤從下面開始按大小順序從新擺放在另外一根柱子上。而且規定,在小圓盤上不能放大圓盤,在三根柱子之間一次只能移動一個圓盤。角色變換!!!java

package com.cnblogs.mufasa;

public class Answer1_Hanoi {
    public static int Solution1(int i){//遞歸調用
        if(i==1){
            return 1;
        }else if(i==2){
            return 3;
        }else {
            return 2*Solution1(i-1)+1;
        }
    }

    public static int Solution2(int i) {//數學直接計算
        return (int) Math.pow(2,i)-1;
    }

    public static void Solution3(int i, String loc1, String loc2, String loc3) {//遞歸調用
        if (i == 1) {
            System.out.println("from " + loc1 + " to " + loc3);
            return;
        }
        Solution3(i - 1, loc1, loc3, loc2);//將LOC1中的除最後一個圓盤,所有搬到第二個柱子上去
        Solution3( 1, loc1, loc2, loc3);//將LOC1中最後一個圓盤,直接搬到第三個柱子上
        Solution3( i-1, loc2, loc1, loc3);//將LOC2上的全部圓盤搬到第三個柱子上去
    //瘋狂遞歸搬運,內部搬運的過程當中有的不能一次搬完,那麼問題就又進一步拆分下去了 } }

 

2,哈夫曼編碼【節省通訊帶寬】底層核心:①二叉樹;②優先隊列;徹底掌握

 

 

 

   注意:哈夫曼樹帶權路徑長度node

  哈夫曼編碼(Huffman Coding),又稱霍夫曼編碼,是一種編碼方式,哈夫曼編碼是可變字長編碼(VLC)的一種。Huffman於1952年提出一種編碼方法,該方法徹底依據字符出現機率來構造異字頭的平均長度最短的碼字,有時稱之爲最佳編碼,通常就叫作Huffman編碼(有時也稱爲霍夫曼編碼)。ide

  流程:①依照使用頻次進行由大到小排序;②構建二叉樹結構;③讀取數據 this

//結構很清晰明瞭編碼

package com.cnblogs.mufasa;

import java.util.HashMap;
import java.util.Map;
import java.util.PriorityQueue;

public class Answer2_Huffman2 {
    private class Node implements Comparable<Node> {//內部類
        char ch;
        int freq;
        boolean isLeaf;
        Node left, right;

        public Node(char ch, int freq) {//葉節點
            this.ch = ch;
            this.freq = freq;
            isLeaf = true;
        }

        public Node(Node left, Node right, int freq) {//父節點
            this.left = left;
            this.right = right;
            this.freq = freq;
            isLeaf = false;
        }

        @Override
        public int compareTo(Node o) {
            return this.freq - o.freq;
        }
    }
    public Map<Character, String> encode(Map<Character, Integer> frequencyForChar) {
        PriorityQueue<Node> priorityQueue = new PriorityQueue<>();//優先隊列,compareTo已經完善過
        for (Character c : frequencyForChar.keySet()) {//優先隊列輸入,至關於排序
            priorityQueue.add(new Node(c, frequencyForChar.get(c)));
        }
        while (priorityQueue.size() != 1) {//當只有一個節點的時候就是root節點
            Node node1 = priorityQueue.poll();//輸出
            Node node2 = priorityQueue.poll();
            priorityQueue.add(new Node(node1, node2, node1.freq + node2.freq));//新構建的父節點
        }
        return encode(priorityQueue.poll());//經由父節點進行輸出
    }
    
    private Map<Character, String> encode(Node root) {
        Map<Character, String> encodingForChar = new HashMap<>();
        encode(root, "", encodingForChar);
        return encodingForChar;
    }
    
    private void encode(Node node, String encoding, Map<Character, String> encodingForChar) {
        if (node.isLeaf) {
            encodingForChar.put(node.ch, encoding);
            return;
        }
        encode(node.left, encoding + '0', encodingForChar);
        encode(node.right, encoding + '1', encodingForChar);
    }

}

 

3,驗證程序

package com.cnblogs.mufasa;

import java.util.HashMap;
import java.util.Map;

public class Client {
    public static void main(String[] args) {
//        System.out.println(Answer1_Hanoi.Solution1(3));//輸出次數
//        System.out.println(Answer1_Hanoi.Solution2(3));//輸出次數
//        Answer1_Hanoi.Solution3(3,"1","2","3");//輸出次數

        char[] chars={'a','b','c','d','e'};
        int[] nums={5,1,9,8,3};
        HashMap<Character,Integer> hm=new HashMap<>();
        for(int i=0;i<chars.length;i++){
            hm.put(chars[i],nums[i]);
        }
        Answer2_Huffman2 huffma=new Answer2_Huffman2();
        Map<Character, String> hm1= huffma.encode(hm);

    }
}

/*
7
7
from 1 to 3
from 1 to 2
from 3 to 2
from 1 to 3
from 2 to 1
from 2 to 3
from 1 to 3

 */
相關文章
相關標籤/搜索