对于我正在处理的应用程序,我需要从嵌套元组创建列表,表示每个分支中包含的数据。
作为参考,元组代表一个霍夫曼树,例如:
tree = (1.0, (0.5, (0.25, (0.125, 'd'),(0.125, 'c')), (0.25, 'b')), (0.5,'a'))
这是从具有以下概率的霍夫曼例程创建的:
a:0.5, b:0.25, c:0.125, d:0.125
我想出一个看起来像
的列表[['a'],['b','c','d']]
我尝试过以下代码:
def makeList(tree):
if len(tree) == 2:
return [tree[0]]
else:
rightlist = []
leftlist = []
right = list(tree[1])
left = list(tree[2])
for i in range(1, len(right)):
rightlist.append(right[i])
for i in range(1, len(left)):
leftlist.append(left[i])
return [rightlist, leftlist]
然而,这会返回
[['a'],[(0.25, (0.125, 'd'),(0.125,'c')),(0.25,'b')]
这不是我想要的。
我怎样才能修改上面的代码以产生我想要的输出?
修改
我已经制作了一些给出平衡输入的代码:
('a',0.25), ('b', 0.25), ('c', 0.25), ('d',0.25)
产生我想要的输出:
[['a','b'], ['c','d']]
def makeList(tree):
if len(tree) == 2:
print("I'm in here")
return [tree[1]]
else:
right = tree[1]
left = tree[2]
rightlist = []
leftlist = []
for i in range(0, len(right)):
if type(right[i]) == tuple:
print('right: ' + str(right[i]))
rightlist.append(right[i][1])
for i in range(0, len(left)):
if type(left[i]) == tuple:
print('left: ' + str(left[i]))
leftlist.append(left[i][1])
return [rightlist, leftlist]
但是,它在以下输入(下面的输出)上失败:
exampleData = [(0.5, 'a'), (0.5,'b')]
[[],[[]]
exampleData = [(0.5, 'a'), (0.25,'b'), (0.25,'c')]
[[],['b'.'c']]
exampleData = [(0.5,'a'), (0.25,'b'), (0.125,'c'), (0.125,'d')]
[[]],['b',(0.125, 'd')]]
但是,需要通过的黄金标准测试是为随机树创建这些列表:
probs = np.random.dirichlet([1]*4).tolist()
indices = range(0,4)
exampleData = zip(probs, indices)
huffTree = makeHuffmanTree(exampleData)
groups = makeLists(groups)
答案 0 :(得分:2)
我有一个递归的解决方案。
def makeListAndFlatten(tree):
treeList = makeList(tree)
branchA = treeList[0]
branchB = treeList[1]
flatA = flatten(branchA)
flatB = flatten(branchB)
return [flatA, flatB]
def makeList(tree):
if len(tree) == 2:
return tree[1]
else:
for i in range(1,len(tree)):
return [tree[len(tree)-1][1], makeList(tree[i])]
def flatten(nestedList):
def aux(listOrItem):
if isinstance(listOrItem, list):
for elem in listOrItem:
for item in aux(elem):
yield item
else:
yield listOrItem
return list(aux(nestedList))
如果我们跑:
makeListAndFlatten(tree)
这给出了结果:
[['a'], ['b', 'c', 'd']]
包含两个列表的列表,其中包含两侧下部分支的叶子。
修改强>
此代码基于原始问题中给出的格式:
tree =(1.0,(0.5,(0.25,(0.125,'d'),(0.125,'c')),(0.25,'b')),(0.5,'a'))
如果输入格式被更改,那么这将无效。
答案 1 :(得分:1)
鉴于你已经拥有了这棵树,最多有两个分支:
import Queue
def leaves(tree):
result = []
queue = Queue.Queue()
queue.put(tree)
while not queue.empty():
node = queue.get()
if type(node[1]) == tuple:
for subnode in node[1:]:
queue.put(subnode)
else:
result.append(node[1])
return result
def makeList(tree):
if len(tree) == 2:
return [tree[1]]
left = tree[1]
right = tree[2]
return [leaves(left), leaves(right)]
这需要两个分支并抓住每个分支的叶子,丢弃每个叶子的前半部分。它使用广度优先搜索来避免递归问题。
我无法将exampleData
列表转换为树来测试它们,但它适用于第一个问题。
答案 2 :(得分:0)
似乎是一般算法,你需要一个函数,它(1)计算下面树的总重量,然后(2)实现树旋转以旋转树,直到你得到平衡。也就是说,这在某种程度上只是标准树平衡算法的变体,除了对于AVL树,例如,你在平衡深度,这里你平衡数据本身的权重。