Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Binary search tree traversal in C

I have this function that traverses a binary search tree and appends nodes to a list if they are between a given lower and upper bound.

// n - the current node
// l - a list to accumulate results
static void doTreeSearchBetween(Tree t, Node n, Record lower,
                                Record upper, List l) {
    // empty tree
    if (n == NULL) {
        return;
    } 
    int cmpUpper = t->compare(n->rec, upper);
    int cmpLower = t->compare(n->rec, lower);

    // search left subtree
    doTreeSearchBetween(t, n->left, lower, upper, l);

    // if node if between lower and upper records append to list
    if (cmpLower >= 0 && cmpUpper <= 0) {
        ListAppend(l, n->rec);
    }

    // search right subtree
    doTreeSearchBetween(t, n->right, lower, upper, l);
}

I realised the issue with this code is that it traverses the entirety of the list in-order, making it very inefficient and I’m looking for a way that would allow me to visit as few nodes as possible. The logic isn’t working out for me, I was wondering if anyone had any ideas? I tried adding a couple if statements for whenever the current node is less than the lower and greater than the upper bound, that didn’t work out for me.

An example of the output:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Inserting: 11 13 17 19 23 29 31 37 41 43
Searching between 10 and 20
Search returned: 11 13 17 19

Type defs:

typedef struct node *Node;
struct node {
    Record rec;
    Node   left;
    Node   right;
};

struct tree {
    Node    root;
    int     (*compare)(Record, Record);
};

struct list {
    Record *items;
    int     numItems;
    int     maxItems;
};


struct record {
    char familyName[MAX_FAMILY_NAME_LENGTH + 1];
    char givenName[MAX_GIVEN_NAME_LENGTH + 1];
};

>Solution :

You should rely on the comparisons to determine whether to recurse on the left and/or right branches:

  • if the tree node is below the lower bound, its left subtree can be pruned.
  • if the tree node is above the upper bound, its right subtree can be pruned.

Assuming it is empty at the root node, the list will be sorted by construction.

// n - the current node
// l - a list to accumulate results
static void doTreeSearchBetween(Tree t, Node n, Record lower,
                                Record upper, List l) {
    // empty tree
    if (n == NULL) {
        return;
    } 
    int cmpUpper = t->compare(n->rec, upper);
    int cmpLower = t->compare(n->rec, lower);

    if (cmpLower >= 0) {
       // search left subtree
       doTreeSearchBetween(t, n->left, lower, upper, l);

       // if node if between lower and upper records append to list
       if (cmpUpper <= 0) {
           ListAppend(l, n->rec);
       }
    }
    if (cmpUpper <= 0) {
       // search right subtree
       doTreeSearchBetween(t, n->right, lower, upper, l);
    }
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading