1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
| ''' 先回顾一下,数据存储空间知识。 位bit: 二进制数,例如1001就是"四位"的二进制数,表示若干状态。 字节byte: 1 字节 == 8 位,是计算机处理的基本单位。通常1个字节可以存入一个ASCII码,2个字节可以存放一个汉字国标码。 字: 计算机进行数据处理时,一次存取、加工和传送的数据长度称为字(word)。一个字通常由一个或多个(一般是字节的整数位)字节构成。例如286微机的字由2个字节组成,它的字长为16;486微机的字由4个字节组成,它的字长为32位机。 ASCII码: 由美国国家标准局(ANSI)制定的ASCII码(American Standard Code for Information Interchange,美国标准信息交换码),它已被国际标准化组织(ISO)定为国际标准,称为ISO 646标准。适用于所有拉丁文字字母,ASCII码有7位码和8位码两种形式
''' ''' 哈夫曼树
如何根据结点的不同查找频率构造更有效的搜索树?
带权路径长度WPL: 二叉树n个叶子结点,每个叶子结点带有权值 W(k),从根结点到叶子结点的长度为L(k) 每个叶子结点的带权路径长度之和 WPL = SUM(W(k)*L(k))
最优二叉树/哈夫曼树: WPL 最小的二叉树。 哈夫曼树不是堆!!只不过哈夫曼树的建立过程用最小堆会快一些。
'''
''' (我并不明白为什么这里用堆比排序效率高) '''
class HeapStruct_2(): def __init__(self,elements=[None],addre=0,capacity=0): self.elements = elements self.addre = addre self.capacity = capacity def MinHeapCreate(self,Capacity_Size): print(' 若插入数值,请确保插入数值在 0 以上 。结点容量为%d'%Capacity_Size) self.elements = [None] * (Capacity_Size+1) self.capacity = Capacity_Size self.elements[0] = self.MinData() print('self capacity = %s'%self.capacity) def MinData(self): return Node(0) def Insert(self,item): if self.IsFull(): print('最小堆已满') return i = self.addre + 1 if self.elements[0].weight >= item.weight: print('插入数值大小小于下限') return while self.elements[i//2].weight > item.weight: self.elements[i] = self.elements[i//2] i //= 2 self.elements[i] = item self.addre += 1 def IsFull(self): if self.addre == self.capacity: print( self.addre,self.capacity) return 1 return 0 def IsEmpty(self): if self.addre == 0: return 1 return def DeleteMin(self): if self.IsEmpty(): print('最小堆已空。') return minitem = self.elements[1] temp = self.elements[self.addre] self.elements[self.addre] = None self.addre -= 1 parent = 1 while parent*2 <= self.addre: left_child = parent * 2 if self.addre != left_child and self.elements[left_child+1].weight < self.elements[left_child].weight: child = left_child + 1 else: child = left_child if self.elements[child].weight <= temp.weight: self.elements[parent] = self.elements[child] parent = child elif self.elements[child].weight > temp.weight: self.elements[parent] = temp return minitem self.elements[parent] = temp return minitem
''' 哈夫曼树的建立算法: 1、 将 权值序列 建立最小堆,element_list 中存放树的结点,而不是单纯的数字。 2、 从最小堆中(按结点值)取出两个最小的元素,再(按结点值)求和建立根结点, 形成一个链表结构的树 T ,返回根结点。
3、 将求和形成的根结点插入最小堆, 此时堆中走了两个元素,来了一个新的元素,只不过这个新元素是 T 的根结点。 4、 重复1、2、3 步骤。直到堆中元素只有一个元素(作n-1次合并),完成世界线收束,哈夫曼树建立完毕。 此时堆中只有一个元素,而这个元素是哈夫曼树的根结点。
整体复杂度为 O(Nlog N) ''' class Node(): def __init__(self,weight=0,left=None,right=None): self.weight = weight self.left = left self.right = right class HFM_Tree(): def __init__(self,H): h = HeapStruct_2() h.MinHeapCreate(10) for i in H: h.Insert(Node(i)) for i in range(h.addre-1): T = Node() T.left = h.DeleteMin() T.right = h.DeleteMin() T.weight = T.left.weight + T.right.weight h.Insert(T) T = h.DeleteMin() self.HFM_tree = T def preorder(self,BT,list_=[]): if BT: list_.append(BT.weight) self.preorder(BT.left,list_) self.preorder(BT.right,list_) return list_
H = [1,2,3,4,5] hfm = HFM_Tree(H) list_ = hfm.preorder(hfm.HFM_tree) print(list_)
|