How can I calculate the level of a node in a perfect binary tree from its depth-first order index?

这一生的挚爱 提交于 2019-12-22 06:02:39

问题


I have a perfect binary tree, i.e. each node in the tree is either a leaf node, or has two children, and all leaf nodes are on the same level. Each node has an index in depth-first order.

(E.g. in a tree with 3 levels the root node has index 0, the first child has 1, the first child of the first child has 2, the second child of the first child has 3, the second child has 4, the first child of the second child has 5, the second child of the second child has index 6.

      0
    /   \
  1      4
 / \    / \
2   3  5   6

)

I know the size of tree (number of nodes/maximum level), but only the index of a particular node, and I need to calculate its level (i.e. its distance to the rootnode). How do I do this most efficiently?


回答1:


let i be the index you are looking for and n be the total number of nodes.

This algorithm do what you want:

level = 0
while i != 0 do
    i--
    n = (n-1)/2
    i = i%n
    level++
done

0 is the index of the root, if i = 0 then you are at the good level, else you can remove the root and you obtain two subtrees n = (n-1)/2 updates the number of nodes is the new tree (which is a subtree of the old one) and i = i%n selects only the good subtree.




回答2:


Here is another suggestion that would make the solution to this question easier:

If you label the nodes with an index in breadth-first order, you can compute the level without any traversal in O(1) time. So if you are doing multiple queries, you can do an O(N) BFT and have each query answered in O(1) time.

The formula for the level is:

level = floor(log(index + 1))

Where the log is to the base 2

Try it out on this tree:

       0
     /    \
    /      \
   1        2
  / \      / \
 /   \    /   \
3     4  5     6

Cheers.




回答3:


It seems as if walking on the tree directly should be efficient enough.

At each step of the algorithm, keep in mind the range of the indexes on the subtree of the node you are at. The first value of the range it the root node, and after that the first half is the range of the subtree on the left, and the second half should be the range of the right subtree. You can then recursively move down until you find your node.

For example, lets search for in a 4 level tree with 15 elements

                 (root node)(left elements)(right elements)
Starting range:  (0)(1 2 3 4 5 6 7)(8 9 10 11 12 13 14)
Go left       :  (1)(2 3 4)(5 6 7)
Go right      :  (5)(6)(7)
Found node, total depth 2

You should be able to do this with a simple loop, using just a couple of variables to store the start and the end of the ranges. You should also easily be able to adapt this if you do some minor changes, such as using post/pre/in-order traversal or starting the indexes form 1 instead of 0.




回答4:


Untested:

int LevelFromIndex( int index, int count)
{
    if (index == 0)
        return 0;
    if (index > (count - 1)/ 2)
        index -= (count - 1) / 2;
    return 1 + LevelFromIndex( index - 1, (count - 1) / 2);
}

Here count is the total number of nodes in the tree.




回答5:


EDIT: Attempt number 1... only works for BFS.

If by perfect binary tree, you mean a binary tree with a heap like structure, then you can calculate a node's parent index using this formula:

parentIndex = (index-1)/2

So you can repeat that formula until you get to <=0, each time you loop you essentially go up a level in the tree.

EDIT: Attempt number 2..

The best way I can think of doing would take O(index + log n) which is O(n). Do a DFS until you reach the desired index, then keep going up the tree using a parent pointer until you reach the root keeping track of the number of times you've gone up. This assumes that a parent pointer exists on each node.




回答6:


If all you have is the index, you can't find the depth.

Suppose you have a tree like this:

    1
   / \
  2   5
 / \
3   4

The node with index 3 has depth 2.

Suppose you have a tree like this:

  1
 / \
2   3
   / \
  4   5

the node with index 3 has depth 1.

You can't distinguish between these two trees just by knowing their indexes. There's no way to find the distance from root just by knowing index.

Edit: If you mean a perfect binary tree as in, all leaves are at the same depth, and every parent has two children, then you still can't find the depth.

Compare these two trees:

  1
 / \
2   3


      1
   /     \
  2       5
 / \     / \
3   4   6   7

The depth of node 3 changes depending on the height of the tree.

Edit 2: if you know the height of the total tree, you can use this recursive algorithm:

def distanceFromRoot(index, rootIndex, treeHeight):
    if index == rootIndex:
        return 0
    leftIndex = rootIndex+1
    rightIndex = rootIndex + 2**treeHeight
    if index >= rightIndex:
        return 1 + distanceFromRoot(index, rightIndex, treeHeight-1)
    else:
        return 1 + distanceFromRoot(index, leftIndex, treeHeight-1)



回答7:


So, we have such tree with 4 levels:

          0             - 0th level
      /       \         
     1          8       - 1th level
   /  \       /  \      
  2    5     9    12    - 2th level
 / \   /\   / \   / \
3   4 6  7 10 11 13 14  - 3th level

As you can see, each left child have index of root increased by one (left = root + 1), because in DFS left child always visits first. Second node have index of left node increased by size of left sub-tree (right = left + leftSize). If we know depth of tree, we can calculate its size (size = 2^depth - 1). As far as left sub-tree have depth equal to depth of parent decreased by one, its size = 2^(parentDepth - 1) - 1.

So now we have an algorithm - calculate index of left node, calculate index of right node. If node index lies between it, go to left node, else - go to right node.

Code:

static int level(int index, int root, int treeDepth) {
        if (index == root)
            return 0;

        if (treeDepth <= 0 /* no tree */ || treeDepth == 1 /* tree contains only root */)
            throw new Exception("Unable to find node");

        int left = root + 1;
        int right = left + (int)Math.Pow(2, treeDepth - 1) - 1;

        if (index == left || index == right)
            return 1;

        if (left < index && index < right)
            return 1 + level(index, left, treeDepth - 1);
        else
            return 1 + level(index, right, treeDepth - 1);
    }


来源:https://stackoverflow.com/questions/10721583/how-can-i-calculate-the-level-of-a-node-in-a-perfect-binary-tree-from-its-depth

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!