1. 程式人生 > >No detail can be too detailed

No detail can be too detailed

這是在做一道程式設計提示遇到的,學習了一位博主的編碼,其中有些問題未能理解,分析解決掉。
首先什麼是哈夫曼樹:
哈夫曼樹,又稱最優二叉樹,是一類帶權路徑長度最短的樹。
也就是根節點到節點的中的長度最小,當然條件就是,每條路徑都是有權重的,
所謂樹的帶權路徑長度,就是樹中所有的葉結點的權值乘上其到根結點的 路徑長度(若根結點為0層,葉結點到根結點的路徑長度為葉結點的層數)。樹的帶權路徑長度記為WPL= (W1*L1+W2*L2+W3*L3+…+Wn*Ln)
這裡寫圖片描述

此時WPL=32×1+24×2+2×3+7×3

一般建立哈夫曼樹的步驟為
1,將所有左,右子樹都為空的作為根節點。
2,在森林中選出兩棵根節點的權值最小的樹作為一棵新樹的左,右子樹,且置新樹的附加根節點的權值為其左,右子樹上根節點的權值之和。注意,左子樹的權值應小於右子樹的權值。
3,從森林中刪除這兩棵樹,同時把新樹加入到森林中。
4,重複2,3步驟,直到森林中只有一棵樹為止,此樹便是哈夫曼樹。
太原理工網站給出了動畫演示

http://www.tyut.edu.cn/kecheng1/site01/suanfayanshi/Huffman.asp

上面提到的根據權重排序,選出權重最小的兩個,這個功能在優先佇列中完全可以做到。所以在構建哈夫曼樹時可以利用優先佇列

然後看看題目吧

Input
The input file will contain a list of text strings, one per line. The text strings will consist only of uppercase alphanumeric characters and underscores (which are used in
place of spaces). The end of the input will be signalled by a line containing only the word “END” as the text string. This line should not be processed. Output For each text string in the input, output the length in bits of the 8-bit ASCII encoding, the length in bits of an optimal prefix-free variable-length
encoding, and the compression ratio accurate to one decimal point. Sample Input AAAAABCD THE_CAT_IN_THE_HAT END Sample Output 64 13 4.9 144 51 2.8

這裡直接給出網上參考程式碼,然後分析

#include<stdio.h>  
#include<string.h>  
#include<ctype.h>  
#include<functional>  
#include<queue>  
using namespace std;  
#define M 1000050  
char str[M];   //全域性變數中 預設初始化為0;
int list[27];  

priority_queue< int,vector<int>,greater<int> >que;  



int main()  
{  
    int ans,sum;  
    int i,a,b,c;  
    while(scanf("%s",str),strcmp(str,"END")){  
        memset(list,0,sizeof(list));  
        for(i=0;str[i];i++){  
            if(isalpha(str[i]))  
                list[str[i]-'A']++;  
            else  
                list[26]++;  
        }  
        sum=i*8;ans=i;c=0;  //sum 為原等長編碼需要的bit位 ans為hfm編碼
        for(i=0;i<27;i++){  
            if(list[i]){  
                que.push(list[i]);  
                c++;  
            }  
        }         
        if(c>1) //c==1時,只有一種字母
        {
            ans=0;//注意只有一種字元的情況  
            while(que.size()!=1)
            {  
                a=que.top();  
                que.pop();  
                b=que.top();  
                que.pop();  
                ans+=a+b;  
                que.push(a+b);  
            }  
            while(!que.empty())//使用後清空佇列  
                que.pop();  
        }  
        printf("%d %d %.1f\n",sum,ans,1.0*sum/ans);  
    }  
    return 0;  
}  

1、輸入字串部分

for(i=0;str[i];i++){  
   if(isalpha(str[i]))  
    list[str[i]-'A']++;  
   else  
    list[26]++;  
  }  

在ctype.h中,是一個巨集,判讀是否為大寫字母
list是一個數組int list[27]統計26個字母和下劃線字元,用來統計多少個A、B,用字母到A的絕對距離作為陣列的下標,陣列對應的元素存放字母出現
的次數。這裡的寫法非常簡潔,陣列元素++的寫法,
2、編碼計數
sum=i*8;ans=i;c=0;
sum 為原等長編碼需要的bit位 ans為hfm編碼,i為字母的個數
3、利用優先佇列來考慮權重問題

for(i=0;i<27;i++){  
   if(list[i]){  
    que.push(list[i]);  
    c++;  
   }  
  }

將字母出現的次數作為權重,壓如佇列中,C用於記錄出現不同字母的個數。
3、模擬建立哈夫曼樹

if(c>1) //c==1時,只有一種字母
  {
   ans=0;//注意只有一種字元的情況  
   while(que.size()!=1)
   {  
    a=que.top();  
    que.pop();  
    b=que.top();  
    que.pop();  
    ans+=a+b;  
    que.push(a+b);  
   }  
   while(!que.empty())//使用後清空佇列  
    que.pop();  
  }  

while中的過程完全按照,上面提到的步驟來
如果加入輸入AAAABBBCCD,根據上面步驟會得到這樣一棵樹
這裡寫圖片描述
這樣編碼出來為
A: 0 1bit
B: 10 2bit
C: 110 3bit
D: 111 3bit
所以中的編碼位數就是出現次數×編碼bit
1×4+2×3+3×2+3×1=19
這個就是帶權路徑長度,因為出現的次數就是權重,編碼長度就是節點到根節點的層數,
如何在不把樹建立起來,求帶權路徑長度,只要將這些權重全部加起來即可,正如程式中所做的那樣
程式中
ans=(1+2)+(3+3)+(4+6);
這樣分解出來
(1+2)+((1+2)+3)+(4+((1+2)+3))
將(1+2)加了3次,實際就是加的層數。
所以ans就是這個哈夫曼樹的帶權路徑和。

相關推薦

No detail can be too detailed

這是在做一道程式設計提示遇到的,學習了一位博主的編碼,其中有些問題未能理解,分析解決掉。 首先什麼是哈夫曼樹: 哈夫曼樹,又稱最優二叉樹,是一類帶權路徑長度最短的樹。 也就是根節點到節點的中的長度最小,當然條件就是,每條路徑都是有權重的, 所謂樹的帶權路

spring pom文件報錯:提示no declaration can be found for element 'dubbo:service'.

net 技術 found cnblogs 點擊 找到 inf 提示 src 轉自:http://blog.csdn.net/happylife_haha/article/details/52755425 pom文件報錯:The matching wildcard is st

dubbo spring pom文件報錯:提示no declaration can be found for element 'dubbo:service'.

valid windows validate tex file lib window win fcm pom文件報錯:The matching wildcard is strict, but no declaration can be found for element

《Spring實戰》-- 'cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element' 錯誤的解決

tip c-c 面向切面 ng- join proc ima -a edi 在Eclipse中新建了一個maven項目學習Spring,在 service.xml 中配置 Spring,想要學習‘面向切面的Spring’,service.xml 內容如下: <bean

關於dubbo創建服務和引用服務時,會報錯:cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 問題的解決

一個 sch 系統 contex ips 分布 配置文件 prot 商城項目   在跟著做淘淘商城項目時,用到了dubbo,作為一個SOA架構的項目,分為表現層與服務層,自然地,為了各個層之間解耦合(或者最大限度地松耦合),我們使用了dubbo這樣一個alibaba開源的分

關於dubbo服務的xml配置檔案報錯的問題——The matching wildcard is strict, but no declaration can be found for element 'dubbo:application'

  在配置dubbo服務的過程中,經常會遇到雖然程式能夠跑起來,但是配置檔案一堆紅叉,雖然不影響功能,但是確實很讓人噁心。   報錯資訊如下:     解決方案:   下載一個dubbo.xsd檔案(就在dubbo.jar裡面)windows->preferrence->xm

spring pom檔案報錯:提示no declaration can be found for element 'dubbo:service'.

