Implement a binary tree and solve the following:
1) Write a function to find the immediate common ancestor of any two nodes in the tree
2) Print elements in pre-order, in-order and post-order traversals
3) Check if a binary tree is a Binary Search Tree
/*
* BinaryTreeNode.cpp
*
* Created on: Apr 21, 2012
* Author: Kiran Hegde
*/
#include <iostream>
#include <algorithm>
#include <queue>
#include <string>
#include <list>
#include <limits>
using namespace std;
class BinaryTreeNode {
public :
BinaryTreeNode(int d) : left(NULL), right(NULL), data(d) {}
~BinaryTreeNode() {
if (left != NULL) {
delete left;
left = NULL;
}
if (right != NULL) {
delete right;
right = NULL;
}
}
//Method to insert data to create a binary search tree (i.e. left <= node < right)
void insert(int x) {
if (x < data) {
if (left != NULL)
left->insert(x);
else {
BinaryTreeNode *node = new BinaryTreeNode(x);
left = node;
}
}
else {
if (right != NULL)
right->insert(x);
else {
BinaryTreeNode *node = new BinaryTreeNode(x);
right = node;
}
}
}
//Method to find d if this is a binary search tree
BinaryTreeNode *find(int d) {
if (d == data) {
return this;
}
else {
if (d < data) {
return (left != NULL ? left->find(d) : NULL);
}
else if (d > data){
return (right != NULL ? right->find(d) : NULL);
}
}
return NULL;
}
int height() {
int heightLeft = (left == NULL ? 0: left->height());
int heightRight = (right == NULL ? 0: right->height());
int height = 1 + max(heightLeft, heightRight);
return height;
}
BinaryTreeNode *left;
BinaryTreeNode *right;
int data;
};
/**
* Create a Binary Tree from any array. The tree is created such that beginning
* of the array is mapped to the root of the tree and subsequent array elements
* are added as the children, going from left to right and top to bottom
*/
BinaryTreeNode *createBinaryTreeFromArray(int *array, int size) {
if (array == NULL) {
return NULL;
}
queue<BinaryTreeNode *> myQueue;
BinaryTreeNode *root = new BinaryTreeNode(array[0]);
myQueue.push(root);
bool done = false;
int i = 1;
while (!done) {
BinaryTreeNode *node = myQueue.front();
if (node->left == NULL) {
node->left = new BinaryTreeNode(array[i]);
myQueue.push(node->left);
i++;
}
else if (node->right == NULL) {
node->right = new BinaryTreeNode(array[i]);
myQueue.push(node->right);
i++;
}
else {
myQueue.pop();
}
if (i == size)
done = true;
}
return root;
}
/**
* Recursive function to create a binary search tree from sorted array
*/
BinaryTreeNode *createMinimalBST(int *array, int start, int end, int level) {
if (end < start) {
return NULL;
}
int mid = (start + end)/2;
BinaryTreeNode *node = new BinaryTreeNode(array[mid]);
node->left = createMinimalBST(array, start, mid-1, level + 1);
node->right = createMinimalBST(array, mid+1, end, level + 1);
return node;
}
/**
* Create a minimal Binary Search Tree from any array
*/
BinaryTreeNode *createMinimalBSTFromArray(int *array, int size) {
//First sort the array
list<int> dataList;
for (int i=0; i<size; i++) {
dataList.push_back(array[i]);
}
dataList.sort();
list<int>::iterator it;
int i=0;
for (it=dataList.begin(); it != dataList.end(); it++) {
array[i++] = *it;
}
BinaryTreeNode *root = createMinimalBST(array, 0, size-1, 0);
return root;
}
void printTree(BinaryTreeNode *root) {
if (root == NULL){
return;
}
queue<BinaryTreeNode *> treeQueue;
queue<int> levelQueue;
queue<int> parentQueue;
queue<string> rightLeftFlagQueue;
treeQueue.push(root);
levelQueue.push(0);
parentQueue.push(root->data);
rightLeftFlagQueue.push("Top");
cout << "Level 1: ";
int prevLevel = 0;
while(! treeQueue.empty()) {
BinaryTreeNode *node = treeQueue.front();
int level = levelQueue.front();
if (node != NULL) {
if (level > prevLevel) {
prevLevel = level;
cout << endl;
cout << "Level " << level + 1 << ": ";
}
int parentData = parentQueue.front();
string rightLeftFlag = rightLeftFlagQueue.front();
if (level > 0) {
cout << parentData << "-->" ;
}
cout << node->data << " ";
if (level > 0) {
cout << rightLeftFlag << " ";
}
if (node->left != NULL) {
treeQueue.push(node->left);
levelQueue.push(level + 1);
parentQueue.push(node->data);
rightLeftFlagQueue.push("L");
}
if (node->right != NULL) {
treeQueue.push(node->right);
levelQueue.push(level + 1);
parentQueue.push(node->data);
rightLeftFlagQueue.push("R");
}
}
treeQueue.pop();
levelQueue.pop();
parentQueue.pop();
rightLeftFlagQueue.pop();
}
}
void preOrderTraversal(BinaryTreeNode *root) {
if (root == NULL)
return;
cout << root->data << " ";
preOrderTraversal(root->left);
preOrderTraversal(root->right);
}
void inOrderTraversal(BinaryTreeNode *root) {
if (root == NULL)
return;
inOrderTraversal(root->left);
cout << root->data << " ";
inOrderTraversal(root->right);
}
void postOrderTraversal(BinaryTreeNode *root) {
if (root == NULL)
return;
postOrderTraversal(root->left);
postOrderTraversal(root->right);
cout << root->data << " ";
}
bool isParent(BinaryTreeNode *node1, BinaryTreeNode *node2) {
if (node1 == NULL)
return false;
if (node1 == node2)
return true;
return (isParent(node1->left, node2) || isParent(node1->right, node2));
}
/**
* Find the closest ancestor (if any) that is common to both node1 and node2
* in a binary tree represented by ancestor.
*/
BinaryTreeNode *findCommonAncestor(BinaryTreeNode *ancestor, BinaryTreeNode *node1,
BinaryTreeNode *node2) {
if (ancestor == NULL) {
return NULL;
}
bool isNode1OnLeft = isParent(ancestor->left, node1);
bool isNode2OnLeft = isParent(ancestor->left, node2);
if (isNode1OnLeft != isNode2OnLeft)
return ancestor;
else {
if (isNode1OnLeft)
return findCommonAncestor(ancestor->left, node1, node2);
else
return findCommonAncestor(ancestor->right, node1, node2);
}
}
/**
* Helper to check whether BST
*/
bool checkIfBST(BinaryTreeNode *root, int leftVal, int rightVal) {
if (root == NULL)
return true;
if ((root->data > rightVal) || (root->data < leftVal))
return false;
return (checkIfBST(root->left, leftVal, root->data) &&
checkIfBST(root->right, root->data, rightVal));
}
/**
* Check if a binary tree is a binary search tree (BST)
*/
bool checkIfBST(BinaryTreeNode *root) {
return checkIfBST(root, numeric_limits<int>::min(), numeric_limits<int>::max());
}
/**
* Test the code
*/
int main() {
int treeArray[] = { 9, 13, 14, 15, 16, 17, 1, 2, 10, 11, 12, 3, 4, 5, 6, 7, 8};
cout << "Array: " << endl;
for (int i=0; i<17; i++) {
cout << treeArray[i] << " ";
}
cout << endl << endl;
//Binary tree created from array with each element
BinaryTreeNode *root = createBinaryTreeFromArray(treeArray, 17);
cout << "Binary Tree from array: height = " << root->height() << endl;
printTree(root);
cout << endl << "Found '10' in tree: " <<
(root->find(10) != NULL?"Yes":"No") << endl;
cout << "BST? " << (checkIfBST(root)?"Yes":"No") << endl;
//Pre-Order, In-Order and Post-Order Traversal
cout << endl << "Pre Order Traversal: " << endl;
preOrderTraversal(root);
cout << endl << endl;
cout << "In Order Traversal: " << endl;
inOrderTraversal(root);
cout << endl << endl;
cout << "Post Order Traversal: " << endl;
postOrderTraversal(root);
cout << endl << endl;
//Create a Binary Search Tree from the same array
BinaryTreeNode *rootBST = new BinaryTreeNode(treeArray[0]);
for (int i=1; i<17; i++) {
rootBST->insert(treeArray[i]);
}
cout << endl << "Binary Search Tree from array: height = "
<< rootBST->height() << endl;
printTree(rootBST);
cout << endl << "Found '10' in tree: " <<
(rootBST->find(10)!= NULL?"Yes":"No") << endl;
cout << "BST? " << (checkIfBST(rootBST)?"Yes":"No") << endl;
//Create a minimal Binary Search Tree from the same array
BinaryTreeNode *rootMinBST = createMinimalBSTFromArray(treeArray, 17);
cout << endl << endl << "Minimum Binary Search Tree from array: height = "
<< rootMinBST->height() << endl;
printTree(rootMinBST);
cout << endl << "Found '10' in tree: " <<
(rootMinBST->find(10)!= NULL?"Yes":"No") << endl;
cout << "BST? " << (checkIfBST(rootMinBST)?"Yes":"No") << endl;
BinaryTreeNode *n1 = rootMinBST->find(10);
BinaryTreeNode *n2 = rootMinBST->find(17);
BinaryTreeNode *res = findCommonAncestor(rootMinBST, n1, n2);
cout << endl << "The closest ancestor to " << n1->data << " and " << n2->data
<< " is " << res->data << endl;
delete(root);
delete(rootBST);
delete(rootMinBST);
}