欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python描述數(shù)據(jù)結(jié)構(gòu)學(xué)習(xí)之哈夫曼樹篇

 更新時間:2020年09月07日 10:38:46   作者:夏悠然然  
這篇文章主要給大家介紹了關(guān)于Python描述數(shù)據(jù)結(jié)構(gòu)學(xué)習(xí)之哈夫曼樹篇的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

前言

本篇章主要介紹哈夫曼樹及哈夫曼編碼,包括哈夫曼樹的一些基本概念、構(gòu)造、代碼實現(xiàn)以及哈夫曼編碼,并用Python實現(xiàn)。

1. 基本概念

哈夫曼樹(Huffman(Huffman(Huffman Tree)Tree)Tree),又稱為最優(yōu)二叉樹,指的是帶權(quán)路徑長度最小的二叉樹。樹的帶權(quán)路徑常記作:

其中,nnn為樹中葉子結(jié)點的數(shù)目,wkw_kwk​為第kkk個葉子結(jié)點的權(quán)值,lkl_klk​為第kkk個葉子結(jié)點與根結(jié)點的路徑長度。

帶權(quán)路徑長度是帶權(quán)結(jié)點和根結(jié)點之間的路徑長度與該結(jié)點的權(quán)值的乘積。有關(guān)帶權(quán)結(jié)點、路徑長度的概念請參閱這篇博客。

對于含有nnn個葉子結(jié)點的哈夫曼樹,其共有2n12n-12n−1個結(jié)點。因為在構(gòu)造哈夫曼樹的過程中,每次都是以兩顆二叉樹為子樹創(chuàng)建一棵新的二叉樹,因此哈夫曼樹中不存在度為1的結(jié)點,即n1=0n_1=0n1​=0,由二叉樹的性質(zhì)可知,葉子結(jié)點數(shù)目n0=n2+1n_0=n_2+1n0​=n2​+1,所以n2=n01n_2=n_0-1n2​=n0​−1,總結(jié)點數(shù)目為n=n0+n1+n2=n+n1=2n1n=n_0+n_1+n_2=n+n-1=2n-1n=n0​+n1​+n2​=n+n−1=2n−1。

2. 構(gòu)造過程及實現(xiàn)

給定nnn棵僅含根結(jié)點的二叉樹T1,T2,,TnT_1,T_2,\dots,T_nT1​,T2​,…,Tn​,它們的權(quán)值分別為w1,w2,,wnw_1,w_2,\dots,w_nw1​,w2​,…,wn​,將它們放入到一個集合FFF中,即F={T1,T2,,Tn}F=\{T_1,T_2,\dots,T_n\}F={T1​,T2​,…,Tn​};然后在集合FFF中選取兩棵權(quán)值最小的根結(jié)點構(gòu)造一棵新的二叉樹,使新二叉樹的根結(jié)點的權(quán)值等于其左、右子樹根結(jié)點的權(quán)值之和;再然后將選中的那兩個結(jié)點從集合FFF中刪除,將新的二叉樹添加到FFF中;繼續(xù)重復(fù)上述操作,直至集合FFF中只剩一棵二叉樹為止。

比如F={(A,3),(B,7),(C,2),(D,11),(E,13),(F,15),(G,9)}F=\{(A,3),(B,7),(C,2),(D,11),(E,13),(F,15),(G,9)\}F={(A,3),(B,7),(C,2),(D,11),(E,13),(F,15),(G,9)},它構(gòu)造出來的哈夫曼樹就是下面這棵二叉樹:

代碼實現(xiàn):

class HuffmanTreeNode(object):
 def __init__(self):
 self.data = '#'
 self.weight = -1
 self.parent = None
 self.lchild = None
 self.rchild = None


