递归地将线分割成更小的段

时间:2017-09-22 08:20:34

标签: algorithm

我有一条线。它从两个索引开始,在最外面的点称为0和1。在任何时候,我都可以创建一个新点,将另外两个点分成两部分(它们之间肯定不一定有点)。但是,当发生这种情况时,索引需要增加。例如,由于结果中存在索引,因此可以实现N = 5的一系列潜在步骤。

              (graph)                 (split between)   (iteration #)
    < ============================ >
    0                              1    0,1          0
    0              1               2    1,2          1
    0              1        2      3    0,1          2
    0      1       2        3      4  

我有两个问题:

  1. 可以使用什么伪代码来找到&#34;&#34;之间的分割。给定迭代次数的值?
  2. 我怎样才能防止形状失衡?我应该对N的值有一些限制吗?我并不特别关心分裂发生的顺序,但我确实希望确保结果是平衡的。
  3. 这是我在开发视频游戏时遇到的一个问题。

2 个答案:

答案 0 :(得分:1)

我不确定这是否是您正在寻找的那种答案,但我将其视为二叉树结构。每个树节点都包含自己的标签及其左右标签。树的根(级别0)将为(2, 0, 1)(左侧为20和右侧为1。每个节点将分成两个子节点。算法会是这样的:

  1. 在步骤 N ,选择最左边的节点,在楼层没有两个孩子(log2( N - 1))。
  2. 从该节点获取节点标签 T 以及左右标签 L R
    • 如果节点没有左子节点,请添加左子节点( N L T )。
    • 如果节点已有左子节点,请添加右子节点( N T R )。
  3. N &lt; - N + 1
  4. 例如,在迭代5,你会有这样的东西:

    Level 0:               (2, 0, 1)
                           /        \
                          /          \
                         /            \
    Level 1:      (3, 0, 2)          (4, 2, 1)
                   /
                  /
    Level 2: (5, 0, 3)
    

    现在,要重建当前分割,您将执行以下操作:

    1. 初始化列表 S &lt; - [0]。
    2. 对于postorder中遍历的树中的每个节点( T L R ):
      • 如果节点没有左子节点,请将 T 附加到 S
      • 如果节点没有正确的子节点,请将 R 附加到 S
    3. 对于上一个案例,您将拥有:

                   S = [0]
      (5, 0, 3) -> S = [0, 5, 3]
      (3, 0, 2) -> S = [0, 5, 3, 2]
      (4, 2, 1) -> S = [0, 5, 3, 2, 4, 1]
      (2, 0, 1) -> S = [0, 5, 3, 2, 4, 1]
      

      所以完整的分割将是[0, 5, 3, 2, 4, 1]。只有当 N = 2 k 时,对于某些正整数 k ,才能完全平衡分裂。当然,您可以使用额外的&#34;距离&#34;来注释树节点。信息,如果你需要跟踪这样的事情。

答案 1 :(得分:1)

我同意jdehesa,因为你所做的事情与二叉树有相似之处。如果可以的话,我建议使用该数据结构,因为它是高度结构化的,定义明确的,并且存在许多用于处理它们的优秀算法。

此外,正如上面评论部分所述,链表也是一个不错的选择,因为你要添加很多元素。正常数组(在内存中是连续的)将要求您在插入其他元素时反复移动多个元素,这很慢。链接列表允许您将元素添加到内存中的任何位置,然后只需更新要插入的位置两侧的链接列表中的几个指针即可完成。没有动人的事。

但是,如果您真的只是想使用数组组合一个工作解决方案而不关心使用其他数据结构,那么这里是您请求的索引的数学:

每对都可以列为(a,b),我们可以快速看到 b = a + 1 。因此,如果你找到了,你就知道了。要获得这些,你需要两个循环:

iteration := 0
i := 0
while iteration < desired_iterations
    for j = (2 ^ i) - 1; j >= 0 && iteration < desired_iterations; j--
        print j, j + 1
        iteration++
    i++

其中^是取幂运算符。我们所做的是找到列表中的倒数第二个元素(2 ^ i)-1 并向后计数,列出索引。然后我们增加“i”以表示我们现在已经将数组大小加倍,然后再次重复。如果我们在任何时候研究了我们想要的迭代次数,那么我们就完成了两次循环。