1

I am trying to develop a Binary search tree that can store duplicate values. Please see the problem below.

enter image description here

Sample Case:

enter image description here

Below is my Code:

#include<stdio.h>
#include<stdlib.h>

long int N=0; //Total number of nodes present
struct node
{
    long int key;
    long int count;
    struct node *left, *right;
};

struct node* make(long int key) //To make a node
{
    struct node *temp = (struct node *)malloc(sizeof(struct node));
    temp->key = key;
    temp->left = temp->right = NULL;
    temp->count = 1;
    return temp;
}

void inOrder(struct node *root) //Traverse inorder
{
    if (root != NULL)
    {
        inOrder(root->left);
        printf("%ld(%ld) ", root->key, root->count);
        inOrder(root->right);
    }
}

struct node* learn(struct node* node, long int key) //Insert Node
{

    if (node == NULL){
        N++;
        return make(key);
    }

    if (key == node->key){
        N++;
        (node->count)++;
        return node;
    }

    if (key < node->key)
        node->left = learn(node->left, key);
    else
        node->right = learn(node->right, key);

    return node;
}

struct node * minValueNode(struct node* node)
{
    struct node* current = node;
    while (current->left != NULL)
        current = current->left;

    return current;
}
//Completely delete the node
struct node* forget(struct node* root, long int key)

{
    if (root == NULL)
        return root;

    if (key < root->key)
        root->left = forget(root->left, key);

    else if (key > root->key)
        root->right = forget(root->right, key);

    else {
        N += -(root->count);
            if ((root->left == NULL) || (root->right == NULL)) {
            struct node* temp = root->left ? root->left : root->right;

            if (temp == NULL) {
                temp = root;
                root = NULL;
            }
            else
                *root = *temp;
            free(temp);
        }
        else {
            struct node* temp = minValueNode(root->right);

            root->key = temp->key;
            root->count = temp->count;
            temp->count = 1;

            root->right = forget(root->right, temp->key);
        }
    }

    if (root == NULL)
        return root;

    return root;
}
//Decrease the count of node key by value n
struct node* decrease(struct node* root, long int key, long int n){

    if (root == NULL) return root;

    if (key < root->key)
        root->left = decrease(root->left, key, n);


    else if (key > root->key)
        root->right = decrease(root->right, key, n);

    else{
        if (root->count > 1 && n < root->count){
            N += -n;
            (root->count) += -n;
            return root;
        }

        N += -(root->count);
        if (root->left == NULL)
        {
            struct node *temp = root->right;
            free(root);
            return temp;
        }
        else if (root->right == NULL)
        {
            struct node *temp = root->left;
            free(root);
            return temp;
        }

        struct node* temp = minValueNode(root->right);
        root->key = temp->key;
        root->right = decrease(root->right, temp->key, n);
    }
    return root;
}
//Find number of nodes larger than key
void largerNums(struct node* root, long int key, long int* lnums){
    if (root == NULL)
        return;

    if (key < root->key){
        (*lnums) += root->count;
        largerNums(root->right, key, lnums);
        largerNums(root->left, key, lnums);
    }
    else if (key >= root->key)
        largerNums(root->right, key, lnums);

    return;
}

//Find number of nodes smaller than key
void smallerNums(struct node* root, long int key, long int* snums){
    if (root == NULL)
        return;

    if (key <= root->key){
        smallerNums(root->left, key, snums);
    }
    else if (key > root->key){
        (*snums) += root->count;
        smallerNums(root->left, key, snums);
        smallerNums(root->right, key, snums);
    }
    return;

}
//Find key'th element in ascending order
void asc(struct node* root, long int key, long int* cnt){

    if (root != NULL) {
        asc(root->left, key, cnt);
        int i;
        for(i=1; i <= (root->count); ++i){
            (*cnt)++;
            if(*cnt == key){
                printf("%ld\n", root->key);
                return;
            }
        }
        asc(root->right, key, cnt);
    }

}

//To compare strings
int myStrCompare(char a[], char b[]){
   int c = 0;

   while (a[c] == b[c]) {
      if (a[c] == '\0' || b[c] == '\0')
         break;
      c++;
   }

   if (a[c] == '\0' && b[c] == '\0')
      return 0;
   else
      return -1;
}
//To know which command user entered
int myCompare(char *str){

    if(myStrCompare(str, "learn") == 0)
        return 1;
    else if(myStrCompare(str, "forget") == 0)
        return 2;
    else if(myStrCompare(str, "decrease") == 0)
        return 3;
    else if(myStrCompare(str, "smaller_nums") == 0)
        return 4;
    else if(myStrCompare(str, "larger_nums") == 0)
        return 5;
    else if(myStrCompare(str, "asc") == 0)
        return 6;

    return -1;
}

