Counting number of nodes in Binary Search Tree C++ - c++

I am struggling to understand why the function CountNodes() below counts all the nodes in a BST.
If we assume we have the following BST:
20
/ \
10 30
/ \ / \
5 15 25 35
If I call CountNodes(pointer to root node 20); then wouldn't the relevant if statement:
if(root->left!=NULL)
{
n=n+1;
n=CountNodes(root->left);
}
simply look at node 10 and say, yes it is not null, add 1 to the counter n, and then call CountNodes(pointer to 10) which would then just send us down the left branch again to 5. Then when at 5 the left and right variables are NULL and hence the whole CountNodes function just returns n equal to int 3.
I guess I am struggling to understand exactly when the value of the argument to CountNodes is updated. Do we look right and check if its NULL and update the counter before we update the argument value in the first recursive call to CountNodes(pointer to 10) in the left look even though the right look appears after the left recursive call in the code?
#include<iostream>
using namespace std;
int n=1;
struct node
{
int data;
node* left;
node* right;
};
struct node* getNode(int data)
{
node* newNode=new node();
newNode->data=data;
newNode->left=NULL;
newNode->right=NULL;
return newNode;
}
struct node* Insert(struct node* root, int data)
{
if (root == NULL)
return getNode(data);
if (data < root->data)
root->left = Insert(root->left, data);
else if (data > root->data)
root->right = Insert(root->right, data);
return root;
}
int CountNodes(node*root)
{
if(root==NULL)
return 0;
if(root->left!=NULL)
{
n=n+1;
n=CountNodes(root->left);
}
if(root->right!=NULL)
{
n=n+1;
n=CountNodes(root->right);
}
return n;
}
int main()
{
node* root=NULL;
root=Insert(root,10);
Insert(root,5);
Insert(root,20);
Insert(root,4);
Insert(root,8);
Insert(root,15);
Insert(root,25);
cout<<"Total No. of Nodes in the BST = "<<CountNodes(root)<<endl;
return 0;
}

You are overwritting the value of n
n=CountNodes(root->left);
You should be adding the count from the sub tree.
n = n + CountNodes(root->left);
There is also another bug in that you are counting this node twice if the node has a left and right tree and never counting it if the node has no subtrees.
if(root->left!=NULL)
{
n=n+1; // Adding one for this node.
n=CountNodes(root->left);
}
if(root->right!=NULL)
{
n=n+1; // Adding one for this node again?
n=CountNodes(root->right);
}
I think you should be doing:
if(root->left!=NULL)
{
n = n + CountNodes(root->left);
}
if(root->right!=NULL)
{
n = n + CountNodes(root->right);
}
n = n + 1;
The next thing is that you check for null on entry into the function. So you don't need to test for null before doing a recursive call.
n = n + CountNodes(root->left);
n = n + CountNodes(root->right);
n = n + 1;
We can then simplify this to:
int CountNodes(node* root)
{
if (root == nullptr) {
return 0;
}
return 1 + CountNodes(root->left) + CountNodes(root->right);
}

Related

Floor Value of an element in a Binary Search Tree

