1

I have a tree n-ary composed in this way:

struct n_tree{
    struct list *adj;    
};

struct list{
    struct n_tree *child;
    struct list *next;
    int key;
};

How i can search an item? I have implemented this function, but it does not work... Thanks!

struct list *find(struct list *root, int key){
    if(root){
        find(root->next,key);
        if (root != NULL){
            if(root->key == key){
                return root;
            }
            else if(root->child != NULL){
                return find(root->child->adj,key);
            }
        }
    }
}
b00k3r
  • 11
  • 1
  • 3
  • How do you split key ranges among `n` nodes? I mean, with binary tree it's simple: everything below the `key` go to the left, and everything else goes on the right. But with `n` elements it's not so clear. – Sergey Kalinichenko May 13 '16 at 11:51
  • You make a recursive call `find(root->next,key);` but never use the result returned. Why do you make that call then? – CiaPan May 13 '16 at 11:52
  • You say you have a *'tree composed in this way'* but you actually don't show any *'way'*. You have just shown data structures, but did not explain their meaning: are lists sorted somehow? what is the relation between `key`s in a list linked with `next`? what is the relation between a `key` in a list item and those in `child` subtree? – CiaPan May 13 '16 at 11:58
  • because I need to use the return recursive calls to visit the tree. – b00k3r May 13 '16 at 12:00
  • the nodes are not sorted, a parent is composed of a list of children, the first node of the list is the first child of the parent – b00k3r May 13 '16 at 12:02
  • But your goal is to find a node with the given key, not 'to visit the tree'. You do that by scanning the tree, of course, but 1) you don't have to scan the whole tree – you can stop the scan as soon as you find what you need; 2) you need to return the node found – otherwise the recursive call is a pure waste of time. – CiaPan May 16 '16 at 12:52

3 Answers3

1

It seems that what you are trying to implement is a n-ary tree with a binary implementation (first child, right sibling).

It's more obvious with other namings :

struct n_tree{
  struct list *root;    
};

struct tree_node{
    int key;
    struct tree_node *first_child;
    struct tree_node *right_sibling;
};

A recursive search function returning the node with the key key or NULL if no node is found could be :

struct tree_node *find_node(struct tree_node *from, int key){
  // stop case
  if (from==NULL) return NULL;
  if (from->key==key) return from;
  // first we'll recurse on the siblings
  struct tree_node *found;
  if ( (found=find_node(from->right_sibling,key) != NULL ) return found;
  // if not found we recurse on the children
  return find_node(from->first_child, key);
}

If you need a wrapper function with a n_tree argument :

struct tree_node* find(struct n_tree* tree, int key) {
  return find_node(tree->root, key);
}
Picodev
  • 506
  • 4
  • 8
0

Before looking at the children, you need to look at the local node, since that's how you actually find things and end the recursion.

Also, doing a recursive call and ignoring the return value is pointless (unless there's an "out-parameter", which there isn't here). So don't do that.

unwind
  • 391,730
  • 64
  • 469
  • 606
0

Here is (possibly the smallest) modification of your code to achieve your goal:

struct list *find(struct list *root, int key){
    for(; root != NULL; root = root->next){   // scan the siblings' list
        if(root->key == key)                  // test the current node
            return root;                      // return it if the value found

        if(root->child != NULL) {             // scan a subtree
            struct list *result = find(root->child->adj, key);
            if(result)                        // the value found in a subtree
                return result;                // abandon scanning, return the node found
        }
    }
    return NULL;                              // key not found
}
CiaPan
  • 9,381
  • 2
  • 21
  • 35