Home > Net >  Is there a way to implement this binary search tree function?
Is there a way to implement this binary search tree function?

Time:07-06

I am struggling to implement the following function:

Given a binary search tree, return the smallest node, then move the pointer to the next smallest node in the tree. Upon calling the function another time, it should return the next smallest node and so on.

Any help would be greatly appreciated.

Here is my program so far with some helper functions and their definitions:

#include <stdio.h>
#include <stdlib.h>
 
/* A binary tree node has data,
   the pointer to left child
   and a pointer to right child */
struct node {
    int data;
    struct node *left;
    struct node *right;
    struct node *parent;
};
 
struct node *minValue(struct node *node);
 
struct node *inOrderSuccessor(
    struct node *root,
    struct node *n)
{
    if (n->right != NULL)
        return minValue(n->right);
   
    struct node *p = n->parent;
    while (p != NULL && n == p->right) {
        n = p;
        p = p->parent;
    }
    return p;
}
 
/* Given a non-empty binary search tree,
    return the minimum data 
    value found in that tree. Note that
    the entire tree does not need
    to be searched. */
struct node *minValue(struct node *node)
{
    struct node *current = node;
 
    /* loop down to find the leftmost leaf */
    while (current->left != NULL) {
        current = current->left;
    }
    return current;
}
 
/* Helper function that allocates a new
    node with the given data and
    NULL left and right pointers. */
struct node *newNode(int data)
{
    struct node *node = (struct node *)malloc(sizeof(struct node));
    node->data = data;
    node->left = NULL;
    node->right = NULL;
    node->parent = NULL;
 
    return (node);
}
 
/* Give a binary search tree and
   a number, inserts a new node with   
    the given number in the correct
    place in the tree. Returns the new
    root pointer which the caller should
    then use (the standard trick to
    avoid using reference parameters). */
struct node *insert(struct node *node,
                    int data)
{
    /* 1. If the tree is empty, return a new,
      single node */
    if (node == NULL)
        return (newNode(data));
    else {
        struct node *temp;
 
        /* 2. Otherwise, recur down the tree */
        if (data <= node->data) {
            temp = insert(node->left, data);
            node->left = temp;
            temp->parent = node;
        } else {
            temp = insert(node->right, data);
            node->right = temp;
            temp->parent = node;
        }
 
        /* return the (unchanged) node pointer */
        return node;
    }
}

CodePudding user response:

Given a binary search tree, return the smallest node, then move the pointer to the next smallest node in the tree. Upon calling the function another time, it should return the next smallest node and so on.

struct node *smallest_node(struct node *root, struct node **saved)
{
    if (!saved) // A litteral NULL
        return NULL;
    
    if (*saved)
        return (*saved)->parent ? (*saved = (*saved)->parent) : *saved;
    
    struct node *min = NULL;
    for (struct node *i = root; i; i = i->left)
        min = i;
    
    *saved = min;
    return min;
}

Example:

int main(void)
{
    struct node *tree = NULL;
    // Fill tree with data ...
    
    struct node *min = NULL;
    while (smallest_node(tree, &min) != tree)
        printf("Smallest = %d\n", min->data);
}

CodePudding user response:

Here are some remarks about your code:

  • the function minValue is correct, by it should accept a null argument (which is an empty tree) and return null for that.

  • the function new_node should check for memory allocation failure to avoid undefined behavior.

  • function inOrderSuccessor should stop scanning when it goes back up to the root node from its right child and return NULL. Also testing for a null parent node will avoid undefined behavior.

  • you can check for failure in insert and return a null pointer.

Here is a modified version:

#include <stdio.h>
#include <stdlib.h>
 
/* A binary tree node has data,
   the pointer to left child
   a pointer to right child
   and a pointer to parent node
 */
struct node {
    int data;
    struct node *left;
    struct node *right;
    struct node *parent;
};
 
/* Given a binary search tree,
    return the node with the minimum data. */
struct node *minValue(struct node *node) {
    if (node) {
        /* loop down to find the leftmost leaf */
        while (node->left != NULL) {
            node = node->left;
        }
    }
    return node;
}
 
struct node *inOrderSuccessor(struct node *root,
                              struct node *n)
{
    if (n->right != NULL)
        return minValue(n->right);
   
    for (;;) {
        struct node *p = n->parent;
        /* sanity test */
        if (p == NULL)
            return NULL;
        /* coming back from the left child, return parent node */
        if (n != p->right)
            return p;
        /* coming back from the right child, stop at the root node */
        if (p == root)
            return NULL;
        n = p;
    }
}
 
/* Helper function that allocates a new
    node with the given data and
    NULL left and right pointers. */
struct node *newNode(int data) {
    struct node *node = malloc(sizeof(*node));
    if (node) {
        node->data = data;
        node->left = NULL;
        node->right = NULL;
        node->parent = NULL;
    }
    return node;
}
 
/* Give a binary search tree and
   a number, inserts a new node with   
    the given number in the correct
    place in the tree. Returns the new
    root pointer which the caller should
    then use (the standard trick to
    avoid using reference parameters).
    Return a null pointer on memory allocation failure */
struct node *insert(struct node *node,
                    int data)
{
    /* 1. If the tree is empty, return a new,
      single node */
    if (node == NULL) {
        return newNode(data);
    } else {
        struct node *temp;
 
        /* 2. Otherwise, recurse down the tree */
        if (data <= node->data) {
            temp = insert(node->left, data);
            if (temp == NULL)  /* return NULL on failure */
                return NULL;
            node->left = temp;
            temp->parent = node;
        } else {
            temp = insert(node->right, data);
            if (temp == NULL)  /* return NULL on failure */
                return NULL;
            node->right = temp;
            temp->parent = node;
        }
        /* return the (unchanged) node pointer */
        return node;
    }
}
  • Related