class HuffmanTree(object):
 def __init__(self, data_list):
 self.nodes = []
 # 按權(quán)重從大到小進行排列
 for val in data_list:
  newnode = HuffmanTreeNode()
  newnode.data = val[0]
  newnode.weight = val[1]
  self.nodes.append(newnode)
 self.nodes = sorted(self.nodes, key=lambda node: node.weight, reverse=True)
 print([(node.data, node.weight) for node in self.nodes])

 def CreateHuffmanTree(self):
 # 這里注意區(qū)分
 # TreeNode = self.nodes[:] 變量TreeNode, 這個相當(dāng)于深拷貝, TreeNode變化不影響nodes
 # TreeNode = self.nodes 指針TreeNode與nodes共享一個地址, 相當(dāng)于淺拷貝, TreeNode變化會影響nodes
 TreeNode = self.nodes[:]
 if len(TreeNode) > 0:
  while len(TreeNode) > 1:
  letfTreeNode = TreeNode.pop()
  rightTreeNode = TreeNode.pop()
  newNode = HuffmanTreeNode()
  newNode.lchild = letfTreeNode
  newNode.rchild = rightTreeNode
  newNode.weight = letfTreeNode.weight + rightTreeNode.weight
  letfTreeNode.parent = newNode
  rightTreeNode.parent = newNode
  self.InsertTreeNode(TreeNode, newNode)
  return TreeNode[0]

 def InsertTreeNode(self, TreeNode, newNode):
 length = len(TreeNode)
 if length > 0:
  temp = length - 1
  while temp >= 0:
  if newNode.weight < TreeNode[temp].weight:
   TreeNode.insert(temp+1, newNode)
   return True
  temp -= 1
 TreeNode.insert(0, newNode)

3. 哈夫曼編碼

在數(shù)據(jù)通信時,假如我們要發(fā)送ABCDEFG”“ABCDEFG”“ABCDEFG”這一串信息,我們并不會直接以這種形式進行發(fā)送,而是將其編碼成計算機能夠識別的二進制形式。根據(jù)編碼類型可將其分為固定長度編碼和可變長度編碼,顧名思義,固定長度編碼就是編碼后的字符長度都相同,可變長度編碼就是編碼后的字符長度不相同。這兩種類型有什么區(qū)別呢?我們來舉例說明一下:

A B C D E F G
固定長度編碼 000 001 010 011 100 101 110
可變長度編碼 0 1 01 10 11 101 110

ABCDEFG”“ABCDEFG”“ABCDEFG”這條信息使用固定長度編碼后的長度為21,使用可變長度編碼后的長度為14,報文變短,報文的傳輸效率會相應(yīng)的提高。但如果傳送的字符為BD”“BD”“BD”,按可變長度編碼后的報文為111”“111”“111”,但是在譯碼是就會出現(xiàn)BBB,BD,DB”“BBB”,“BD”,“DB”“BBB”,“BD”,“DB”多種結(jié)果,因此采用可變長度編碼時需要注意任一字符不能是其他字符的前綴,符合這樣的可變長度編碼稱為前綴編碼。

報文最短可以引申到二叉樹路徑最短,即構(gòu)造前綴編碼的實質(zhì)就是構(gòu)造一棵哈夫曼樹,通過這種形式獲得的二進制編碼稱為哈夫曼編碼。這里的權(quán)值就是報文中字符出現(xiàn)的概率,出現(xiàn)概率越高的字符我們用越短的字符表示。

以下表中的字符及其出現(xiàn)的概率為例來實現(xiàn)哈夫曼編碼:

字符 A B C D E F G H
出現(xiàn)概率 0.01 0.43 0.15 0.02 0.03 0.21 0.07 0.08
哈夫曼編碼 101010 0 110 101011 10100 111 1011 100


代碼實現(xiàn)就是在哈夫曼樹的基礎(chǔ)上加一個編碼的函數(shù):

 def HuffmanEncode(self, Root):
  TreeNode = self.nodes[:]
  code_result = []
  for index in range(len(TreeNode)):
   temp = TreeNode[index]
   code_leaf = [temp.data]
   code = ''
   while temp is not Root:
    if temp.parent.lchild is temp:
     # 左分支
     code = '0' + code
    else:
     # 右分支
     code = '1' + code
    temp = temp.parent
   code_leaf.append(code)
   code_result.append(code_leaf)
  return code_result

測試結(jié)果如下:

if __name__ == '__main__':
 tree_obj = HuffmanTree([('A', 0.01), ('B', 0.43), ('C', 0.15), ('D', 0.02), ('E', 0.03), ('F', 0.21), ('G', 0.07), ('H', 0.08)])
 huf_tree = tree_obj.CreateHuffmanTree()
 huf_code = tree_obj.HuffmanEncode(huf_tree)
 for index in range(len(huf_code)):
  print('{0}: {1}'.format(huf_code[index][0], huf_code[index][1]))