int main()
{
    long int i, q, x, n, lnums, snums, cnt=0;
    int choice;
    char input[100];
    struct node* root= NULL;

    scanf("%ld", &q);
    //printf("%s", input);

    for(i=1; i<=q; ++i){
        scanf("%s", input);
        //printf("%s", input);
        choice = myCompare(input);
        //printf("\n%d", choice);

        switch(choice){
            case 1: scanf("%ld", &x);
                root = learn(root, x);
                break;
            case 2: scanf("%ld", &x);
                root = forget(root, x);
                break;
            case 3: scanf("%ld%ld", &x, &n);
                if(n < 1){
                    break;
                }else{
                    root = decrease(root, x, n);
                }
                break;
            case 4: scanf("%ld", &x);
                snums = 0;
                smallerNums(root, x, &snums);
                printf("%ld\n", snums);
                break;
            case 5: scanf("%ld", &x);
                lnums = 0;
                largerNums(root, x, &lnums);
                printf("%ld\n", lnums);
                break;
            case 6: scanf("%ld", &x);
                if(x > N){
                    printf("%d\n", -1);
                    break;
                }else{
                    cnt=0;
                    asc(root, x, &cnt);
                }
                break;
            /*case -1: inOrder(root);  \\to know the current state of tree
                printf(" N= %ld \n", N); \\to know total number of nodes
                */ 

        }
    }
   /* root = learn(root, 5);
    root = learn(root, 2);
    root = learn(root, 7);
    root = learn(root, 3);
    root = learn(root, 2);
    smallerNums(root, 5, &s);
    printf("\n%ld\n", s);
    largerNums(root, 2, &l);
    printf("%ld\n", l);
    asc(root, 2, &cnt); cnt = 0;
    root = decrease(root, 2, 1);
    asc(root, 2, &cnt); cnt = 0;
    inOrder(root); printf("\n");
    root = forget(root, 7);
    printf("\n"); inOrder(root);
    l=0;
    largerNums(root, 2, &l);
    printf("%ld\n", l);
    root = forget(root, 5);
    l=0;
    largerNums(root, 2, &l);
    printf("%ld\n", l);
*/


    return 0;
}


My code is passing the sample test case, however when I submit my code, I getting TLE in 2 test cases in 2 wrong test cases(out of 10)

I am unable to understand what is going wrong in my code. I have spent almost 5 days trying to figure out. If you guys can help me then I will be grateful.

The reason for TLE that I suspect is due to the function smallerNums and largerNums because in these functions I am visiting each(almost) node recursively. It would be great if you guys could tell me how can I keep size of subtree at each node, so that I won't have to travers the whole of this tree.

nice_dev
  • 17,053
  • 2
  • 21
  • 35
  • 2
    Please don't post pictures of text. Post text as text. – Jabberwocky Feb 11 '20 at 14:45
  • 1
    You can consider to include the problem description here, not everyone likes to click to an unknown link. – User_67128 Feb 11 '20 at 14:46
  • A binary search tree does not have duplicate values. Otherwise you cannot search it. The only difference I see in your struct is `count`. If a binary tree must have duplicate values, then the node data structure can have a list of the duplicate key values with different data values. Now you find the key and then can list/print/whatever the data values. – Paul Ogilvie Feb 11 '20 at 14:47
  • There no duplicate node as such, I am keeping a "count" field to account for the number of times a value is entered in the tree – Ashwini Patil Feb 11 '20 at 14:49
  • @AshwiniPatil You will have to keep count of smaller nodes(left nodes count) and bigger nodes(right nodes count) as well which I don't see in your node definition. You will also have to make sure that your BST is balanced to ensure a log(n) performance. See [balanced BST](https://en.wikipedia.org/wiki/Self-balancing_binary_search_tree) – nice_dev Feb 11 '20 at 14:58
  • @vivek_23 that is exactly my problem, how do I keep count of smaller and larger nodes, I have never done anything like that. Main problem is when I delete a node,(or decrease a node's count by number > 1) how do I update these numbers then. – Ashwini Patil Feb 11 '20 at 15:01
  • @AshwiniPatil When you add/insert a new node, you traverse down. While doing so, increment all in between nodes' left or right count by 1. When you delete, you do traverse/percolate down in the same way. Do a subtraction of 1 this time. – nice_dev Feb 11 '20 at 15:03
  • @vivek_23 I agree, but the node that I am deleting might have count > 1, what then? (note that in the question, number of nodes greater than a value also includes their count) – Ashwini Patil Feb 11 '20 at 15:04
  • @AshwiniPatil You can have a recursive function or use a stack to collect all parent nodes in the path. After getting the count and deleting the node, deduct that count from all nodes in the stack. – nice_dev Feb 11 '20 at 15:09
  • @AshwiniPatil - Can you explain what TLE is? – jmq Feb 11 '20 at 15:11
  • @jmq Time limit exceeded – Ashwini Patil Feb 11 '20 at 15:12
  • @vivek_23 I am unable to follow your method. Could you teach me in private? I'd be very much grateful for your help – Ashwini Patil Feb 12 '20 at 17:38

0 Answers0