哈夫曼編碼的非樹節點形式實現

楔子

今日心血來潮參加了某廠家的機試,牛客網上機試,一看只有一題且時間90分鐘200分,允許使用本地IDE,就知道肯定幾分鐘出不來,看題目可喜的是秒懂哈夫曼編碼,可悲的是一年半以前學的樹圖數據結構都忘光了。

思考過程

我知道用優先級隊列+樹可以實現,可是heapq和二叉樹一年多沒用了,只知道用numpy和pandas汗顏,於是慌了一逼。

於是想自己寫一個headq

反正排序用sort()不用自己寫,heapq也好實現,後來怕耗時太多,heapq勉強想起來怎麼用,稍微試了一下,用起來沒問題

構建二叉樹實在太久了,完全不讓看文檔,不敢不相信在有限的時間裏可以調試成功,於是就想了使用非樹的實現方式,就是把手動畫的二叉樹,從樹葉往上補充哈夫曼編碼

from heapq import *
# 輸入,轉化爲list
strs = input()
strs = [i for i in strs]

# 去重
str_single = set(strs)

# 按照詞頻入優先級隊列
hq =[]
for s in str_single:
    heappush(hq,(strs.count(s),s))

# 初始化明文字典
result = {}
for i in str_single:
    result[i] = ''

# 從樹葉往上構建哈夫曼編碼
while hq:
    left = heappop(hq)
    if hq:
        right = heappop(hq)
        # 取兩個最小詞頻的節點,單個字母優先在左邊
        if left[0] == right[0]:
            if len(left[1]) > len(right[1]):
                left,right = right,left
        # 左邊對應編碼加0,非單個單詞比如‘cd',那麼對應的c和d的哈夫曼編碼均需要加0
        for i in left[1]:
            result[i] +=  '0'
        # 右邊對應編碼加1
        for i in right[1]:
            result[i] +=  '1'
        # 把合成節點放入優先隊列
        heappush(hq,(left[0]+right[0],left[1]+right[1]))
    else:
        break

# 最後結果對應哈夫曼編碼是反的,故反轉一下
for k,v in result.items():
    v = [i for i in v]
    result[k] = ''.join(v[::-1])
# 輸出結果
for i in strs:
    print(''.join(result[i]),end='')

總結

還是好好再複習一下樹和圖吧,否則連面試機會都沒有,汗顏!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章