總結(jié)

到此這篇關(guān)于Python描述數(shù)據(jù)結(jié)構(gòu)學(xué)習(xí)之哈夫曼樹篇的文章就介紹到這了,更多相關(guān)Python數(shù)據(jù)結(jié)構(gòu)之哈夫曼樹內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • python模塊詳解之pywin32使用文檔(python操作windowsAPI)

    python模塊詳解之pywin32使用文檔(python操作windowsAPI)

    pywin32是一個第三方模塊庫,主要的作用是方便python開發(fā)者快速調(diào)用windows API的一個模塊庫,這篇文章主要給大家介紹了關(guān)于python模塊詳解之pywin32使用文檔的相關(guān)資料,文中將python操作windowsAPI介紹的非常詳細,需要的朋友可以參考下
    2024-01-01
  • 將圖片文件嵌入到wxpython代碼中的實現(xiàn)方法

    將圖片文件嵌入到wxpython代碼中的實現(xiàn)方法

    前面一篇文章中提到的那個程序,GUI中包含了一張圖片。在編譯成exe文件發(fā)布時,無法直接生成一個單獨的exe文件。因此需要直接把圖片寫入到代碼中
    2014-08-08
  • 淺談Pytorch 定義的網(wǎng)絡(luò)結(jié)構(gòu)層能否重復(fù)使用

    淺談Pytorch 定義的網(wǎng)絡(luò)結(jié)構(gòu)層能否重復(fù)使用

    這篇文章主要介紹了Pytorch定義的網(wǎng)絡(luò)結(jié)構(gòu)層能否重復(fù)使用的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • 基于matplotlib中ion()和ioff()的使用詳解

    基于matplotlib中ion()和ioff()的使用詳解

    這篇文章主要介紹了基于matplotlib中ion()和ioff()的使用詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-06-06
  • 基于python實現(xiàn)圖書管理系統(tǒng)

    基于python實現(xiàn)圖書管理系統(tǒng)

    這篇文章主要為大家詳細介紹了基于python實現(xiàn)圖書管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-04-04
  • 關(guān)于Flask 上下文詳細介紹

    關(guān)于Flask 上下文詳細介紹

    這篇文章主要給大家分享了關(guān)于Flask 上下文詳細介紹,我們可以把上下文理解為當(dāng)前環(huán)境的快照,是一個用來保存狀態(tài)的對象。在代碼執(zhí)行的某個時刻,根據(jù)上下文的代碼邏輯,可以決定在當(dāng)前時刻下使用到的環(huán)境變量等。下面一起進入文章了解詳情內(nèi)容,需要的朋友也可以參考一下
    2021-11-11
  • pytest使用parametrize將參數(shù)化變量傳遞到fixture

    pytest使用parametrize將參數(shù)化變量傳遞到fixture

    這篇文章主要為大家介紹了pytest使用parametrize將參數(shù)化變量傳遞到fixture的使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-05-05
  • Python導(dǎo)入或執(zhí)行python源文件的3種方法

    Python導(dǎo)入或執(zhí)行python源文件的3種方法

    這篇文章主要給大家介紹了關(guān)于Python導(dǎo)入或執(zhí)行python源文件的3種方法,python源代碼的文件以"py"為擴展名,由python.exe解釋,可以在控制臺下運行,需要的朋友可以參考下
    2023-08-08
  • Python NumPy創(chuàng)建數(shù)組方法

    Python NumPy創(chuàng)建數(shù)組方法

    這篇文章主要介紹了Python NumPy創(chuàng)建數(shù)組方法,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的朋友可以參考一下
    2022-09-09
  • Python中的JSON?Pickle?Shelve模塊特性與區(qū)別實例探究

    Python中的JSON?Pickle?Shelve模塊特性與區(qū)別實例探究

    在Python中,處理數(shù)據(jù)序列化和持久化是極其重要的,JSON、Pickle和Shelve是三種常用的模塊,它們提供了不同的方法來處理數(shù)據(jù)的序列化和持久化,本文將深入研究這三個模塊,探討它們的特性、用法以及各自的優(yōu)缺點
    2024-01-01

最新評論