Javascript 迭代逆预序遍历

Javascript 迭代逆预序遍历,javascript,dom,recursion,tree,depth-first-search,Javascript,Dom,Recursion,Tree,Depth First Search,我想找到布局直接放在元素上方的项。在页面的DOM结构中,这意味着某些内容可以嵌套在几个层次的深处,也可以意味着在层次结构中提升几个层次。比如说 div.a div.b div.c div.d div.e div.f div.g div.h div.i div.j div.k 其中.b、.h、.i是.a的直系子女,依此

我想找到布局直接放在元素上方的项。在页面的DOM结构中,这意味着某些内容可以嵌套在几个层次的深处,也可以意味着在层次结构中提升几个层次。比如说

div.a        
  div.b      
    div.c      
    div.d    
      div.e  
        div.f
    div.g    
  div.h      
  div.i      
div.j        
div.k        
其中.b、.h、.i是.a的直系子女,依此类推

例如,当我调用getBefore$'.h'时;我想去拿.g。这将表面上涉及一个先点击div.b的预订单反向搜索

我遇到的问题是,如果不执行全局递归扫描,很难处理getBefore$'.c'的情况;我希望得到.b,因为它是布局中位于它前面的项。没有全局遍历递归堆栈的例程更清楚地了解.b,它不知道.d是中间子级,它不应该向下递归并获取其层次结构中最底层的项,结果是.g,这使我们走错了方向


因此,根据这一观察结果,在我看来,递归实现似乎无法干净地完成,因为例程的输入不是根节点,而是某棵树中结构未知的某个节点。那么,什么是迭代实现这一点的合理方法呢?DOM为我提供了向上移动到父节点的指针,我还提供了指向前一个节点的指针(如果有的话),并且我还可以获取任何给定模式的子节点列表(如果有的话)。

我就是这样让它工作的。它使用一个规则的递归前序遍历例程的组合,该例程由一个知道前进方向的迭代例程调用

迭代例程获取一个节点,并通过调用node=node.previousSibling向上遍历同级列表。当它到达顶部时,将转到父节点:node=node.parentNode。在每一步中,它都会调用一个方法,该方法使用标准的递归预排序搜索(recursive preorder search)来获取树中以节点为根的最后一个合适的项。这样,.g导致.f,因为$'.g'[0]。以前的同级是.d,.d的最后一项是.f


奇怪的是,向前看,getAfter例程也做同样的事情,但朝着前进的方向,不需要递归。但是递归地执行它确实会使代码稍微优雅一些。

使用堆栈进行预排序遍历的关键思想是先推右子级,然后推左子级,这样左子级将在右子级之前处理

class Node {
    int key;
    Node left, right;

    public Node() {}

    public Node(int key) {
        this.key = key;
    }
}

public List<Integer> preOrderIterative() {
    List<Integer> list = new ArrayList<>();
    Stack<Node> nodeStack = new Stack<>();

    nodeStack.push(root);

    while (!nodeStack.empty()) {
         Node node = nodeStack.pop();
         list.add(node.key);

         if (null != node.right) nodeStack.push(node.right);
         if (null != node.left) nodeStack.push(node.left);
    }
    return list;
}

从您的描述中不清楚为什么这样的算法在getBefore$'.d'?@hindmost上失败,因为该算法必须进行一些深度优先搜索,例如从.g到.f。不可否认,这个问题可以提出得更好。@hindmost我的意思是,当调用.c时,我不能让天真的递归遍历重新访问.g,因为前序顺序是相反的。。。注意,即使我用访问标志标记节点,.g仍然未访问。。。