Python 查找压缩文本的长度(哈夫曼编码)
给定一个由n个字符组成的文本和一个由哈夫曼编码生成的二叉树,使得叶节点具有属性:一个字符串(字符本身)和一个整数(其在文本中的频率)。从根到任何叶的路径表示其码字 我想写一个递归函数来计算压缩文本的长度,并找到它的大O复杂度 例如,如果我有文本Python 查找压缩文本的长度(哈夫曼编码),python,time-complexity,binary-tree,huffman-code,Python,Time Complexity,Binary Tree,Huffman Code,给定一个由n个字符组成的文本和一个由哈夫曼编码生成的二叉树,使得叶节点具有属性:一个字符串(字符本身)和一个整数(其在文本中的频率)。从根到任何叶的路径表示其码字 我想写一个递归函数来计算压缩文本的长度,并找到它的大O复杂度 例如,如果我有文本 abaccab 每个角色在哈夫曼树中都有相关的频率和深度: 4 / \ a:3 5 / \ b:2 c:2 那么压缩文本的总长度是11 我想到了这个,但它看起来很粗糙: def get_长度(节点,深度): #叶节
abaccab
每个角色在哈夫曼树中都有相关的频率和深度:
4
/ \
a:3 5
/ \
b:2 c:2
那么压缩文本的总长度是11
我想到了这个,但它看起来很粗糙:
def get_长度(节点,深度):
#叶节
如果node.left_child为无,node.right_child为无:
返回节点。频率*深度
#只有一个子节点
elif node.left_子项为None,node.right_子项为None:
返回get_长度(node.right_子节点,深度+1)
elif node.right\u子项为None,node.left\u子项为None:
返回get_长度(node.left_子级,深度+1)
#具有两个子节点的节点
其他:
返回get_长度(node.left_子项,深度+1)+get_长度(node.right_子项,深度+1)
获取长度(根,0)
复杂性:O(log2n),其中n是字符数
我该如何改进这一点?这种情况下的复杂性是什么?虽然查找压缩文本长度的复杂性应该是
O(n)
(利用simplelen
),但完成编码的时间复杂性应该是O(nlog(n))
。算法如下:
t1 = FullTree
for each character in uncompressed input do: #O(n)
tree_lookup(t1, character) #O(log(n))
在未压缩输入上循环是O(n)
,而在平衡二叉树中查找节点是O(log(n))
(O(n)
最坏情况或其他情况)。因此,结果是n*O(log(n))=>O(nlog(n))
。另外,请注意,查找复杂性的O(log2n)
是准确的,因为根据对数规则,可以简化为O(log(2)+log(n))=>O(k+log(n)),对于某些常数k。
但是,由于大O只检查最坏情况下的近似值,O(k+log(n))=>O(log(n))
您可以通过在二叉树中创建更简单的查找来改进二叉树:
from collections import Counter
class Tree:
def __init__(self, node1, node2):
self.right = node1
self.left = node2
self.value = sum(getattr(i, 'value', i[-1]) for i in [node1, node2])
def __contains__(self, _node):
if self.value == _node:
return True
return _node in self.left or _node in self.right
def __lt__(self, _node): #needed to apply sorted function
return self.value < getattr(_node, 'value', _node[-1])
def lookup(self, _t, path = []):
if self.value == _t:
return ''.join(map(str, path))
if self.left and _t in self.left:
return ''.join(map(str, path+[0])) if isinstance(self.left, tuple) else self.left.lookup(_t, path+[0])
if self.right and _t in self.right:
return ''.join(map(str, path+[1])) if isinstance(self.right, tuple) else self.right.lookup(_t, path+[1])
def __getitem__(self, _node):
return self.lookup(_node)
s = list('abaccab')
r = sorted(Counter(s).items(), key=lambda x:x[-1])
while len(r) > 1:
a, b, *_r = r
r = sorted(_r+[Tree(a, b)])
compressed_text = ''.join(r[0][i] for i in s)
虽然查找压缩文本长度的复杂性应该是
O(n)
(利用simplelen
),但完成编码的时间复杂性应该是O(nlog(n))
。算法如下:
t1 = FullTree
for each character in uncompressed input do: #O(n)
tree_lookup(t1, character) #O(log(n))
在未压缩输入上循环是O(n)
,而在平衡二叉树中查找节点是O(log(n))
(O(n)
最坏情况或其他情况)。因此,结果是n*O(log(n))=>O(nlog(n))
。另外,请注意,查找复杂性的O(log2n)
是准确的,因为根据对数规则,可以简化为O(log(2)+log(n))=>O(k+log(n)),对于某些常数k。
但是,由于大O只检查最坏情况下的近似值,O(k+log(n))=>O(log(n))
您可以通过在二叉树中创建更简单的查找来改进二叉树:
from collections import Counter
class Tree:
def __init__(self, node1, node2):
self.right = node1
self.left = node2
self.value = sum(getattr(i, 'value', i[-1]) for i in [node1, node2])
def __contains__(self, _node):
if self.value == _node:
return True
return _node in self.left or _node in self.right
def __lt__(self, _node): #needed to apply sorted function
return self.value < getattr(_node, 'value', _node[-1])
def lookup(self, _t, path = []):
if self.value == _t:
return ''.join(map(str, path))
if self.left and _t in self.left:
return ''.join(map(str, path+[0])) if isinstance(self.left, tuple) else self.left.lookup(_t, path+[0])
if self.right and _t in self.right:
return ''.join(map(str, path+[1])) if isinstance(self.right, tuple) else self.right.lookup(_t, path+[1])
def __getitem__(self, _node):
return self.lookup(_node)
s = list('abaccab')
r = sorted(Counter(s).items(), key=lambda x:x[-1])
while len(r) > 1:
a, b, *_r = r
r = sorted(_r+[Tree(a, b)])
compressed_text = ''.join(r[0][i] for i in s)
要查找压缩文本的确切总长度, 我不认为有任何办法可以单独处理每个独特的角色 以及它在文本中出现的次数计数,总共是O(n),其中n是文本中唯一字符的数量(同时n是哈夫曼树中叶节点的数量)。 有几种不同的方法来表示从哈夫曼码到明文字母的映射。二叉树表示法有助于找到压缩文本的确切总长度;树中总共有2*n-1个节点,其中n是文本中唯一字符的数量,递归扫描每个节点需要2*n-1次,这也相当于总共O(n)
要查找压缩文本的确切总长度, 我不认为有任何办法可以单独处理每个独特的角色 以及它在文本中出现的次数计数,总共是O(n),其中n是文本中唯一字符的数量(同时n是哈夫曼树中叶节点的数量)。 有几种不同的方法来表示从哈夫曼码到明文字母的映射。二叉树表示法有助于找到压缩文本的确切总长度;树中总共有2*n-1个节点,其中n是文本中唯一字符的数量,递归扫描每个节点需要2*n-1次,这也相当于总共O(n)