閑來無事寫寫-Huffman樹的生成過程


前言:最近項目上一直沒事干,感覺無聊到了極點,給自己找點事做,補一下大學沒有完成的事情,寫一個huffman算法Java版的,學校里面寫過c語言的。

因為很久沒搞數據結構和算法這方面了(現在搞Java web,真心感覺沒什么挑戰啊),代碼寫的一般,邊聽歌邊寫,3小時,不知道為什么現在效率這么低,寫習慣了

xml配置,感覺純寫算法代碼手生的緊,悲呼唉哉!

1、哈夫曼樹:

        給定n個權值作為n個葉子結點,構造一棵二叉樹,若帶權路徑長度達到最小,稱這樣的二叉樹為最優二叉樹,也稱為哈夫曼樹(Huffman tree)

2、生成過程:

       1. 在n個權值里面首先尋找最小的兩個權值作為子節點,開始生成第一棵子樹;

       2.將新子樹的父節點作為一個新的權值與剩余的權值繼續做比較,選出最小的兩個權值繼續構造新子樹;

       3.依次進行,直到最后一棵子樹生成;

       4.這時候,最后一棵子樹的根節點就是整個哈夫曼樹的根節點,從此根節點開始遍歷,就能遍歷完整個哈夫曼樹。

3、圖形表示:

        假設有6個權值:1、2、3、4、5、6,生成哈夫曼樹的過程如下:

       

      

依次下去...

這樣,最終得到的父節點21就是哈夫曼樹的根節點,遍歷樹的話,

c/c++就是:root->left  root->right就可以通過遞歸的方式從root節點訪問到最后一個子節點。

Java就是:   root.left   root.right通過遞歸從root訪問到最后一個子節點。

當然,二叉樹的遍歷不止遞歸一種方法,遞歸是最有效率的一種,還可以通過數據結構里面堆/棧的方式進行遍歷。

下面是我寫的實現哈夫曼樹的Java代碼(為了完成功能,絕壁不是優秀的,但可以方便看懂)

注:儲存權值使用了List列表,隨時增或者刪方便一點。

  1 import java.util.ArrayList;
  2 import java.util.List;
  3 
  4 class Node
  5 {
  6     int weight;
  7     Node left,right,parent;
  8     public Node(int weight)
  9     {
 10         this.weight=weight;
 11     }
 12 }
 13 public class Huffman {
 14     private static List<Node> list=new ArrayList<Node>();
 15     public  static Node root;
 16     public void insert(Node node)
 17     {
 18         //按照插入排序的方式將節點有序插入list
 19         if(list.size()==0){
 20             list.add(node);
 21             return;
 22         }
 23         int size=list.size();
 24         for(int i=0;i<size;)
 25         {
 26             if(list.get(i).weight<node.weight){
 27                 i++;
 28                 if(i>=list.size())
 29                     list.add(node);
 30             }
 31             else
 32             {
 33                 //交換位置
 34                 list.add(list.get(list.size()-1));
 35                 for(int j=list.size()-1;j>i;j--)
 36                 {                    
 37                     list.set(j, list.get(j-1));
 38                 }
 39                 list.set(i, node);//插入新數據
 40                 return;
 41             }
 42             
 43         }
 44         
 45     }
 46     public Node createTree(Node n1,Node n2)
 47     {
 48         //返回新子樹的父節點
 49         Node parentNode=new Node(0);
 50         parentNode.weight=n1.weight+n2.weight;
 51         parentNode.left=n1;
 52         parentNode.right=n2;
 53         n1.parent=parentNode;
 54         n2.parent=parentNode;      
 55         return parentNode;
 56     }
 57     public void run(List<Node> list)
 58     {
 59         int length=list.size();        
 60         while(length!=0)
 61         {
 62             if(length==1){
 63                 root=list.get(0);
 64                 return;
 65             }
 66             if(length==2){
 67                 root=createTree(list.get(0),list.get(1));
 68                 return;
 69             }  
 70             Node n1=list.get(0);
 71             Node n2=list.get(1);
 72             Node newNode=createTree(n1,n2);
 73             for(int i=0;i<length-2;i++)
 74             {
 75                 //轉移數據
 76                 list.set(i, list.get(i+2));
 77             }
 78             list.remove(length-1);
 79             list.remove(length-2);
 80             insert(newNode);
 81             length=list.size();
 82         }
 83         
 84     }
 85     public void display(Node node)
 86     {
 87         if(node!=null)
 88         {
 89             display(node.left);
 90             System.out.print(node.weight+"\t");
 91             display(node.right);
 92         }
 93     }
 94     public void drawTree(Node node)
 95     {
 96         if(node!=null)
 97         {
 98             //中序遍歷,打算打印樹形狀,有些麻煩,后面改進
 99 //            if(node.parent!=null&&node.parent.left==node)
100 //                System.out.print("/");
101 //            if(node.parent!=null&&node.parent.right==node)
102 //                System.out.print("\\");
103             System.out.print(node.weight+"\t");
104             drawTree(node.left);
105             drawTree(node.right);
106         }
107     }
108     public static void main(String[] args)
109     {
110         Huffman hf=new Huffman();
111         hf.insert(new Node(1));
112         hf.insert(new Node(2));
113         hf.insert(new Node(3));
114         hf.insert(new Node(4));
115         hf.insert(new Node(5));
116         hf.insert(new Node(6));
117         hf.run(list);
118         System.out.println("前序遍歷");
119         hf.display(root);
120         System.out.println("\n中序遍歷");
121         hf.drawTree(root);
122     }
123 }

執行結果:

后面,將寫通過哈夫曼解析具體報文。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM