- •Data Structures and Algorithms Topics for the 1st part of the course Prepared by Dr. Alex Ossyka
- •- Representation of objects in computer memory :
- •Iterative implementation (by loop)
- •1St print: 5
- •2Nd print: 9 3d print: 7
- •2Nd print: 5
- •1St print: 9 3d print: 7
- •Balanced Trees
- •Height-Balanced Binary Search Trees
1St print: 5
A.preorder_rec(root)
A.preorder_rec(&n3)
A.preorder_rec(&n2)
call3 return3 call6 return 62Nd print: 9 3d print: 7
A.preorder_rec(null)
A.preorder_rec(null)
A.preorder_rec(null)
A.preorder_rec(null)
call4 return1 call5 return2 call7 return4 call8 return5
*/
//*************************
public void inorder()
{ System.out.println("inorder sequence of nodes:");
inorder_rec(root);
System.out.println(";");
}//inorder
protected void inorder_rec(TNode p)
{ if(p != null)
{ inorder_rec(p.left);
System.out.print(", " + p.data);
inorder_rec(p.right);
}//if
}//inoder_rec
/* tracing the call: A.inorder(). Given object BinaryTree A including objects n1, n2, n3 of TNode class.
#6000
A: root Note: #6000 denotes the address of the node n1, etc.
5
#8000
#9000
#6000n1:
null
9
null
null
7
null
#8000 #9000n2: n3:
main()
After return8, it is printed: , 9, 5, 7
A.inorder()
call1 return8
call2 return7
A.inorder_rec(#6000)
2Nd print: 5
A.preorder_rec(root)
A.inorder_rec(#9000)
A.inorder_rec(#8000)
call3 return3 call6 return 61St print: 9 3d print: 7
A.inorder_rec(null)
A.inorder_rec(null)
A.inorder_rec(null)
A.inorder_rec(null)
call4 return1 call5 return2 call7 return4 call8 return5
*/
//**********************
public void postorder()
{ System.out.println("postorder sequence of nodes:");
postorder_rec(root);
System.out.println(";");
}//postorder
protected void postorder_rec(TNode p)
{ if(p != null) { postorder_rec(p.left);
postorder_rec(p.right);
System.out.print(", " + p.data);
}//if
}//postoder_rec
//*****************************
public int size()
{ return size_rec(root); }//size
protected int size_rec(TNode p)
{ if(p == null) return 0;
else return size_rec(p.left) + size_rec(p.right) + 1;
}// size_rec
//**********************
}//class BinaryTree
Note: Functions of this class are called by objects of other derived classes of binary trees.
Topic 12. Binary Search Tree (BST).
D
x
efinition: A binary search tree is a binary tree where data in each node is greater than its left son data and not greater than its right son data.
z
A: If A is BST then y < x z.
y
Example: Given a sequence of keys: 15, 12, 17, 11, 13, 17, 16. Add them one by one in that sequence to an empty BST.
Algorithm (recursive) of addItem(key) for binary search trees:
Examine the tree
If it is empty then make a root and save key in it;
else if(key < root data) then examine the left subtree;
else examine the right subtree.
Note: a new key is always inserted in the root node of a new subtree.
15
root BinarySearchTree A
12
17
11
13
16
17
Java code of the class BinarySearchTree
Prepared by Dr. Alex Ossyka
//////////////////////////////////////////////////////////////////////////////////////////////////
public class BinarySearchTree extends BinaryTree{
public BinarySearchTree()
{ super(); }//This class inherits the constructor of the BinaryTree class.
//*************************
public boolean search(int item)
{ return search_rec(item, root); }//search
protected boolean search_rec(int item, TNode p)
{ if(p == null)
return false;
if(p.data == item)
return true;
else if(p.data > item)
return search_rec(item, p.left);
else
return search_rec(item, p.right);
}//search_rec
//***************************************
public void addNode(int item)
{ root = addNode_rec(item, root); }//addNode
protected TNode addNode_rec(int item, TNode p)
{ if(p == null)
{ p = new TNode(item);
p.left = p.right = null;
}//if
else if(item < p.data)
p.left = addNode_rec(item, p.left);
else p.right = addNode_rec(item, p.right);
return p;
}//addNode_rec
//*************************
/* Deleting a node by using four member functions
public void deleteNode(int item)
{ root = deleteNode_rec(item, root); }//deleteNode
protected TNode deleteNode_rec(int item, TNode p)
{ if(item < p.data) p.left = deleteNode_rec(item, p.left);
else if(item > p.data) p.right = deleteNode_rec(item, p.right);
else p = delete_NodeFound(p);
return p;
}//deleteNode_rec
protected TNode delete_NodeFound(TNode p)
//It deletes the node referenced by p.
{ int info;
if(p.left == null) return p.right;
else if(p.right == null) return p.left;
else
{ info = getPredecessor(p.left);
p.data = info;
p.left = deleteNode_rec(info, p.left); //delete the predecessor node
return p;
}//else
}//delete_NodeFound
private int getPredecessor(TNode p) //returns data member of the rightmost node in tree
{ while(p.right != null)
p = p.right;
return p.data;
}//getPredecessor
*/
//*************************
//Deleting a tree node by using three member functions
public void deleteNode(int item)
{ root = deleteNode_rec(item, root); }//deleteNode
protected TNode deleteNode_rec(int item, TNode p)
{ if(item < p.data) p.left = deleteNode_rec(item, p.left);
else if(item > p.data) p.right = deleteNode_rec(item, p.right);
else p = delete_NodeFound(p);
return p;
}//deleteNode_rec
protected TNode delete_NodeFound(TNode p) //It deletes the node referenced by p.
{ if(p.left == null) return p.right
else if(p.right == null) return p.left;
else
{ TNode p1 = p;
while(p1.right != null)//searching for rightmost node in tree
p1 = p1.right;
p.data = p1.data; //assigning data member of the rightmost node
p.left = deleteNode_rec(p.data, p.left); //delete the preceding node
return p;
}//else
}//delete_NodeFound
}//class BinarySearchTree}
///////////////////////////////////////////////////////////////////////////
import binarytree.*;
//Dr. Alex Ossyka
public class BinaryTreeTest {
public static void main(String args[])
{
BinarySearchTree A = new BinarySearchTree();
A.addNode(15);
A.addNode(10);
A.addNode(7);
A.addNode(50);
A.addNode(12);
A.addNode(45);
if(A.search(50)) System.out.println("found");
else System.out.println("not found");
if(A.search(60)) System.out.println("found");
else System.out.println("not fount");
A.inorder();
A.preorder();
A.postorder();
int a = A.size();
System.out.println("The number of nodes in tree = " + a);
if(A.search(50))//checking the precondidion for deleteNode()
A.deleteNode(50);
else System.out.println("Item is not in tree. It cannot be deleted.");
A.preorder();
a = A.size();
System.out.println("The number of nodes in tree = " + a);
}//main
}//class BinaryTreeTest
Output of the program
found
not fount
inorder sequence of nodes:
, 7, 10, 12, 15, 45, 50;
preorder sequence of nodes:
, 15, 10, 7, 12, 50, 45;
postorder sequence of nodes:
, 7, 12, 10, 45, 50, 15;
The number of nodes in tree = 6
preorder sequence of nodes:
, 15, 10, 7, 12, 45;
The number of nodes in tree = 5
Binary search tree. Removing a node
Remove operation on binary search tree is more complicated, than add and search. Basically, in can be divided into two stages:
search for a node to remove;
if the node is found, run remove algorithm.
Remove algorithm in detail
Now, let's see more detailed description of a remove algorithm. First stage is identical to algorithm for search, except we should track the parent of the current node. Second part is more tricky. There are three cases, which are described below.
Node to be removed has no children.
This case is quite simple. Algorithm sets corresponding link of the parent to NULL and disposes the node.
Example. Remove -4 from a BST.
Node to be removed has one child.
It this case, node is cut from the tree and algorithm links single child (with it's subtree) directly to the parent of the removed node.
Example. Remove 18 from a BST.
Node to be removed has two children.
This is the most complex case. To solve it, let us see one useful BST property first. We are going to use the idea, that the same set of values may be represented as different binary-search trees. For example those BSTs:
contains
the same values {5, 19, 21, 25}. To transform first tree into second
one, we can do following:
choose minimum element from the right subtree (19 in the example);
replace 5 by 19;
hang 5 as a left child.
The same approach can be utilized to remove a node, which has two children:
find a minimum value in the right subtree;
replace value of the node to be removed with found minimum. Now, right subtree contains a duplicate!
apply remove to the right subtree to remove a duplicate.
Notice, that the node with minimum value has no left child and, therefore, it's removal may result in first or second cases only.
Example. Remove 12 from a BST.
Find minimum element in the right subtree of the node to be removed. In current example it is 19.
Replace 12 with 19. Notice, that only values are replaced, not nodes. Now we have two nodes with the same value.
Remove 19 from the left subtree.
Finally, there is nothing special about the right subtree of a deleted node. We could do the same thing with the left subtree: just use the largest value in the left subtree. In our example we can overwrite the value 12 by 9 (the largest value in the left subtree here) and delete the node with 9 in the left subtree. Now deleting is reduced to case 1 or case 2.
