Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 如何有效地将嵌套集转换为对象层次_Algorithm_Nested Sets - Fatal编程技术网

Algorithm 如何有效地将嵌套集转换为对象层次

Algorithm 如何有效地将嵌套集转换为对象层次,algorithm,nested-sets,Algorithm,Nested Sets,假设我有一个表示嵌套集合层次结构的节点列表(例如伪c#) 但这是相当低效的 有更好(也就是更快)的方法吗 编辑 可能的解决方案(): var stack=新堆栈(nodes.Take(1)); foreach(节点中的变量n.Skip(1)) { while(stack.Peek().right树算法的递归算法产生困惑,我(在scala中)得出以下结论: 希望这能对其他人有所帮助。我知道这个问题已经很老了(我没有找到关于这个主题的任何其他问题/信息),我也不知道“伪C#”,但为了防止你们中的一些

假设我有一个表示嵌套集合层次结构的节点列表(例如伪c#)

但这是相当低效的

有更好(也就是更快)的方法吗

编辑

可能的解决方案():

var stack=新堆栈(nodes.Take(1));
foreach(节点中的变量n.Skip(1))
{
while(stack.Peek().right

节点必须按
left

排序。我可能想探索的方法是按left排序,然后您可以只迭代一次

当你到达一个节点的左边时,你可以“打开”它,然后把它粘在一个堆栈上

当到达要处理的新节点时,通过确定其右侧是否小于左侧的新节点,检查堆栈顶部的节点是否应关闭。如果是,则将其从堆栈中移除(关闭它),并已处理其所有子级。然后检查堆栈的新顶部,直到找到一个仍然打开。然后将当前节点作为子节点添加到堆栈顶部的节点,然后打开该节点(因此它位于堆栈顶部)

你链接的维基百科页面上的图表()就是启发我这么做的原因

<>我的算法基本上沿着中间行,每当你进入其中一个集合就是我所说的开头,剩下一个集合就结束了。很明显,最近打开但未关闭的集合将位于堆栈的顶部,因此也就是放置子对象的位置


我认为由于排序的原因,这个问题的复杂性应该是O(nlogn)。剩下的部分就是O(n)。

我可能会考虑探索的方法是按左排序,然后您可以只迭代一次

当你到达一个节点的左边时,你可以“打开”它,然后把它粘在一个堆栈上

当到达要处理的新节点时,通过确定其右侧是否小于左侧的新节点,检查堆栈顶部的节点是否应关闭。如果是,则将其从堆栈中移除(关闭它),并已处理其所有子级。然后检查堆栈的新顶部,直到找到一个仍然打开。然后将当前节点作为子节点添加到堆栈顶部的节点,然后打开该节点(因此它位于堆栈顶部)

你链接的维基百科页面上的图表()就是启发我这么做的原因

<>我的算法基本上沿着中间行,每当你进入其中一个集合就是我所说的开头,剩下一个集合就结束了。很明显,最近打开但未关闭的集合将位于堆栈的顶部,因此也就是放置子对象的位置


我认为由于排序的原因,这个问题的复杂性应该是O(nlogn)。剩下的只是O(n)。

我知道这个问题已经很老了(我没有找到关于这个主题的任何其他问题/信息),我也不知道“伪C#”,但为了防止你们中的一些人对嵌套集列表=>树算法的递归算法产生困惑,我(在scala中)得出以下结论:


希望这能对其他人有所帮助。

我知道这个问题已经很老了(我没有找到关于这个主题的任何其他问题/信息),我也不知道“伪C#”,但为了防止你们中的一些人对嵌套集列表=>树算法的递归算法感到困惑,以下是我(在scala中)得出的结论:


希望这能对某人有所帮助。

也许我在某个地方遗漏了一步,但当我使用上面的逻辑进行这项工作时,我在堆栈上找到了几个重复的元素。它们如预期的那样位于树中,但另外它们也位于根节点上方的堆栈顶部。我不得不在末尾添加一个小循环来清理堆栈

        var stack = new Stack<DvrNode>(nodes.Take(1));
        foreach (var n in nodes.Skip(1))
        {
            while (stack.Peek().Right < n.Left)
                stack.Pop();

            ((List<DvrNode>)stack.Peek().Children).Add(n);
            stack.Push(n);
        }

        while (stack.Peek().Left != 1)
            stack.Pop();
var stack=新堆栈(nodes.Take(1));
foreach(节点中的变量n.Skip(1))
{
while(stack.Peek().Right
也许我遗漏了某个步骤,但是当我使用上面的逻辑处理这个问题时,我在堆栈上得到了两个重复的元素。它们如预期的那样位于树中,但另外它们也位于根节点上方的堆栈顶部。我不得不在末尾添加一个小循环来清理堆栈

        var stack = new Stack<DvrNode>(nodes.Take(1));
        foreach (var n in nodes.Skip(1))
        {
            while (stack.Peek().Right < n.Left)
                stack.Pop();

            ((List<DvrNode>)stack.Peek().Children).Add(n);
            stack.Push(n);
        }

        while (stack.Peek().Left != 1)
            stack.Pop();
var stack=新堆栈(nodes.Take(1));
foreach(节点中的变量n.Skip(1))
{
while(stack.Peek().Right
left
right
是否以某种方式表示子节点?是的,我发现很难弄清楚如何使用left和right来获得父节点……left和right是描述嵌套集层次结构中节点位置的数字,所以问题本质上是:您有一个
(leftindex,rightindex,key)
三元组,您需要一个
树(leftpointer,rightpointer,key)
节点?左和右是否以某种方式表示子节点?是的,我发现很难弄清楚如何使用左和右来获得父节点……左和右是描述嵌套集层次结构中节点位置的数字,所以问题本质上是:您有一个列表de>(leftindex,rightindex,key)三倍,您想要一个包含
(leftpointer,rightpointer,key)
节点的树?这是一个不错的解决方案,因为排序在大多数时候都非常便宜。这是一个不错的解决方案,因为排序在大多数时候都非常便宜。
var stack = new Stack<Node>(nodes.Take(1));
foreach (var n in nodes.Skip(1))
{
    while (stack.Peek().right < n.left)
        stack.Pop();

    stack.Peek().addChild(n);
    stack.Push(n);
}
def retrieveUserFolderTree(user: User): Future[List[Folder]] = {
  // Get a list of user's folders orderred by left asc
  val dbFoldersPromise = folderDAO.findUserFolders(user)

  dbFoldersPromise.map {
    case rootFolder :: tail => generateChildren(0, rootFolder.right, tail)
    case Nil => Nil
  }
}

private def generateChildren(currentLeft: Int, currentRight: Int, dbFolders: Seq[DBFolder]): List[Folder] = {
  dbFolders match {
    case dbFolder :: tail if dbFolder.left > currentRight => Nil
    case dbFolder :: tail if dbFolder.left > currentLeft => Folder(dbFolder.id, dbFolder.name, generateChildren(dbFolder.left, dbFolder.right, tail)) :: generateChildren(dbFolder.right, currentRight, tail)
    case dbFolder :: tail => generateChildren(currentLeft, currentRight, tail)
    case Nil => Nil
  }
}
        var stack = new Stack<DvrNode>(nodes.Take(1));
        foreach (var n in nodes.Skip(1))
        {
            while (stack.Peek().Right < n.Left)
                stack.Pop();

            ((List<DvrNode>)stack.Peek().Children).Add(n);
            stack.Push(n);
        }

        while (stack.Peek().Left != 1)
            stack.Pop();