Huffman樹與最優二叉樹續

  OK,昨天咱們對huffman數的基本知識,以及huffman樹的建立作了一些簡介,http://www.cnblogs.com/Frank-C/p/5017430.htmlhtml

今天接着聊:數組

huffman樹建立完成以後,咱們如何去獲得huffman編碼呢?編碼

image

                                                  圖12.4_1 huffman樹形結構spa

 

                                               圖12.4_2  huffman存儲結構(數組)3d

 

首先,以上面的樹爲例,咱們必須明白幾個要點: 指針

       1:從什麼地方開始訪問這顆樹:根節點 , index 2n-1 = 15code

       2:訪問的規則:向左爲0  向右爲1htm

       3:以什麼樣的訪問循序去訪問呢?blog

            好說,get

                   (1): 詢問是否有左孩子,一直向左走,直到左孩子爲零,若是此時右孩子也爲零,證實已經找到了一個葉子結點(信息元)。(固然,在訪問的同時進行編碼記錄)

                   (2): 原路返回一層(編碼同時減一),詢問是否有右孩子,有,進入右孩子,無,再返回上一層

                   一直重複(1)和(2)步,直到最終回退到更節點,在回到根節點的parent,即此時迭代器(index)爲零

固然,我只是說了一下大概的步驟,具體的代碼實現,還得是細之又細,往下看!!!!!!   有木有

*HC=(HuffmanCode)malloc((n+1)*sizeof(char*));
   /* 分配n個字符編碼的頭指針向量([0]不用) */
   cd=(char*)malloc(n*sizeof(char)); /* 分配求編碼的工做空間   即傳遞(temp)空間*/
   c=m;   //直接指向最上面那個非葉子節點
   cdlen=0;
   for(i=1;i<=m;++i)/* 遍歷赫夫曼樹時用做結點狀態標誌  直接把所有節點置爲零   此時這棵樹已經創建了   故權重已經沒有多大用處了*/
     (*HT)[i].weight=0; 
   while(c)
   {
     if((*HT)[c].weight==0)   //負責向左
     { /* 向左 */
       (*HT)[c].weight=1;   /* ************* */
       if((*HT)[c].lchild!=0)   /*若是權爲零的左孩子節點不是第一個元素(下標爲0)*/
       {
         c=(*HT)[c].lchild;
         cd[cdlen++]='0';
       }
       /*看這個左孩子有沒有右孩子  若是右孩子爲零(即沒有右孩子),那麼是一個葉子節點*/
       else if((*HT)[c].rchild==0)   
       { /* 登記葉子結點的字符的編碼 */
         (*HC)[c]=(char *)malloc((cdlen+1)*sizeof(char));
         cd[cdlen]='\0';
         strcpy((*HC)[c],cd); /* 複製編碼(串) */
       }
     }        
     /*條件改變*/
     else if((*HT)[c].weight==1)   /*負責向右   只會回退 不會動    判斷是左孩子是葉子節點仍是中間的內點*/
     { /* 向右 */
       (*HT)[c].weight=2;   /////************           
       if((*HT)[c].rchild!=0)   //決定你這個權值此時會不會被清零
       {
         c=(*HT)[c].rchild;
         cd[cdlen++]='1';
       }
     }
     else  //負責回退
     { /* HT[c].weight==2,退回 */
       (*HT)[c].weight=0;  /////**************
       c=(*HT)[c].parent;
       --cdlen; /* 退到父結點,編碼長度減1   迭代:利用前面走過的路*/
     }
   }
   free(cd);

  上面代碼經過一個weight(在while語句執行以前就已經被清零了哦哦哦),來判斷當前節點(葉子節點的狀況除外):(只做爲過程說明,不是狀態判斷條件)

                                                   未被訪問或已經被訪問且沒有用了:  0

                                                   正在訪問左樹且「右樹尚未訪問」(固然這是廢話): 1

                                                   正在訪問右樹且 」左樹已經訪問「  (固然這也是廢話): 2

何時回退,左節點沒有或已經訪問完,且,右節點沒有或已經訪問玩,如何保證以前這些個條件呢。簡單,if else分支語句的做用體現出來了,把負責回退的判斷語句放在最後,前面來判斷有左孩子木有哈,有右孩子木有啊,沒有,證實找到一個葉子節點(信息元),記錄信息,此時,此葉子節點weight已經被置爲1,那麼最中被置爲2且沒有右節點,進入最後一個else分支,置爲零且回退。

 

當分支節點爲1是(此時左節點已經被訪問),會首先被置爲2,詢問是否有右節點,有進入,即注意,當前節點若是是父節點的右孩子,字此時的父節點weight定被置爲了二,當此節點爲葉子節點且符合上面的葉子節點回退規則時,回退到父節點,父節點有爲2,繼續回退。

 

總結:代碼分支語句分紅了三個主分支塊   weight爲0(判斷是否未訪問過的節點)     weight爲1(判斷是否爲左樹已經訪問)    weight爲2,節點weight須要進行清零且回退

對於葉子節點,則主要有第一個分支塊進行處理,並由第二和三個分支塊進行輔助判斷與回退。

 

 

如何去經過編碼反編譯成信息或信息元,我想着就再簡單不過了,至少比編碼的建立容易吧,直接根據樹以必定的規則去找(如,0:左孩子, 1:右孩子),  鑑於每一個信息元的獨立性與信息元之間的無包含性,既適合反編碼,有適合找錯誤。

 

OK,That’s  all!!!

相關文章
相關標籤/搜索