Algorithm 多数树评价

Algorithm 多数树评价,algorithm,tree,ternary-tree,Algorithm,Tree,Ternary Tree,考虑一个深度为h的完整三元树,由一根根连接到三个深度为h-1的完整三元树组成。有n=3^h个叶,每个叶都有一个与之关联的布尔值。每个内部节点(包括根节点)都等于其大多数子节点的值 下面是深度为2的树的示例: 给定树叶输入向量[0,0,1,0,1,0,1,0,1,1],我们希望找到树的根。为了找到根,我们可以计算所有叶和内部节点(即3^h操作)。但我们可能能够计算更少的节点。在上面的示例中,我们可以看到第一个内部节点(最左侧)的值可以在检查其前两个子节点后进行计算。类似地,在depth=1时,前

考虑一个深度为h的完整三元树,由一根根连接到三个深度为h-1的完整三元树组成。有n=3^h个叶,每个叶都有一个与之关联的布尔值。每个内部节点(包括根节点)都等于其大多数子节点的值

下面是深度为2的树的示例:

给定树叶输入向量[0,0,1,0,1,0,1,0,1,1],我们希望找到树的根。为了找到根,我们可以计算所有叶和内部节点(即3^h操作)。但我们可能能够计算更少的节点。在上面的示例中,我们可以看到第一个内部节点(最左侧)的值可以在检查其前两个子节点后进行计算。类似地,在depth=1时,前两个节点足以找到树的根

我一直在考虑这个问题,但找不到解决这个问题的好办法

import numpy as np
import random

class node:
def __init__(self):
    self.low = None
    self.mid = None
    self.high = None

def put(self, low, mid, high):
    self.low = low
    self.mid = mid
    self.high = high
    return self

class ternary_tree:

def __init__(self, leaves, count= 0):
    self.leaves = leaves
    self.root = node()
    self.value = None
    self.count = count

def get_root(self):
    self.root.put(self.leaves[0], self.leaves[1], self.leaves[2])
    self.value = majority(self.root)
    return self.value

def majority(node):
    global ops_count
    r1, r2, r3 = random.sample([node.low, node.mid, node.high], 3)
    if r1 > 0:
        ops_count += 1
        if r2 > 0:
            ops_count += 1
            return 1;
        elif r3 > 0:
            ops_count += 1
            return 1;
        else:
            return 0;
    else:
        ops_count += 1
        if r2 == 0:
            ops_count += 1
            return 0;
        elif r3 == 0:
            ops_count += 1
            return 0;
        else:
            return 1;

if __name__ == "__main__":
    h = 2 # depth of the tree
    my_leaves = [random.randint(0,1) for i in range(0, 3**h)] #input vector
    ops_count = 0 #Counting the number of steps
    nb_trees = len(my_leaves) // 3
    my_trees = [ternary_tree(leaves=my_leaves[i:i+3]) for i in range(0, nb_trees)]
    new_leaves = []
    t1, t2, t3 = random.sample(my_trees, 3)
    new_leaves.append(t1.get_root())
    new_leaves.append(t2.get_root())
    if new_leaves[0] == new_leaves[1]:
        new_leaves.append(new_leaves[0])
    else:
        new_leaves.append(t3.get_root())
    ternary_tree(leaves=new_leaves).get_root()
我认为代码可以完成这项工作,但它不是最优的,因为它仍然检查所有内部节点,并且不跳过冗余节点。我认为正确的方法是使用递归算法,比如二叉搜索树,但我无法将BST与多数树求值联系起来

如果你能告诉我如何解决这个问题,我将不胜感激。谢谢


这个例子来自这里:。

事实上,递归将是找到根值的方法。我真的不认为有必要创建树数据结构:当所有叶值的值作为列表输入时,我们就真的有了合适格式的所有信息

以下是当只给出叶值列表时,
多数
函数的外观:

import random

def majority(leaves):
    counter = 0

    def recur(start, size):
        nonlocal counter
        if size == 1:
            counter += 1  # about to access a leaf's value
            return leaves[start]
        size //= 3
        # Randomly choose which child we will leave as "plan B" in case
        #  two others give opposite values
        last = random.randint(0, 2)
        # Get the values of the two other children, using recursion
        val1 = recur(start + ((last+1)%3)*size, size)
        val2 = recur(start + ((last+2)%3)*size, size)
        # If equal, we do not need to retrieve the remaining child's value
        if val1 == val2:
            return val1
        # Too bad,... we need the value of the third child to break the tie
        return recur(start + last*size, size)
    
    rootval = recur(0, len(leaves))
    return rootval, counter
你可以这样称呼它:

h = 2
leaves = [random.randint(0,1) for i in range(0, 3**h)]

rootval, counter = majority(leaves)

print("The leaves are {}".format(leaves))
print("Accessed {} leaves to find that root's value is {}".format(counter, rootval))

事实上,递归将是找到根值的方法。我真的不认为有必要创建树数据结构:当所有叶值的值作为列表输入时,我们就真的有了合适格式的所有信息

以下是当只给出叶值列表时,
多数
函数的外观:

import random

def majority(leaves):
    counter = 0

    def recur(start, size):
        nonlocal counter
        if size == 1:
            counter += 1  # about to access a leaf's value
            return leaves[start]
        size //= 3
        # Randomly choose which child we will leave as "plan B" in case
        #  two others give opposite values
        last = random.randint(0, 2)
        # Get the values of the two other children, using recursion
        val1 = recur(start + ((last+1)%3)*size, size)
        val2 = recur(start + ((last+2)%3)*size, size)
        # If equal, we do not need to retrieve the remaining child's value
        if val1 == val2:
            return val1
        # Too bad,... we need the value of the third child to break the tie
        return recur(start + last*size, size)
    
    rootval = recur(0, len(leaves))
    return rootval, counter
你可以这样称呼它:

h = 2
leaves = [random.randint(0,1) for i in range(0, 3**h)]

rootval, counter = majority(leaves)

print("The leaves are {}".format(leaves))
print("Accessed {} leaves to find that root's value is {}".format(counter, rootval))

需要实际创建树数据结构吗?不需要。需要实际创建树数据结构吗?不需要。谢谢!我必须在我的递归思维上多做一些工作。现在我看到了你的解决方案,看起来很简单。我会继续练习的。非常感谢!我必须在我的递归思维上多做一些工作。现在我看到了你的解决方案,看起来很简单。我会继续练习。