Difference between revisions of "CSC212 IntBST.java: A Non-Generic BST Implementation"
(Created page with "--~~~~ ---- <br /> <source lang="java"> →* * IntBST.java * @author D. Thiebaut, adapted from Drozdek's textbook. * Basic implementation of a Binary-Search Tree.: impor...") |
|||
Line 3: | Line 3: | ||
<br /> | <br /> | ||
<source lang="java"> | <source lang="java"> | ||
+ | |||
/** | /** | ||
* IntBST.java | * IntBST.java | ||
− | * @author D. Thiebaut, adapted from Drozdek's | + | * @author D. Thiebaut |
− | * | + | * All material taken from, or adapted from Drozdek's |
+ | * Data Structures and Algorithms in Java. | ||
+ | * | ||
*/ | */ | ||
− | |||
import java.util.LinkedList; | import java.util.LinkedList; | ||
import java.util.List; | import java.util.List; | ||
import java.util.Queue; | import java.util.Queue; | ||
+ | /** | ||
+ | * A class implementing a BST node, with an integer key, | ||
+ | * and a left and right pointer. | ||
+ | * @author thiebaut | ||
+ | * | ||
+ | */ | ||
class IntBSTNode { | class IntBSTNode { | ||
− | + | ||
− | + | public int key; | |
− | + | public IntBSTNode left, right; | |
− | + | IntBSTNode( int el, IntBSTNode l, IntBSTNode r ) { | |
− | + | key = el; | |
− | + | left = l; | |
− | + | right = r; | |
− | + | } | |
− | + | ||
− | + | IntBSTNode( int el ) { | |
− | + | this( el, null, null ); | |
− | + | } | |
} | } | ||
+ | /** | ||
+ | * The tree class. Implements most useful methods. | ||
+ | * @author thiebaut | ||
+ | * | ||
+ | */ | ||
public class IntBST { | public class IntBST { | ||
− | + | protected IntBSTNode root; | |
− | + | ||
− | + | /** | |
− | + | * constructor creates an empty tree. | |
− | + | */ | |
− | + | IntBST( ) { | |
− | + | root = null; | |
− | + | } | |
− | + | ||
− | + | protected void setRoot( IntBSTNode p ) { | |
− | + | root = p; | |
− | + | } | |
− | + | ||
− | + | public void clear() { | |
− | + | root = null; | |
− | + | } | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | /** | |
− | + | * Just use for debugging... Recursively visits the tree | |
+ | * and display information about what it finds. | ||
+ | */ | ||
+ | protected void debugVisit() { | ||
+ | debugVisit( root ); | ||
+ | } | ||
+ | |||
+ | protected void debugVisit( IntBSTNode p ) { | ||
+ | if ( p==null ) return; | ||
+ | String leftString="has no left child", rightString = "has no right child"; | ||
+ | if ( p.left != null) leftString = "has " + p.left.key + " as left child"; | ||
+ | if ( p.right != null) rightString = "has " + p.right.key + " as right child"; | ||
+ | System.out.println( "Node " + p.key + ", " + leftString + ", and " + rightString ); | ||
+ | debugVisit( p.left ); | ||
+ | debugVisit( p.right ); | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Iteratively searches for an element in the tree. Returns the node | ||
+ | * containing the element if found, or null otherwise. | ||
+ | * @param el | ||
+ | * @return | ||
+ | */ | ||
+ | public IntBSTNode search( int el ) { | ||
+ | IntBSTNode p = root; | ||
+ | while ( p != null ) { | ||
+ | if ( el == p.key ) | ||
+ | return p; | ||
+ | if ( el < p.key ) | ||
+ | p = p.left; | ||
+ | else | ||
+ | p = p.right; | ||
+ | } | ||
+ | return null; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * recursively searches for an element in the tree. Returns the | ||
+ | * node containing the element, or null if not found. | ||
+ | * @param el | ||
+ | * @return | ||
+ | */ | ||
+ | public IntBSTNode recSearch( int el ) { | ||
+ | return recSearch( root, el ); | ||
+ | } | ||
− | + | private IntBSTNode recSearch( IntBSTNode p, int el ) { | |
− | + | if ( p==null ) | |
− | + | return null; | |
− | + | if ( el == p.key ) | |
− | + | return p; | |
− | + | if ( el < p.key ) | |
− | + | return recSearch( p.left, el ); | |
− | + | else | |
− | + | return recSearch( p.right, el ); | |
− | + | } | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | ||
− | + | /** | |
− | + | * Traveral methods | |
− | + | * inOrderVisit | |
− | + | * preOrderVisit | |
− | + | * postOrderVisit | |
− | + | */ | |
− | + | public void inOrderVisit() { | |
− | + | inOrderVisit( root ); | |
− | + | System.out.println(); | |
− | + | } | |
− | + | ||
− | + | private void inOrderVisit( IntBSTNode p ) { | |
− | + | if ( p==null ) | |
− | + | return; | |
− | + | inOrderVisit( p.left ); | |
− | + | System.out.print( p.key + " "); | |
+ | inOrderVisit( p.right ); | ||
+ | } | ||
+ | |||
+ | public void preOrderVisit() { | ||
+ | preOrderVisit( root ); | ||
+ | System.out.println(); | ||
+ | } | ||
+ | private void preOrderVisit( IntBSTNode p ) { | ||
+ | if ( p==null ) | ||
+ | return; | ||
+ | System.out.print( p.key + " "); | ||
+ | preOrderVisit( p.left ); | ||
+ | preOrderVisit( p.right ); | ||
+ | } | ||
− | + | public void postOrderVisit() { | |
− | + | postOrderVisit( root ); | |
− | + | System.out.println(); | |
+ | } | ||
+ | private void postOrderVisit( IntBSTNode p ) { | ||
+ | if ( p==null ) | ||
+ | return; | ||
+ | postOrderVisit( p.left ); | ||
+ | postOrderVisit( p.right ); | ||
+ | System.out.print( p.key + " "); | ||
+ | } | ||
− | + | /** | |
− | + | * visits the tree breadth-first. Display the key in all | |
− | + | * the nodes, in breadth-first order. | |
− | + | */ | |
− | + | public void breadthFirst() { | |
− | tree. | + | IntBSTNode p = root; |
+ | Queue<IntBSTNode> queue = new LinkedList<IntBSTNode>(); | ||
+ | |||
+ | if ( p == null ) | ||
+ | return; | ||
+ | |||
+ | queue.add( p ); | ||
+ | while ( ! queue.isEmpty() ){ | ||
+ | p = queue.poll(); | ||
+ | //--- do some work with the key. Here we just print it... | ||
+ | System.out.print( p.key + " " ); | ||
+ | if ( p.left != null ) queue.add( p.left ); | ||
+ | if ( p.right != null ) queue.add( p.right ); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Inserts an element in the tree. We assume that the element | ||
+ | * is not already there. | ||
+ | * @param el | ||
+ | */ | ||
+ | public void insert( int el ) { | ||
+ | // is the tree empty? if so, create 1 node | ||
+ | if ( root==null ) { | ||
+ | root = new IntBSTNode( el ); | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | // go down to the leaf that will be the parent | ||
+ | // of the new node | ||
+ | IntBSTNode p = root, prev = null; | ||
+ | while ( p != null ) { | ||
+ | prev = p; | ||
+ | if ( p.key < el ) | ||
+ | p = p.right; | ||
+ | else | ||
+ | p = p.left; | ||
+ | } | ||
+ | |||
+ | // add element as new leaf of prev's node | ||
+ | if ( el < prev.key ) | ||
+ | prev.left = new IntBSTNode( el ); | ||
+ | else | ||
+ | prev.right = new IntBSTNode( el ); | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Delete element by merging. Finds the element, then the largest | ||
+ | * of its left-subtree, and attaches the right-subtree of the node to | ||
+ | * delete to this largest element. | ||
+ | * @param el: the key we want to remove. | ||
+ | */ | ||
+ | public void delete( int el ) { | ||
+ | IntBSTNode tmp, node, p=root, prev = null; | ||
+ | |||
+ | if ( root == null ) { | ||
+ | System.out.println( "Trying to delete from an empty tree" ); | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | // find the node containing el | ||
+ | while ( p!=null && p.key != el ) { | ||
+ | prev = p; | ||
+ | if (p.key < el ) | ||
+ | p = p.right; | ||
+ | else | ||
+ | p = p.left; | ||
+ | } | ||
+ | |||
+ | if ( p==null ) { | ||
+ | System.out.println( "Key " + el + " not in tree" ); | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | // we found the element. p is pointing to it. prev is pointing to | ||
+ | // parent (or is null if el is in root). | ||
+ | node = p; | ||
+ | |||
+ | // no right sub-tree? | ||
+ | if ( node.right == null ) { | ||
+ | // yes, then pick the left subtree | ||
+ | node = node.left; | ||
+ | } | ||
+ | else if ( node.left == null ) { | ||
+ | // yes, then pick the right subtree | ||
+ | node = node.right; | ||
+ | } | ||
+ | else { | ||
+ | // two existing subtrees. | ||
+ | // go to left subtree | ||
+ | tmp = node.left; | ||
+ | |||
+ | // and find the right-most node that doesn't have a right child. | ||
+ | while ( tmp.right != null ) | ||
+ | tmp = tmp.right; | ||
+ | |||
+ | // tmp points to right-most node (blue node) | ||
+ | |||
+ | // attach right subtree of node we're deleting (yellow node) | ||
+ | // to right most node (blue node) | ||
+ | tmp.right = node.right; | ||
+ | |||
+ | node = node.left; | ||
+ | } | ||
+ | |||
+ | if ( p==root ) | ||
+ | root = node; | ||
+ | else if ( prev.left == p ) | ||
+ | prev.left = node; | ||
+ | else | ||
+ | prev.right = node; | ||
+ | } | ||
+ | |||
+ | public void balance() { } | ||
+ | |||
+ | static public void main( String[] args ) { | ||
+ | IntBST2 tree = new IntBST2(); | ||
+ | |||
+ | // create a new tree by using insert() | ||
+ | int[] keys = new int[] { 8, 3, 10, 1, 6, 14, 4, 7, 13 }; | ||
+ | |||
+ | for ( int i=0; i< keys.length; i++ ) | ||
+ | tree.insert( keys[i] ); | ||
− | + | tree.breadthFirst(); | |
+ | } | ||
} | } | ||
+ | |||
</source> | </source> |
Revision as of 16:32, 29 October 2014
--D. Thiebaut (talk) 19:59, 28 October 2014 (EDT)
/**
* IntBST.java
* @author D. Thiebaut
* All material taken from, or adapted from Drozdek's
* Data Structures and Algorithms in Java.
*
*/
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
/**
* A class implementing a BST node, with an integer key,
* and a left and right pointer.
* @author thiebaut
*
*/
class IntBSTNode {
public int key;
public IntBSTNode left, right;
IntBSTNode( int el, IntBSTNode l, IntBSTNode r ) {
key = el;
left = l;
right = r;
}
IntBSTNode( int el ) {
this( el, null, null );
}
}
/**
* The tree class. Implements most useful methods.
* @author thiebaut
*
*/
public class IntBST {
protected IntBSTNode root;
/**
* constructor creates an empty tree.
*/
IntBST( ) {
root = null;
}
protected void setRoot( IntBSTNode p ) {
root = p;
}
public void clear() {
root = null;
}
/**
* Just use for debugging... Recursively visits the tree
* and display information about what it finds.
*/
protected void debugVisit() {
debugVisit( root );
}
protected void debugVisit( IntBSTNode p ) {
if ( p==null ) return;
String leftString="has no left child", rightString = "has no right child";
if ( p.left != null) leftString = "has " + p.left.key + " as left child";
if ( p.right != null) rightString = "has " + p.right.key + " as right child";
System.out.println( "Node " + p.key + ", " + leftString + ", and " + rightString );
debugVisit( p.left );
debugVisit( p.right );
}
/**
* Iteratively searches for an element in the tree. Returns the node
* containing the element if found, or null otherwise.
* @param el
* @return
*/
public IntBSTNode search( int el ) {
IntBSTNode p = root;
while ( p != null ) {
if ( el == p.key )
return p;
if ( el < p.key )
p = p.left;
else
p = p.right;
}
return null;
}
/**
* recursively searches for an element in the tree. Returns the
* node containing the element, or null if not found.
* @param el
* @return
*/
public IntBSTNode recSearch( int el ) {
return recSearch( root, el );
}
private IntBSTNode recSearch( IntBSTNode p, int el ) {
if ( p==null )
return null;
if ( el == p.key )
return p;
if ( el < p.key )
return recSearch( p.left, el );
else
return recSearch( p.right, el );
}
/**
* Traveral methods
* inOrderVisit
* preOrderVisit
* postOrderVisit
*/
public void inOrderVisit() {
inOrderVisit( root );
System.out.println();
}
private void inOrderVisit( IntBSTNode p ) {
if ( p==null )
return;
inOrderVisit( p.left );
System.out.print( p.key + " ");
inOrderVisit( p.right );
}
public void preOrderVisit() {
preOrderVisit( root );
System.out.println();
}
private void preOrderVisit( IntBSTNode p ) {
if ( p==null )
return;
System.out.print( p.key + " ");
preOrderVisit( p.left );
preOrderVisit( p.right );
}
public void postOrderVisit() {
postOrderVisit( root );
System.out.println();
}
private void postOrderVisit( IntBSTNode p ) {
if ( p==null )
return;
postOrderVisit( p.left );
postOrderVisit( p.right );
System.out.print( p.key + " ");
}
/**
* visits the tree breadth-first. Display the key in all
* the nodes, in breadth-first order.
*/
public void breadthFirst() {
IntBSTNode p = root;
Queue<IntBSTNode> queue = new LinkedList<IntBSTNode>();
if ( p == null )
return;
queue.add( p );
while ( ! queue.isEmpty() ){
p = queue.poll();
//--- do some work with the key. Here we just print it...
System.out.print( p.key + " " );
if ( p.left != null ) queue.add( p.left );
if ( p.right != null ) queue.add( p.right );
}
}
/**
* Inserts an element in the tree. We assume that the element
* is not already there.
* @param el
*/
public void insert( int el ) {
// is the tree empty? if so, create 1 node
if ( root==null ) {
root = new IntBSTNode( el );
return;
}
// go down to the leaf that will be the parent
// of the new node
IntBSTNode p = root, prev = null;
while ( p != null ) {
prev = p;
if ( p.key < el )
p = p.right;
else
p = p.left;
}
// add element as new leaf of prev's node
if ( el < prev.key )
prev.left = new IntBSTNode( el );
else
prev.right = new IntBSTNode( el );
}
/**
* Delete element by merging. Finds the element, then the largest
* of its left-subtree, and attaches the right-subtree of the node to
* delete to this largest element.
* @param el: the key we want to remove.
*/
public void delete( int el ) {
IntBSTNode tmp, node, p=root, prev = null;
if ( root == null ) {
System.out.println( "Trying to delete from an empty tree" );
return;
}
// find the node containing el
while ( p!=null && p.key != el ) {
prev = p;
if (p.key < el )
p = p.right;
else
p = p.left;
}
if ( p==null ) {
System.out.println( "Key " + el + " not in tree" );
return;
}
// we found the element. p is pointing to it. prev is pointing to
// parent (or is null if el is in root).
node = p;
// no right sub-tree?
if ( node.right == null ) {
// yes, then pick the left subtree
node = node.left;
}
else if ( node.left == null ) {
// yes, then pick the right subtree
node = node.right;
}
else {
// two existing subtrees.
// go to left subtree
tmp = node.left;
// and find the right-most node that doesn't have a right child.
while ( tmp.right != null )
tmp = tmp.right;
// tmp points to right-most node (blue node)
// attach right subtree of node we're deleting (yellow node)
// to right most node (blue node)
tmp.right = node.right;
node = node.left;
}
if ( p==root )
root = node;
else if ( prev.left == p )
prev.left = node;
else
prev.right = node;
}
public void balance() { }
static public void main( String[] args ) {
IntBST2 tree = new IntBST2();
// create a new tree by using insert()
int[] keys = new int[] { 8, 3, 10, 1, 6, 14, 4, 7, 13 };
for ( int i=0; i< keys.length; i++ )
tree.insert( keys[i] );
tree.breadthFirst();
}
}