我认为其他解决方案是 O(n)。为此,您需要的只是 O(log n) 的每个节点的子节点计数。
当您插入一个节点时,对于您遍历的每个节点,您将遍历节点上的计数器加一。
您需要在删除、重新平衡等时维护这些计数器,这通常并不困难。
有了这个,您可以在插入时获取节点的位置,按值查找节点的位置或按位置查找节点。
按位置查找节点与按值查找相同的二元遍历。如果您想要位置 1000 的项目,那么您从根开始。没有根,不是那个位置的项目。然后你看左边的孩子(你也可以按其他顺序做,并切换升序/降序),如果左边的孩子存在,左边的孩子的数量是0加上左边的孩子的数量节点。假设在这种情况下,左派存在并且有 500 个孩子。那么你知道1000不能剩下了,因为左边没有足够的项目,所以它一定是对的。您可以重复此操作,并一直检查边界。
对于简单的 O(n) 顺序遍历,如果您有一个全局计数器,您只需在遍历左侧后增加它。这应该与深度优先搜索相同。无需减少和增加计数器或压入和弹出堆栈。你也可以让你的函数返回一个计数。
public int inOrderTraverseTree(Node root){
if(root == null)
return 0;
int count = inOrderTraverseTree(root.leftChild);
count++;
count += inOrderTraverseTree(root.rightChild);
return count;
}
如果您也想返回节点,这种方法只会变得烦人。
您当然可以用自己的堆栈替换递归函数,但这是一个很少需要的性能优化,如果您需要性能,那么使用 O(log n) 解决方案比优化的基于堆栈的解决方案要好得多。