Simple Binary Search Tree Class with Insert and Search Functions I am trying to learn to implement DSs in C++ and here is a simple implementation. Please review in terms of optimization, memory management, coding standards, etc

#include &lt;stdio.h&gt;
#include &lt;iostream&gt;

class BstNode{
int data;
BstNode* left;
BstNode* right;

public:
BstNode(int data)
{
    this-&gt;data = data;
    this-&gt;left = NULL;
    this-&gt;right = NULL;
}
~BstNode();

void Insert(int data)
{
    if(this-&gt;data &gt;= data)
    {
        if (this-&gt;left == NULL)
            this-&gt;left = new BstNode(data);
        else 
            this-&gt;left-&gt;Insert(data);
    }
    else
    {
        if (this-&gt;right == NULL)
            this-&gt;right = new BstNode(data);
        else 
            this-&gt;right-&gt;Insert(data);
    }
}

bool Search(int data)
{
    if(this-&gt;data == data)
        return true;
    else if(this-&gt;data &gt;= data)
    {
        if(this-&gt;left == NULL)
            return false;
        else
            return this-&gt;left-&gt;Search(data);
    }
    else
    {
        if(this-&gt;right == NULL)
            return false;
        else
            return this-&gt;right-&gt;Search(data);
    }

}
};

int main()
{
BstNode* ptr_root = new BstNode(15);
ptr_root-&gt;Insert(10);
ptr_root-&gt;Insert(16);
int num;
std::cout&lt;&lt;"Enter the number: \n";
std::cin&gt;&gt; num;
if (ptr_root-&gt;Search(num))
    std::cout&lt;&lt;"Found\n";
else
    std::cout&lt;&lt;"Not Found\n";

return 0;
}
Overall organization

Right now, you've defined a BstNode, which you use directly in main. I'd at least consider defining a Bst class, and then (probably inside that) a Node class.

class Bst {
    class Node {
        // only code to deal with individual nodes goes here
    };

    Node *root;
public:

    bool insert(int value);

    bool find(int value);
};


Then to create a Binary search tree, you'd just instantiate a Bst object, and use it:

int main() {

    Bst tree;

    // oops--this will lead to a completely imbalanced tree.
    for (int i=0; i&lt;10; i++)
        tree.insert(i);

}


in-class initialization

Since you (almost?) always create a node with its child pointers set to nullptrs, I'd just specify that directly in the class instead of in the ctor:

// ...
class Node {
    int value;
    Node *left = nullptr;
    Node *right = nullptr;

    Node(int value) : value(value) {}
};


Insertion and Search

I'd at least consider whether you really want to use recursion to do insertion and/or search. Since you only ever descend to one child of any given node, it's pretty easy to use iteration for these tasks.

Insert return type

I'd at least consider having Insert return a bool to indicate whether it actually inserted a value in the tree or not (e.g., return false if a value is already present).

Collection type

What you've currently implemented is roughly equivalent to a std::set. That is, it stores only keys. This can certainly be useful, but there are times its also useful to have data associated with the key (i.e., roughly equivalent to std::map).

Generic Code

Right now, you've written the code so the only thing can be stored in your BST is ints. I'd at least consider making it generic so other types can be stored.

template &lt;class T, class Cmp = std::less&lt;T&gt;&gt;
class Bst {
    // ...


This increases complexity a little, but increases functionality quite a lot.