Python 查找压缩文本的长度(哈夫曼编码)

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_长度(节点,深度): #叶节

给定一个由n个字符组成的文本和一个由哈夫曼编码生成的二叉树,使得叶节点具有属性:一个字符串(字符本身)和一个整数(其在文本中的频率)。从根到任何叶的路径表示其码字

我想写一个递归函数来计算压缩文本的长度,并找到它的大O复杂度

例如,如果我有文本

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)
(利用simple
len
),但完成编码的时间复杂性应该是
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)
(利用simple
len
),但完成编码的时间复杂性应该是
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)