A Binary Search Tree (BST) is a binary tree data structure with the key property that for each node, all elements in its left subtree are less than the node's key, and all elements in its right subtree are greater than the node's key. This property makes BSTs efficient for searching, inserting, and deleting elements.
This example demonstrates a basic implementation of a Binary Search Tree with integer values.
#include <iostream>
#include <algorithm>
class BinarySearchTree {
private:
struct Node {
int data;
Node* left;
Node* right;
Node(int val) : data(val), left(nullptr), right(nullptr) {}
};
Node* root;
Node* insert(Node* node, int value) {
if (node == nullptr) {
return new Node(value);
}
if (value < node->data) {
node->left = insert(node->left, value);
} else if (value > node->data) {
node->right = insert(node->right, value);
}
return node;
}
Node* search(Node* node, int value) const {
if (node == nullptr || node->data == value) {
return node;
}
if (value < node->data) {
return search(node->left, value);
}
return search(node->right, value);
}
void inorderTraversal(Node* node) const {
if (node) {
inorderTraversal(node->left);
std::cout << node->data << " ";
inorderTraversal(node->right);
}
}
Node* findMin(Node* node) const {
while (node->left != nullptr) {
node = node->left;
}
return node;
}
Node* remove(Node* node, int value) {
if (node == nullptr) {
return node;
}
if (value < node->data) {
node->left = remove(node->left, value);
} else if (value > node->data) {
node->right = remove(node->right, value);
} else {
// Node with only one child or no child
if (node->left == nullptr) {
Node* temp = node->right;
delete node;
return temp;
} else if (node->right == nullptr) {
Node* temp = node->left;
delete node;
return temp;
}
// Node with two children
Node* temp = findMin(node->right);
node->data = temp->data;
node->right = remove(node->right, temp->data);
}
return node;
}
void destroyTree(Node* node) {
if (node) {
destroyTree(node->left);
destroyTree(node->right);
delete node;
}
}
int getHeight(Node* node) const {
if (node == nullptr) {
return 0;
}
return 1 + std::max(getHeight(node->left), getHeight(node->right));
}
public:
BinarySearchTree() : root(nullptr) {}
~BinarySearchTree() { destroyTree(root); }
void insert(int value) {
root = insert(root, value);
}
bool search(int value) const {
return search(root, value) != nullptr;
}
void inorder() const {
inorderTraversal(root);
std::cout << std::endl;
}
void remove(int value) {
root = remove(root, value);
}
int height() const {
return getHeight(root);
}
};
int main() {
BinarySearchTree bst;
bst.insert(50);
bst.insert(30);
bst.insert(70);
bst.insert(20);
bst.insert(40);
bst.insert(60);
bst.insert(80);
std::cout << "Inorder traversal: ";
bst.inorder();
std::cout << "Height of the tree: " << bst.height() << std::endl;
int searchValue = 40;
std::cout << "Searching for " << searchValue << ": "
<< (bst.search(searchValue) ? "Found" : "Not Found") << std::endl;
int removeValue = 30;
std::cout << "Removing " << removeValue << std::endl;
bst.remove(removeValue);
std::cout << "Inorder traversal after removal: ";
bst.inorder();
return 0;
}
BinarySearchTree
class uses a Node
structure to represent each node in the tree.insert
: Adds a new value to the tree while maintaining the BST property.search
: Looks for a value in the tree.inorderTraversal
: Performs an inorder traversal, which visits nodes in ascending order.remove
: Deletes a node from the tree, handling different cases (leaf, one child, two children).height
: Calculates the height of the tree.main
function demonstrates how to use the BST by inserting values, searching, removing, and traversing the tree.This example shows how to implement a BST with string keys and associated integer values, demonstrating its use as a simple key-value store.
#include <iostream>
#include <string>
#include <algorithm>
class BST_KeyValue {
private:
struct Node {
std::string key;
int value;
Node* left;
Node* right;
Node(const std::string& k, int v) : key(k), value(v), left(nullptr), right(nullptr) {}
};
Node* root;
Node* insert(Node* node, const std::string& key, int value) {
if (node == nullptr) {
return new Node(key, value);
}
if (key < node->key) {
node->left = insert(node->left, key, value);
} else if (key > node->key) {
node->right = insert(node->right, key, value);
} else {
// Update value if key already exists
node->value = value;
}
return node;
}
Node* search(Node* node, const std::string& key) const {
if (node == nullptr || node->key == key) {
return node;
}
if (key < node->key) {
return search(node->left, key);
}
return search(node->right, key);
}
void inorderTraversal(Node* node) const {
if (node) {
inorderTraversal(node->left);
std::cout << node->key << ": " << node->value << std::endl;
inorderTraversal(node->right);
}
}
void destroyTree(Node* node) {
if (node) {
destroyTree(node->left);
destroyTree(node->right);
delete node;
}
}
public:
BST_KeyValue() : root(nullptr) {}
~BST_KeyValue() { destroyTree(root); }
void insert(const std::string& key, int value) {
root = insert(root, key, value);
}
bool search(const std::string& key, int& value) const {
Node* result = search(root, key);
if (result) {
value = result->value;
return true;
}
return false;
}
void printInOrder() const {
inorderTraversal(root);
}
};
int main() {
BST_KeyValue bst;
bst.insert("apple", 5);
bst.insert("banana", 7);
bst.insert("cherry", 3);
bst.insert("date", 1);
bst.insert("elderberry", 2);
std::cout << "Key-Value pairs in order:" << std::endl;
bst.printInOrder();
std::string searchKey = "banana";
int value;
if (bst.search(searchKey, value)) {
std::cout << "Value for key '" << searchKey << "': " << value << std::endl;
} else {
std::cout << "Key '" << searchKey << "' not found." << std::endl;
}
// Update a value
bst.insert("banana", 10);
std::cout << "\nAfter updating 'banana':" << std::endl;
bst.printInOrder();
return 0;
}
BST_KeyValue
class uses a Node
structure to represent each node in the tree.insert
: Adds a new key-value pair or updates the value if the key already exists.search
: Looks for a key in the tree and returns its associated value.inorderTraversal
: Prints all key-value pairs in ascending order of keys.main
function demonstrates how to use this BST as a simple key-value store, including inserting pairs, searching for values, and updating existing entries.Balancing: Standard BSTs can become unbalanced, leading to worst-case O(n) time complexity for operations. Self-balancing variants like AVL trees or Red-Black trees address this issue.
Duplicate Keys: The handling of duplicate keys should be clearly defined. In this implementation, we update the value if the key already exists.
Traversal Orders: Besides inorder traversal, preorder and postorder traversals can be useful for different applications.
Memory Management: Proper memory management is crucial, especially when implementing destructors and copy constructors.
Applications: BSTs are widely used in many applications, including:
Binary Search Trees are efficient data structures for storing sorted data and performing quick search, insertion, and deletion operations. They are particularly useful in applications that require frequent lookups and maintenance of ordered data.
In this guide, we explored two implementations of Binary Search Trees:
These examples highlight the versatility of BSTs in handling different types of data and their efficiency in maintaining sorted information. The first example provides a foundation for understanding BST operations, while the second demonstrates a practical application in storing and retrieving key-value pairs, which is a common requirement in many software systems.
BSTs are particularly relevant to your interests in scientific computing and artificial intelligence. In scientific computing, they can be used for efficient data organization and quick lookups. In AI and machine learning, decision trees (which are a type of BST) are used in various algorithms for classification and regression tasks.
For further exploration, you might consider implementing more advanced tree structures like AVL trees or Red-Black trees, which maintain balance automatically. You could also explore using BSTs in specific applications related to your research or teaching in scientific computing or AI, such as implementing efficient database indexing or decision-making algorithms.
Previous Page | Course Schedule | Course Content