Python 如何从数字列表生成所有可能的最大堆?

Python 如何从数字列表生成所有可能的最大堆?,python,algorithm,tree,heap,max-heap,Python,Algorithm,Tree,Heap,Max Heap,最大堆可以在同一棵树本身中具有任意分支因子 例如,在给定[8,5,3,1]的情况下,可能会生成一些堆 8 or 8 or 8 /|\ | | 5 1 3 5 5 and so on..... (a) / \ | 3 1

最大堆可以在同一棵树本身中具有任意分支因子

例如,在给定[8,5,3,1]的情况下,可能会生成一些堆

  8      or       8       or    8        
 /|\              |             |
5 1 3             5             5           and so on.....
 (a)             / \            |
                3   1           3
                 (b)            |
                                1
                               (c)

对于我的目的,我认为树(a)与树(d)和(e)低于

相同。 编辑:


(1) 我尝试了一种算法来生成所有可能的树,然后根据max heap属性进行过滤。但很明显,这是指数型的,因此在Python中,即使是包含超过10个元素的列表也需要一段时间


(2) 因此,我只想构造那些服从max heap属性的树,而不是过滤树,但无法由此构造递归子问题。

这一个比无限制树生成器简单得多

有趣的是,对于
k
元素,确实存在
(k-1)可能的常规堆。(如果我们正在生成堆的森林,那么可能会有
k!
森林,这相当于生成一个以新节点为根的单堆。)

关键的洞察是heap属性保证任何子树的最大元素都是该子树的根(因此最大的元素就是树的根)。因为我们不关心子元素的顺序,所以我们可以同意在每个节点上按降序排列子元素,这将保证子树中第二大元素正好是该子树根的最左边的子元素

所以我们可以按降序放置元素,迭代所有可能的放置。在我们将最大的元素作为树的根之后,接下来的每个元素都可以成为任何先前放置的元素的最后(或唯一)子元素。(所有先前放置的子元素都比新元素大,因此将其放在第一个位置会保持规范的子元素顺序。当然,由于所有先前放置的元素都较大,新元素可以是其中任何一个元素的子元素。)

通过该过程,在已放置
i
元素的步骤中,下一个元素正好存在
i
可能的位置。因此,公式
(k-1)

实现上述功能非常简单,尽管它不是一个功能解决方案:候选树在每一步都会被修改。(这意味着,如果要修改或保留已生成的树以供将来参考,则需要对其进行完整复制。)

以下是从8、5、3、1构建的六个堆:

>>> print('\n'.join(map(str,allheaps("8531"))))
(8 5 3 1)
(8 (5 1) 3)
(8 5 (3 1))
(8 (5 3) 1)
(8 (5 3 1))
(8 (5 (3 1)))
或者,用图解法(手工完成)

堆的数量是非根节点数量的阶乘这一事实表明堆和置换之间存在同构。确实有,从上面的图表可以看出

我们可以通过对树进行后序深度优先遍历,将堆转化为置换。后序遍历保证漫游中的最后一个节点是根节点

另一方面,从以根标签结尾的排列到堆,我们初始化一个空堆栈并从左到右扫描排列。我们首先通过从堆栈顶部弹出任何较小的元素来填充其子列表,然后将每个标签推送到堆栈上。如果排列以最大的元素结束,它将是扫描结束时堆栈上的唯一元素。(如果我们允许任意排列,我们将得到
n!
堆林,而不是
(n-1)!
根堆。)

这表明我们可以通过使用枚举置换和从置换构造堆的任何方便方法来枚举堆:

from itertools import permutations
from functools import reduce
def putlabel(stk, label):
    kids=[]
    while stk and stk[-1].root < label: kids.append(stk.pop())
    stk.append(tree(label, kids))
    return stk

def permtoheap(root, perm):
    '''Construct a heap with root 'root' using the non-root nodes from
       a postorder walk. 'root' should be larger than max(perm); otherwise,
       the result will not satisfy the heap property.
    '''
    return tree(root, reduce(putlabel, perm, []))

def allheaps2(labels):
    if labels:
        yield from (permtoheap(labels[0], p) for p in permutations(labels[1:]))
从itertools导入置换
从functools导入reduce
def标签(stk,标签):
孩子们=[]
而stk和stk[-1].root
到目前为止您尝试了什么?我尝试了一种算法来生成所有可能的树,然后根据max heap属性进行过滤。但很明显,这是指数型的,因此在Python中,即使是包含超过10个元素的列表也需要一段时间。为什么会有这么多的否决票?不是否决票,但这个问题缺乏努力,请发布您尝试过的内容,即使它不起作用。此外,这个问题是一个比较宽泛的问题,感觉像是一个“给我代码”类型的问题,通常不太受欢迎。我的建议是改进这个问题,发布您尝试过的代码,并在formSee中解释它的错误,您可以将其扩展到d进制堆。对于非标准堆类型(示例b),您可以自己操作。在生成树之前,您可能需要复制它。这段代码一次又一次地生成同一个对象,因此试图将结果收集到一个列表中或做任何事情来存储这些树都会导致出现问题。@user2357112:是的,这可能很好。但这只是为了展示算法。在功能上也可以做到这一点,但Python并不是真正的功能性语言。(此外,如果大多数堆立即被拒绝,那么复制将是浪费时间;最好只复制需要的堆。)
>>> print('\n'.join(map(str,allheaps("8531"))))
(8 5 3 1)
(8 (5 1) 3)
(8 5 (3 1))
(8 (5 3) 1)
(8 (5 3 1))
(8 (5 (3 1)))
(8 5 3 1) (8 (5 1) 3) (8 5 (3 1)) (8 (5 3) 1) (8 (5 3 1)) (8 (5 (3 1)))
    8          8           8           8           8            8
  / | \      /   \       /   \       /   \         |            |
 5  3  1    5     3     5     3     5      1       5            5
            |                 |     |            /   \          |
            1                 1     3           3     1         3
                                                                |
                                                                1
from itertools import permutations
from functools import reduce
def putlabel(stk, label):
    kids=[]
    while stk and stk[-1].root < label: kids.append(stk.pop())
    stk.append(tree(label, kids))
    return stk

def permtoheap(root, perm):
    '''Construct a heap with root 'root' using the non-root nodes from
       a postorder walk. 'root' should be larger than max(perm); otherwise,
       the result will not satisfy the heap property.
    '''
    return tree(root, reduce(putlabel, perm, []))

def allheaps2(labels):
    if labels:
        yield from (permtoheap(labels[0], p) for p in permutations(labels[1:]))