So I was reading the book - Data Structures and Algorithms Made Easy by Narasimha Karumanchi and in that the floor Value of a bst snippet is given - Problem 61 in BST Chapter.
The snippet confused me very much and now I just want to know how it is working :
The snippet as Follows :
node* floorValue(node* root, node* prev ,int k)
{
if(!root){
return NULL;
}
if( !(floorValue(root->left , prev ,k))
{
return 0;
}
if(root->data == k)
{
return root;
}
if(root->data > k)
{
return prev;
}
prev = root;
return floorValue(root->right , prev , k);
}
In this the node* prev which is initiated with NULL is storing the previous node and int k is the integer for which we are finding the floor value.
Can someone please help me in understanding its recursion. I am confused because :
1 . The code : if( !(floorValue(root->left , prev ,k)) { return 0; }
will return 0 when the left most of the element of the tree is hit. But that will trigger all the recursive calls return 0.
Why it's returning 0 when we are returning the node* and not any int
Help will be really appreciated. I have solved this question but it was not using this method but a more straight forward one ( according to me ). I want to know what am I doing wrong or what I am missing in this code.
Input:
The First input will be the number of nodes:
The next n lines will be the nodes data. The first input after n will be the root value.
FULL CODE:
#include<bits/stdc++.h>
using namespace std;
struct node
{
int data;
node* left;
node* right;
};
node* insertBST(node* root , int x)
{
if(root==NULL)
{
node* root= new node;
root->data = x;
root->left = root->right = NULL;
return root;
}
else
{
if(x <root->data)
{
root->left = insertBST(root->left , x);
}
else
{
root->right = insertBST(root->right , x);
}
}
}
void inorder(node* root)
{
if(root)
{
inorder(root->left);
cout<<root->data<<" ";
inorder(root->right);
}
}
node* floorValue(node* root, node* prev ,int k)
{
if(!root){
return NULL;
}
if( !(floorValue(root->left , prev ,k))
{
return 0;
}
if(root->data == k)
{
return root;
}
if(root->data > k)
{
return prev;
}
prev = root;
return floorValue(root->right , prev , k);
}
int main()
{
int n;
cin>>n;
node *root = new node;
root = NULL;
for(int i = 0 ;i<n;i++)
{
int k;
cin>>k;
root= insertBST(root , k);
}
inorder(root);
cout<<"\nEnter the Value for which floor has to be searched : ";
int k;
cin>>k;
node* prev = NULL;
cout<<floorValue(root , prev, k);
return 0;
}
The code is exactly the same as given in the book except some variable names.
Thank You and thanks in advance.
The snippet you found is awful, but the answer to your questions is that return 0 is the same as return NULL -- it's not an integer, it's a null pointer. The code is supposed to return null if there is no node in the tree <= the search value.
Here's a much better implementation:
Node* floorNode(Node* tree, int k) {
Node *flr = NULL;
while(tree) {
if (tree -> data <= k) {
flr = tree;
tree = tree->right;
} else {
tree = tree->left;
}
}
return flr;
}
It's classic Binary Search algorithm. I always recommend you to understand the problem you posted. If you clear with algorithm you will know how Binary Search actualy works, as well as how Backtrack works using StackTrace of your system/computer memory.
Let's dive into that. :)
if(!root){
return NULL;
}
the above code snippet, is the case, if you reach here, it is guranteed you searched all the possibilities, but didn't find the 'key' you want. :(
if( !(floorValue(root->left , prev ,k))
{
return NULL;
}
Remember you should return NULL, instead of return 0, since the return value of your function is actually NULL, (though both 0/NULL defines the false case in c/c++, prematurely you can use any of it.
Now you can see, you are diving into the function, with root->left, means left-part of Tree are checking first, similar to Binary Search, where you are searching left side of your input elements.
if(root->data == k)
{
return root;
}
If you reach here, congrats, you finally reached into your destination :D, other words, you found your result in huge (or small, whatever) input elements.
if(root->data > k)
{
return prev;
}
The above snippent is same when your middle elements are greater than your key, so you know you have to go left side of your inputs. (going right will always give you Sadness, you will ended up with nothing).
prev = root;
return floorValue(root->right , prev , k);
The above code are telling you, you went left, but got 0 (you ended up with failure to find the result), so you need to go right side now.
Now most importantly, understand these two following snippets ::
if(root->data > k)
{
return prev;
}
and
prev = root;
return floorValue(root->right , prev , k);
The above two snippets not only dive you into left or right part of your tree (or inputs) but also checking each and every left and right node of your left Tree, and right and left of your right Tree.
When its failed to get the key you want, it's backtrack to your place where you started to go into LEFT (it's kind of DARK series, let's assume left is PAST here, :D right?? ) now you have to go to future, that's RIGHT, to find out the key.
you get the key ? return it from the left(past), or go to right(future) again.
you will definitely reach a conclusion, either SUCCESS or FAILURE.
enjoy.

recursive code for finding the height of a binary tree

I am trying to find the height of a binary tree and here is my attempt at the same
#include<iostream>
#include<stack>
using namespace std;
int total = 0;
int length = -1;
class Node{
public:
int data;
Node *left;
Node *right;
Node(int k){
data = k;
left = right = NULL;
}
};
void height(Node *root){
if(root==NULL)
return;
length++;
if(length>total)
total = length;
height(root->left);
height(root->right);
}
int main(){
Node *root = new Node(3);
root->left = new Node(4);
root->left->left = new Node(5);
root->right = new Node(6);
root->right->left = new Node(7);
height(root);
cout<<total;
return 0;
}
here length and total have been declared as global variables having values -1 and 0 respectively.
When I run the code, the output which I am getting is the number of nodes in the tree - 1 but not the height of the tree. Please let me know my mistake here.
Sure, you're incrementing length on every node.
If you're doing it recursively, it is actually very simple:
std::size_t height(Node const *root) {
if(!root) return 0;
return 1 + std::max(height(root->left), height(root->right));
}
Your approach is more of a backtracking than a simple recursion. In this approach you should be mindful to revert back to the original state at each step. Here length is always being incremented. You should revert it back.
void height(Node *root){
if(root==NULL)
return;
length++;
total = std::max(total,length+1); // Either this or initialize length as 0
height(root->left);
height(root->right);
length--; // <--- Add this line
}

AVL TREE - Most efficient way to print a value, by location. C++

Hey I have to find the most eficient way to print a number by giving the postion. The input is like this:
8 (N-> N Numbers)
INS 100 (Add 100 to the tree)
INS 200 (Add 200 to the tree)
INS 300 (Add 300 to the tree)
REM 200 (Remove the number 200 from the tree)
PER 1 (Have to output the biggest number in the tree-> Shoud print 300)
INS 1000 (Add 1000 to the tree)
PER 1 ((Have to output the biggest number in the tree-> Shoud print 1000))
PER 2 (I have to output the second biggest number so: 300)
I have a way to print like this, but is very slow and I have to maintain a O(N * log(N)).
Here is my full code
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
using namespace std;
// An AVL tree node
struct node
{
int key;
struct node *left;
struct node *right;
int height;
};
// A utility function to get maximum of two integers
int max(int a, int b);
// A utility function to get height of the tree
int height(struct node *N)
{
if (N == NULL)
return 0;
return N->height;
}
// A utility function to get maximum of two integers
int max(int a, int b)
{
return (a > b)? a : b;
}
/* Helper function that allocates a new node with the given key and
NULL left and right pointers. */
struct node* newNode(int key)
{
struct node* node = (struct node*)
malloc(sizeof(struct node));
node->key = key;
node->left = NULL;
node->right = NULL;
node->height = 1; // new node is initially added at leaf
return(node);
}
// A utility function to right rotate subtree rooted with y
// See the diagram given above.
struct node *rightRotate(struct node *y)
{
struct node *x = y->left;
struct node *T2 = x->right;
// Perform rotation
x->right = y;
y->left = T2;
// Update heights
y->height = max(height(y->left), height(y->right))+1;
x->height = max(height(x->left), height(x->right))+1;
// Return new root
return x;
}
// A utility function to left rotate subtree rooted with x
// See the diagram given above.
struct node *leftRotate(struct node *x)
{
struct node *y = x->right;
struct node *T2 = y->left;
// Perform rotation
y->left = x;
x->right = T2;
// Update heights
x->height = max(height(x->left), height(x->right))+1;
y->height = max(height(y->left), height(y->right))+1;
// Return new root
return y;
}
// Get Balance factor of node N
int getBalance(struct node *N)
{
if (N == NULL)
return 0;
return height(N->left) - height(N->right);
}
struct node* insert(struct node* node, int key)
{
/* 1. Perform the normal BST rotation */
if (node == NULL)
return(newNode(key));
if (key < node->key)
node->left = insert(node->left, key);
else
node->right = insert(node->right, key);
/* 2. Update height of this ancestor node */
node->height = max(height(node->left), height(node->right)) + 1;
/* 3. Get the balance factor of this ancestor node to check whether
this node became unbalanced */
int balance = getBalance(node);
// If this node becomes unbalanced, then there are 4 cases
// Left Left Case
if (balance > 1 && key < node->left->key)
return rightRotate(node);
// Right Right Case
if (balance < -1 && key > node->right->key)
return leftRotate(node);
// Left Right Case
if (balance > 1 && key > node->left->key)
{
node->left = leftRotate(node->left);
return rightRotate(node);
}
// Right Left Case
if (balance < -1 && key < node->right->key)
{
node->right = rightRotate(node->right);
return leftRotate(node);
}
/* return the (unchanged) node pointer */
return node;
}
/* Given a non-empty binary search tree, return the node with minimum
key value found in that tree. Note that the entire tree does not
need to be searched. */
struct node * minValueNode(struct node* node)
{
struct node* current = node;
/* loop down to find the leftmost leaf */
while (current->left != NULL)
current = current->left;
return current;
}
struct node* apagaNode(struct node* root, int key)
{
// STEP 1: PERFORM STANDARD BST DELETE
if (root == NULL)
return root;
// If the key to be deleted is smaller than the root's key,
// then it lies in left subtree
if ( key < root->key )
root->left = apagaNode(root->left, key);
// If the key to be deleted is greater than the root's key,
// then it lies in right subtree
else if( key > root->key )
root->right = apagaNode(root->right, key);
// if key is same as root's key, then This is the node
// to be deleted
else
{
// node with only one child or no child
if( (root->left == NULL) || (root->right == NULL) )
{
struct node *temp = root->left ? root->left : root->right;
// No child case
if(temp == NULL)
{
temp = root;
root = NULL;
}
else // One child case
*root = *temp; // Copy the contents of the non-empty child
free(temp);
}
else
{
// node with two children: Get the inorder successor (smallest
// in the right subtree)
struct node* temp = minValueNode(root->right);
// Copy the inorder successor's data to this node
root->key = temp->key;
// Delete the inorder successor
root->right = apagaNode(root->right, temp->key);
}
}
// If the tree had only one node then return
if (root == NULL)
return root;
// STEP 2: UPDATE HEIGHT OF THE CURRENT NODE
root->height = max(height(root->left), height(root->right)) + 1;
// STEP 3: GET THE BALANCE FACTOR OF THIS NODE (to check whether
// this node became unbalanced)
int balance = getBalance(root);
// If this node becomes unbalanced, then there are 4 cases
// Left Left Case
if (balance > 1 && getBalance(root->left) >= 0)
return rightRotate(root);
// Left Right Case
if (balance > 1 && getBalance(root->left) < 0)
{
root->left = leftRotate(root->left);
return rightRotate(root);
}
// Right Right Case
if (balance < -1 && getBalance(root->right) <= 0)
return leftRotate(root);
// Right Left Case
if (balance < -1 && getBalance(root->right) > 0)
{
root->right = rightRotate(root->right);
return leftRotate(root);
}
return root;
}
int imprime(struct node *root,int targetPos,int curPos)
{
if(root != NULL)
{
int newPos = imprime(root->left, targetPos, curPos);
newPos++;
if (newPos == targetPos)
{
printf("%d\n", root->key);
}
return imprime(root->right, targetPos, newPos);
}
else
{
return curPos;
}
}
int main()
{
struct node *root = NULL;
int total=0;
int n,b;
string a;
cin >> n;
for (int i=0; i<n; i++)
{
cin >> a >> b;
if(a=="INS")
{root = insert(root, b);total=total+1;}
else
if(a=="REM")
{root = apagaNode(root, b);total=total-1;}
else
imprime(root, total-b+1, 0);
}
return 0;
}
The way I found to print the values:
int imprime(struct node *root,int targetPos,int curPos)
{
if(root != NULL)
{
int newPos = imprime(root->left, targetPos, curPos);
newPos++;
if (newPos == targetPos)
{
printf("%d\n", root->key);
}
return imprime(root->right, targetPos, newPos);
}
else
{
return curPos;
}
}
Problem is that this function is very slow, and I can't use it. How is the best way to print by a given postion like this? (A heard about, counting n_nodes, and during the rotations I have to incremennt, decrement, i realy did not understand. Help me please! Give some tips, and advices) (PS: I'm not an expert with this kind of algorithms)
The advice you heard is correct: you should add a node counter to your node structure:
struct node
{
int key;
struct node *left;
struct node *right;
int height;
int n_nodes;
};
It should hold the number of nodes in the tree. Assuming it's correct, you can improve the algorithm for finding a node with a target position: it will know exactly in which branch of the tree to look (left or right), which will make the search faster (current imprime implementation is O(n)).
So, how to make it so the n_nodes field holds the right value? Fortunately, you already have an example: height. Look where your existing code changes it; these are roughly the places where you have to update n_nodes, too. Most of them are trivial (just add 1 to it); the more interesting ones are the rotation functions:
struct node *rightRotate(struct node *y)
{
struct node *x = y->left;
struct node *T2 = x->right;
// Perform rotation
x->right = y;
y->left = T2;
// Update heights
y->height = max(height(y->left), height(y->right))+1;
x->height = max(height(x->left), height(x->right))+1;
// Update numbers of nodes
x->n_nodes = ...;
y->n_nodes = ...;
T2->n_nodes = ...;
// Return new root
return x;
}
So it transforms the tree like this:
y x
/ \ / \
x D A y
/ \ ==> / \
A T2 T2 D
/ \ / \
B C B C
Here A, B, C and D are trees whose sizes your program knows; let's denote their sizes as a, b, c and d. So the transformation changes these sizes like this:
size of x: from a+b+c+2 to a+b+c+d+3
size of y: from a+b+c+d+3 to b+c+d+2
size of T2: unchanged
So just transform this to code.

C++: Sum of all node values of a binary tree

I'm preparing for a job interview. I was stuck at one of the binary tree questions:
How can we calculate the sum of the values present in all the nodes of a binary tree?
The elegant recursive solution (in pseudo-code):
def sum (node):
if node == NULL:
return 0
return node->value + sum (node->left) + sum (node->right)
then just use:
total = sum (root)
This correctly handles the case of a NULL root node.
And if you want to see it in action in C++, here's some code using that algorithm. First, the structure for a node and the sum function:
#include <iostream>
typedef struct sNode {
int value;
struct sNode *left;
struct sNode *right;
} tNode;
int sum (tNode *node) {
if (node == 0) return 0;
return node->value + sum (node->left) + sum (node->right);
}
Then the code below is a test harness code for inserting nodes:
static tNode *addNode (tNode *parent, char leftRight, int value) {
tNode *node = new tNode();
node->value = value;
node->left = 0;
node->right = 0;
if (parent != 0) {
if (leftRight == 'L') {
parent->left = node;
} else {
parent->right = node;
}
}
return node;
}
And, finally, the main function for constructing the following tree, one that covers all of the valid possibilities (empty node, node with two children, node with no children, node with one right child and node with one left child):
10
/ \
7 20
/ \
3 99
\
4
\
6
The code to construct that tree and report the sum at various points is shown here:
int main (void) {
// Empty tree first.
tNode *root = 0;
std::cout << sum (root) << '\n';
// Then a tree with single node (10).
root = addNode (0, ' ', 10);
std::cout << sum (root) << '\n';
// Then one with two subnodes (10, 7, 20).
addNode (root,'L',7);
addNode (root,'R',20);
std::cout << sum (root) << '\n';
// Then, finally, the full tree as per above.
addNode (root->left,'L',3);
addNode (root->left->left,'R',4);
addNode (root->left->left->right,'R',6);
addNode (root->right,'R',99);
std::cout << sum (root) << '\n';
return 0;
}
This outputs (the correct):
0
10
37
149
Traverse the tree in any order (pre, post, in). Instead of printing the node calculate the total.
void sum(Node* root, int& total)
{
if(root == NULL)
{
return;
}
sum(root->left, total);
total = total + root->value;
sum(root->right, total);
}
int main()
{
int total =0;
sum(root,total);
cout << total;
}
The same way you search the tree, or display each node, or any other tree-wide operation: visit the current node, visit the left sub-tree (recursively), and visit the right sub-tree (recursively).
Essentially, something like this:
int TreeNode::calculateSum() const
{
int sum = this->value;
if (this->left != NULL) sum += this->left ->calculateSum();
if (this->right != NULL) sum += this->right->calculateSum();
return sum;
}
Because of the if checks the recursion will eventually bottom out when it reaches nodes with no left or right children (leaf nodes).
While the STL has more complex and concise mechanisms for doing this, it's a very fast rode to productivity just to learn to use a manual loop over a container, something like:
Tree::value_type total = Tree::value_type();
for (Tree::const_iterator i = tree.begin(); i != tree.end(); ++i)
total += *i;
This assumes your binary tree is a STL::map, or if not you'll provide an iterator concept for your own implementation....
Use one of the Tree Traversal techniques(In-order, Pre-order, Post-order) to visit each node and store the sum in a variable.
You can find more details on tree traversal in this wiki
50
/ \
30 70
/ \ / \
20 40 60 80
returns:350
int Sum(struct node *root)
{
if(root->left == NULL && root->right== NULL)
return root->key;
int lvalue,rvalue;
lvalue=Sum(root->left);
rvalue=Sum(root->right);
return root->key+lvalue+rvalue;
}
public int sum(Node root){
if(root==null){
return 0;
}
if(root.left == null && root.right==null){
return root.key;
}
return sum(root.left)+sum(root.right)+root.key;
}

How to convert a binary search tree into a doubly linked list?

Given a binary search tree, i need to convert it into a doubly linked list(by traversing in zig zag order) using only pointers to structures in C++ as follows,
Given Tree:
1
|
+-------+---------+
| |
2 3
| |
+----+---+ +----+---+
| | | |
4 5 6 7
| | | |
+--+--+ +--+--+ +--+--+ +--+--+
| | | | | | | |
8 9 10 11 12 13 14 15
Node Structure:
struct node
{
char * data;
node * left;
node * right;
};
Create List(zig zag order):
1 <-> 3 <-> 2 <-> 4 <-> 5 <-> 6 <-> 7 <-> 15 <-> ... <-> 8
Could someone please help me out.
This is a Breadth-first search algorithm. Wikipedia has a good explanation on how to implement it.
After implementing the algorithm, creating your linked list should be a no-brainer (since it will only be a matter of appending each visited element to the list)
That's an awkward type of tree traversal. I wonder how often anyone has ever actually needed to do such a thing in real code. Nevertheless, it's the problem to be solved here...
Here's how I would approach dealing with this:
First, when I compare the desired output to the structure of the tree, I notice that each "level" of the tree is processed in turn from top to bottom. So top node first, then all child nodes, then all grand-child notes, and so on. So probably a good solution will involve a loop that processes one level and at the same time builds up a list of nodes in the next level to be used in the next iteration of the loop.
Next, this "zig zag" order means it needs to alternate which direction the child nodes are processed in. If a particular iteration goes from left to right, then the next iteration must go from right to left. And then back to left to right for the subsequent iteration and so on. So in my idea of a loop that processes one level and builds a list of the next level, it probably needs to have some sort of alternating behavior when it builds that list of nodes for the next level. On even iterations the list is built one way. On odd iterations the list is built the other way.
Alternatively, another other way to think about this whole thing is: Design a solution to that can build the result list in 1,2,3,4,5,6,etc order. Then modify that design to have the zig zag order.
Does this give you enough of an idea on how to design a solution?
This might help you:
Create a separate list for every level of the tree
Traverse the tree and copy the values to the lists as you traverse the tree
Reverse the order of every other list
Connect the lists
In this solution below I have used two stacks to store Levels alternatively.
say nodes at level 0 will be store in stack 1 whose name is head1;now pop the element while it not become empty and push the elements in stack 2.the order i.e left or right child of insertion will depend on the level.and change the insertion order at each level.
node * convert_to_dll(node *p)
{
static int level=0;
push_in_stack(p,&head1);
printf("%d\n",p->data);
while( head1!=NULL || head2!=NULL) {
//pop_from_queue(&headq);
if(head1!=NULL && head2==NULL) {
while(head1!=NULL) {
if(level%2==0) {
node *p;
p=new node;
p=pop_from_stack(&head1);
if(p->right!=NULL) {
push_in_stack(p->right,&head2);
printf("%d\n",(p->right)->data);
}
if(p->left!=NULL)
{
push_in_stack(p->left,&head2);
printf("%d\n",(p->left)->data);
}
}
}
//traverse_stack(head2);
level++;
} else {
while(head2!=NULL) {
if(level%2!=0) {
node *q;
q=new node;
q=pop_from_stack(&head2);
if(q->left!=NULL) {
push_in_stack(q->left,&head1);
printf("%d\n",(q->left)->data);
}
if(q->right!=NULL) {
push_in_stack(q->right,&head1);
printf("%d\n",(q->right)->data);
}
}
} //traverse_stack(head2);
level++;
}
}
return p;
}
you can write a function to add nodes in a doubly linked list. You can then call this function while traversing the tree. In this way you should be able to do it.
Hmm... This is a tough one. The problem with traversal in this order is that you are doing a lot of skipping around. This is generally true in any tree traversal order that is not depth or breadth first.
Here's how I would resolve the situation. Start with a single, empty array of lists of nodes and begin traversing the tree depth first. Be sure to keep track of the depth of your traversal.
At each point in traversal, note the depth of your traversal and pick the list at the index in the array. If there isn't one there, add it first. If the depth is even (Assuming root has depth 0), add the node to the end of the list. If it's odd, add it to the beginning.
Once you've traversed all nodes, concatenate the lists.
Why use pointers?? You could just store your BST as an array A[1...n]. So, A[1] would have root, A[2] and A[3] would have nodes of the depth 1, etc. This is possible since it is an almost complete tree, and you know how many elements will be present at a given depth - i.e. 2^d at depth d (except of course at the last depth). Now all you've got to do is access the array in a zag-zag manner, and create a new BST (array) of the new order. So, how would you traverse the array in a zig-zag manner?? For any given element A[i], the left child would be A[2i] and the right child A[2i + 1]. So, if your current depth d is odd, then traverse 2^d elements, and when you reach the 2^dth element, go to its left child. If your current depth d is even, again traverse 2^d elements, but when you reach the 2^dth element, go to its right child. Storing them as arrays rather than nodes makes your data structure leaner, and your implementation simpler.
This ( http://cslibrary.stanford.edu/109/TreeListRecursion.html) has the answer with pretty pictures :)
#include<iostream>
#include<conio.h>
using namespace std;
class TreeNode
{
public:
int info;
TreeNode* right;
TreeNode* left;
//TreeNode* parent;
TreeNode()
{
info = 0;
right = left = NULL;
}
TreeNode(int info)
{
this -> info = info;
right = left = NULL;
}
};
class ListNode
{
public:
int info;
ListNode* next;
ListNode()
{
info = 0;
next = NULL;
}
ListNode(int info)
{
this -> info = info;
next = NULL;
}
};
TreeNode* root = NULL;
ListNode* start;
ListNode* end;
void addTreeNode(TreeNode*);
void convertTreeToList(TreeNode*);
void printList(ListNode*);
int findDepth(TreeNode*);
int _tmain(int argc, _TCHAR* argv[])
{
start = end = new ListNode(0);
char choice = 'y';
int info;
while(choice == 'y')
{
cout<<"Enter the info of new node:\n";
cin>>info;
addTreeNode(new TreeNode(info));
cout<<"Want to add a new node to the tree?(y/n)\n";
cin>>choice;
}
cout<<"Depth of the tree is: "<<findDepth(root);
cout<<"Converting the tree into a doubly linked list....\n";
convertTreeToList(root);
printList(start->next);
cin>>choice;
return 0;
}
void addTreeNode(TreeNode* node)
{
if(!root)
{
root = node;
}
else
{
TreeNode* currRoot = root;
while(1)
{
if(node -> info >= currRoot -> info)
{
if(!currRoot -> right)
{
currRoot -> right = node;
break;
}
else
{
currRoot = currRoot -> right;
}
}
else
{
if(!currRoot -> left)
{
currRoot -> left = node;
break;
}
else
{
currRoot = currRoot -> left;
}
}
}
}
}
void convertTreeToList(TreeNode* node)
{
if(node -> left != NULL)
{
convertTreeToList(node -> left);
}
end ->next = new ListNode(node -> info);
end = end -> next;
end -> next = start;
if(node -> right != NULL)
{
convertTreeToList(node -> right);
}
}
void printList(ListNode* start)
{
while(start != ::start)
{
cout<<start->info<<" -> ";
start = start -> next;
}
cout<<"x";
}
int findDepth(TreeNode* node)
{
if(!node)
{
return 0;
}
else
{
return (max(findDepth(node -> left), findDepth(node -> right)) + 1);
}
}
Linked list you get here is singly linked and sorted. Hope you can easily make changes in this code to get a doubly linked list. Just copy - paste this code and compile it.It will work fine.
Let us assume that the root of the binary tree is at level 0(an even number). Successive levels can be considered as alternating between odd even (children of root are at odd level, their children are at even level etc.). For a node at even level, we push its children onto a stack(This enables reverse traversal). For a node at odd level, we push its children onto a queue(This enables forward traversal). After children have been pushed, we remove the next available element (top of stack or front of queue) and recursively call the function by changing level to odd or even depending on where the removed element lies. The removed element can be inserted at the end of the doubly linked list. Pseudo-code below.
// S = stack [accessible globally]
// Q = queue [accessible globally]
//
// No error checking for some corner cases to retain clarity of original idea
void LinkNodes(Tree *T,bool isEven,list** l)
{
if(isEven) {
S.push(T->right);
S.push(T->left);
while( !S.empty() ) {
t = S.pop();
InsertIntoLinkedList(l,t);
LinkNodes(t,!isEven);
}
} else {
Q.enque(T->left);
Q.enque(T->right);
while( !Q.empty() ) {
t = Q.deque();
InsertIntoLinkedList(l,t);
LinkNodes(t,isEven);
}
}
}
In the calling function:
bool isEven = true;
list *l = NULL;
// Before the function is called, list is initialized with root element
InsertIntoLinkedList(&l,T);
LinkNodes(T,isEven,&l);
/* * File: main.cpp * Author: viswesn * * Created on December 1, 2010, 4:01 PM */
struct node {
int item;
struct node *left;
struct node *right;
struct node *next;
struct node *prev;
};
struct node *dlist = NULL;
struct node *R = NULL;
struct node* EQueue[10] = {'\0'};
int Etop = 0;
struct node* OQueue[10] = {'\0'};
int Otop = 0;
int level=-1;
struct node *insert(struct node *R, int item)
{
struct node *temp = NULL;
if (R != NULL) {
if (item < R->item) {
R->left = insert(R->left, item);
} else {
R->right = insert(R->right, item);
}
} else {
temp = (struct node *)malloc(sizeof(struct node));
if (temp == NULL) {
return NULL;
}
temp->item = item;
temp->left = NULL;
temp->right = NULL;
temp->next = NULL;
temp->prev = NULL;
R = temp;
}
return R;
}
void print(struct node *node)
{
if (node != NULL) {
print(node->left);
printf("%d<->", node->item);
print(node->right);
}
}
void EvenEnqueue(struct node *item) {
if (Etop > 10) {
printf("Issue in EvenEnqueue\n");
return;
}
EQueue[Etop] = item;
Etop++;
}
void OddEnqueue(struct node *item)
{
if (Otop > 10){
printf("Issue in OddEnqueue\n");
return;
}
OQueue[Otop] = item;
Otop++;
}
int isEvenQueueEmpty() {
if (EQueue[0] == '\0') {
return 1;
}
return 0;
}
int isOddQueueEmpty()
{
if (OQueue[0] == '\0') {
return 1;
}
return 0;
}
void EvenDQueue()
{
int i = 0;
for(i=0; i< Etop; i++)
EQueue[i]='\0';
Etop = 0;
}
void OddDQueue()
{
int i = 0;
for(i=0; i< Otop; i++)
OQueue[i]='\0';
Otop = 0;
}
void addList() {
int counter = 0;
struct node *item = NULL;
if (level%2 == 0) {
/* Its Even level*/
while(counter < Etop)
{
struct node *t1 = EQueue[counter];
struct node *t2 = EQueue[counter+1];
if ((t1!=NULL) && (t2!=NULL)) {
t1->next = t2;
t2->prev = t1;
}
counter++;
}
item = EQueue[0];
} else {
/* Its odd level */
while(counter < Otop)
{
struct node *t1 = OQueue[counter];
struct node *t2 = OQueue[counter+1];
if ((t1!=NULL) && (t2!=NULL)) {
t2->next = t1;
t1->prev = t2;
}
counter++;
}
item = OQueue[Otop-1];
}
if(dlist !=NULL) {
dlist->next = item;
}
item->prev = dlist;
if (level%2 == 0) {
dlist = EQueue[Etop-1];
} else {
dlist = OQueue[0];
}
}
void printTree()
{
int nodeCount = 0;
int counter = 0;
if (!isEvenQueueEmpty()) {
/* If even level queue is not empty */
level++;
nodeCount = pow(2,level);
printf("[");
while(counter < nodeCount) {
if (EQueue[counter] != '\0') {
struct node *t = EQueue[counter];
printf("%d<->", t->item);
if (t->left != NULL)
OddEnqueue(t->left);
if (t->right != NULL)
OddEnqueue(t->right);
} else {
break;
}
counter++;
}
addList();
printf("]");
EvenDQueue();
}
counter = 0;
if (!isOddQueueEmpty()){
/* If odd level queue is not empty */
level++;
nodeCount = pow(2,level);
printf("[");
while(counter < nodeCount){
if (OQueue[counter] != '\0') {
struct node *t = OQueue[counter];
printf("%d<->", t->item);
if (t->left != NULL)
EvenEnqueue(t->left);
if (t->right != NULL)
EvenEnqueue(t->right);
} else {
break;
}
counter++;
}
addList();
printf("]");
OddDQueue();
}
if (isEvenQueueEmpty() && isOddQueueEmpty()){
return;
}
else {
printTree();
}
}
void printLevel(struct node *node)
{
if (node == NULL)
return;
EvenEnqueue(node);
printTree();
printf("\n");
}
void printList(struct node *item)
{
while(item!=NULL) {
printf("%d->", item->item);
item = item->next;
}
}
int main(int argc, char** argv) {
int a[]={20,30,40,12,2,15,18};
int size = sizeof(a)/sizeof(int);
int i = 0;
for(i=0; i< size; i++) {
R = insert(R, a[i]);
}
printf("Inoder traversal - Binary tree\n");
print(R);
printf("\n\n");
printf("Level traversal - Binary tree\n");
printLevel(R);
printf("\n");
printf("Double link list traversal - Binary tree\n");
printList(R);
printf("\n");
return 0;
}