pom檔案報錯:The matching wildcard is strict, but no declaration can be found for  element 'dubbo:service'. 解決辦法: 找到dubbo的jar包,解壓後在META-INF

Spark Worker 啟動報錯:No subfolder can be created in

解決方案寫在前面:在spark-env.sh裡有個引數 SPARK_LOCAL_DIRS,是存放shuffle資料落盤的目錄,這個報錯就是這個目錄不存在導致的。建立目錄重啟worker,再將核數和記憶體均衡一下。 附錄一下報錯: 18/03/29 09:59:01

spring pom檔案報錯:提示no declaration can be found for element 'dubbo:service'.

pom檔案報錯:The matching wildcard is strict, but no declaration can be found for  element 'dubbo:service'. 解決辦法: 找到dubbo的jar包,解壓後在META-INF資

spring使用AOP時the prefix aop for element is not bound.和no declaration can be found錯誤

在使用<aop:config>標籤時,xml編譯錯誤報:the prefix aop for element "aop:config" is not bound錯誤 原因是:未在xml檔案頭部匯入xmlns:aop=“http://www.springframe

matching wildcard is strict, but no declaration can be found for element for

今天重灌了一下MyEclipse7.5,開啟原來的Flex專案,又報了以下兩個錯誤,之前解決過,但不想又出現,於是把它的解決方法貼出來,做個備忘!錯誤資訊為錯誤資訊 寫道cvc-complex-type.2.4.c: The matching wildcard is str

解決 There are no resources that can be added or removed from the server

nbsp source hat remove 沒有 部署項目 eclipse 中項 cli 網上下載了一個項目,在eclipse中部署時,加載項目到tomcat中項目名稱無法顯示,報出There are no resources that can be added or r

eclipse導入git項目出現There are no resources that can be added or removed from the server錯誤

ips ide 好的 編碼 ati 沒有 rec The 插件 上傳到git上的項目因為配置了過濾文件,將.settings文件和.project文件都過濾掉了,settings文件中主要存放的是各種插件配置,約束你可以更好的利用IDE進行編碼 因為將這兩個文件過濾掉

eclipse匯入git專案出現There are no resources that can be added or removed from the server錯誤

上傳到git上的專案因為配置了過濾檔案,將.settings檔案和.project檔案都過濾掉了,settings檔案中主要存放的是各種外掛配置,約束你可以更好的利用IDE進行編碼   因為將這兩個檔案過濾掉了,所以導致從git上拉下來的專案,加入到tomcat中是出現如下錯誤(There

ubuntu/wireshark: There are no interfaces on which a capture can be done.故障解決

在ubuntu安裝wireshare, 在啟動程式啟動wireshark.  點captrue->interface, 出現: There are no interfaces on which a capture can be done. 解決方法: 命令列啟動:(

Tomcat新增web專案出現There are no resources that can be added or removed from the server

在JavaEE專案開發時,從SVN上檢出程式碼.將專案新增到tomcat或jboss伺服器上出現There are no resources that can be added or removed f

check whether the subset(no need to be consective) and be sum of X

subsets [] bool else true ret code art size #include "stdafx.h" bool isSubsetSum(int set[], int n, int sum) { bool sumOfSubSet[100][1

MYSQL報警:Warning: Using a password on the command line interface can be insecure.

color col fig文件 成功 efault 如果 輸入 nbsp pre 問題描述:執行下面的語句,sql是執行成功了,但是出現了一個報警,報警看上去始終不舒服 mysql -hip -Pport -uuser -ppassword -e "use db;de

Warning: Using a password on the command line interface can be insecure.解決辦法

com localhost log dev title war cli too edit 轉自 http://www.cnblogs.com/sunss/p/6256706.html 被一個小朋友問到,直接公布答案: If your MySQL cli

Talbot basically sweating the idea and can be happy for the repeat functionality

appear cas actual pear value edi fort lte finally Practically no one enjoyed more NHL hockey when compared with Cam Talbot last time. It