Home > OS >  C getting lowest level of a tree
C getting lowest level of a tree

Time:11-11

I need to know how many leafs have a tree but with some conditions.

  • All the children or leafs, will be always on the same level, but it can be the level 1,2,3,4,5 ... I don't know which one will be. So you can't count grandhildren grandgrandchildren ... they will be at the same level and will be the lower of them, in that case: grandgrandchildren.
  • There must be a node without leafs, but if it is not the lowest level of leafs, it doesn't have to count as leaf.

I will try to explain myself with some examples. Imagine you have this tree:

 A
 |- B
 |  |- B1
 |  |- B2                 Number of 'leafs' = 2 (B1 and B2). C doesn't count as it is in an 
 |                                                           upper level)
 |- C

Another example:

 A
 |- B
 |  |- B1
 |  |- B2                 Number of 'leafs' = 3 (B1,B2,D1)
 |
 |- C
 |- D
    |-D1

Another example:

 A
 |- B
 |  |- B1
 |  |   |-B11
 |  |- B2                 Number of 'leafs' = 1 (B11). D1 is not a leaf. It is a 'node' as 
 |                                    leafs in this case are in level 4 (counting A as 1)
 |- C
 |- D
    |-D1

I'm working with C and Qt with something similar to QTreeWidgetItem so I have an object (let's call it myTree and I can ask something like: myTree->childCount() so in the first example, if I call it, it will say 2 (B and C) and for each one I can repeat the operation.

I was trying to count everything that gives me childcount() but then, it gaves me 4 (B,C,B1 and B2) instead of 2 (B1,B2) which is what i want...Here I put what I was trying:

 int grandchild = 0;
   for (int i = 0; i < myTree->childCount( );   i)
   {
        Obj* child = myTree->child( i ); //Get the children. First time will be B and C
        if (child)
        {
          grandchild  = p_child->childCount( ); // Here I wanted to get a total, for first example, I will get 3 which is not what I want 
        }
    }

Thank you in advance.

CodePudding user response:

For recursive functions, you start with the assumption that the function, when operating on a node, will return all relevant information about that node. Each node then only needs to inspect its children and itself to decide what to return to the level above it.

If the node has no children, then the result is trivial: this node has one max depth node at a depth of 0 (itself).

Otherwise, the max depth is equal to the largest max depth among its children 1, and the count is equal to the sum of the counts of all children that share the largest max depth.

#include <utility>
#include <vector>

struct node_type {
    std::vector<node_type*> children;
};

// returns the max depth between the node and all of its children
// along with the number of nodes at that depth
std::pair<int, int> max_depth_count(const node_type& node) {
    int depth = 0; // itself
    int count = 1; // itself

    for (const auto c : node.children) {
        auto [child_depth, child_count] = max_depth_count(*c);
        child_depth  ;

        if (child_depth > depth) {
            depth = child_depth;
            count = child_count;
        }
        else if (child_depth == depth) {
            count  = child_count;
        }
    }

    return {depth, count};
}

CodePudding user response:

One way to do this, is to perform a breadth-first traversal. That way you visit one level after the other, and the size of the last non-empty level is then what you need.

Such a breadth-first traversal can be done using a queue.

Here is how you can code it using the interface (Obj*, childCount, child) you provided in the question:

int n = 0; // number of nodes in the "current" level
if (myTree != nullptr) {
    std::queue<Obj*> q;
    q.push(myTree); // The first level just has the root
    while (q.size()) { // While the level is not empty...
        n = q.size(); // ...remember its size
        for (int i = 0; i < n;   i) { // ...and replace this level with the next
            Obj* node = q.front();
            q.pop();
            int m = node->childCount();
            for (int j = 0; j < m;   j) {
                q.push(node->child(j));
            }
        }
    }
}
std::cout << n << "\n";
  • Related