algorithm – 任意树的DFS排序比较函数

想象一个完整的二叉树,其中每个深度级别的节点从左到右编号.

>节点1有2个孩子和3个孩子.
>节点2有4个孩子和5个孩子.
>节点3有6个孩子和7个孩子.

等等

在深度D处将存在2 ^ D个节点,其中数字为2 ^ D … 2 ^(D 1)-1

深度优先搜索遍历任何深度的完整树是确定性的.

例如,将始终遍历深度为4的树:
1,2,4,8,9,5,10,11,3,6,12,13,7,14,15.

我正在寻找一种方法来排序数字列表,它们将落在任何树的DFS遍历中.

特别是,我想要一个比较函数,它可以取两个数字并确定哪个在DFS遍历中首先出现.

有任何想法吗?

为某些最大树大小预先计算DFS遍历是一种方法,但我更喜欢不需要计算和存储该信息的数学解决方案.

最佳答案 具有最佳性能的算法将是FUD建议的算法,因为您只需要遍历树一次,然后比较将只是O(1).

但是如果你不想遍历整个树,只想要一个比较器,那么就有一个O(log n)比较器(可以优化为O(log log n),或者实际上是O(1)).

这个想法是:

Observation 1: If the two nodes are on the same depth, the higher numbered node will be traversed later.

Observation 2: If the two nodes are not on the same depth, by noting that parent is always visited first before descendants, we take the ancestor of the deeper node which is on the same depth as the more shallow node. Then compare using Observation 1.

使用完整二叉树中的数字系统,您可以通过取n / 2获得节点n的父节点.因此,在获得每个节点的深度(可以在O(log n)或预先计算中完成)之后,例如d1< d2,我们用2 ^(d2-d1)划分更深的节点(功率可以在O(log p)中完成,在这种情况下p是O(log n),所以它是O(log log n)).然后看哪一个更大=) 在C:

// This method can be modified to be faster
// See: https://stackoverflow.com/questions/671815/what-is-the-fastest-most-efficient-way-to-find-the-highest-set-bit-msb-in-an-i
int depth(int n){
    int result=-1;
    for(;n>0; result++, n/=2);
    return result;
}

bool n1_before_n2(int n1, int n2){
    int d1 = depth(n1);
    int d2 = depth(n2);
    if(d1>d2) n1 >>= (d1-d2);
    if(d2>d1) n2 >>= (d2-d1);
    return n1<n2;
}
点赞