/**
* Copyright (c) Michael Baczynski 2007
* http://lab.polygonal.de/ds/
*
* This software is distributed under licence. Use of this software
* implies agreement with all terms and conditions of the accompanying
* software licence.
*/
package de.polygonal.ds
{
import de.polygonal.ds.Collection;
import de.polygonal.ds.NullIterator;
import de.polygonal.ds.BinaryTreeNode;
/**
* A Binary Search Tree (BST).
*
*
A BST stores data in a recursive manner so that you can
* access it quickly by using a key. Therefore, a BST automatically
* sorts data as it is inserted.
* For a BST to be valid, every node has to follow two rules:
* 1. The data value in the left subtree must be less than the data value in the current node.
* 2. The data value in the right subtree must be greater than the data value in the current node.
*/
public class lib_as_de_polygonal_ds_BinarySearchTree implements Collection
{
/**
* The root node being referenced.
*/
public var root:BinaryTreeNode;
private var _compare:Function;
/**
* Initializes a BST tree with a given comparison function.
* The function should return -1 if the left is 'less than'
* the right, 0 if they are equal, and 1 if the left is 'greater than'
* the right. If the function is omitted, the BST uses a
* default function for comparing integers.
*
* @param compare The comparison function.
*/
public function lib_as_de_polygonal_ds_BinarySearchTree(compare:Function = null)
{
root = null;
if (compare == null)
{
_compare = function(a:int, b:int):int
{
return a - b;
}
}
else
_compare = compare;
}
/**
* Inserts data into the tree.
*
* @param obj The data.
*/
public function insert(obj:*):void
{
var cur:BinaryTreeNode = root;
if (!root) root = new BinaryTreeNode(obj);
else
{
while (cur)
{
if (_compare(obj, cur.data) < 0)
{
if (cur.left)
cur = cur.left
else
{
cur.setLeft(obj);
return;
}
}
else
{
if (cur.right)
cur = cur.right;
else
{
cur.setRight(obj);
return;
}
}
}
}
}
/**
* Finds a piece of data in the tree and returns a reference
* to the node that contains a match, or null if no match is found.
*
* @param obj The data to find.
* @return A node containing the data or null if the data isn't found.
*/
public function find(obj:*):BinaryTreeNode
{
var cur:BinaryTreeNode = root, i:int;
while (cur)
{
i = _compare(obj, cur.data);
if (i == 0) return cur;
cur = i < 0 ? cur.left : cur.right;
}
return null;
}
/**
* Removes a node from the BST.
*
* @param node The node to remove.
*/
public function remove(node:BinaryTreeNode):void
{
if (node.left && node.right)
{
var t:BinaryTreeNode = node;
while (t.right) t = t.right;
if (node.left == t)
{
t.right = node.right;
t.right.parent = t;
}
else
{
t.parent.right = t.left;
if (t.left) t.left.parent = t.parent;
t.left = node.left;
t.left.parent = t;
t.right = node.right;
t.right.parent = t;
}
if (node == root)
root = t;
else
{
if (node.isLeft())
node.parent.left = t;
else
node.parent.right = t;
}
t.parent = node.parent;
node.left = null;
node.right = null;
node = null;
}
else
{
var child:BinaryTreeNode = null;
if (node.left)
child = node.left;
else
if (node.right)
child = node.right;
if (node == root)
root = child;
else
{
if (node.isLeft())
node.parent.left = child;
else
node.parent.right = child;
}
if (child) child.parent = node.parent;
node.left = node.right = null;
node = null;
}
}
/**
* Checks if a given item exists.
*
* @return True if the item is found, otherwise false.
*/
public function contains(obj:*):Boolean
{
if (find(obj)) return true;
return false;
}
/**
* Clears the tree recursively, starting from this node.
*/
public function clear():void
{
if (root)
{
root.destroy();
root = null;
}
}
/**
* Regular iterator is not supported,
* use BinaryTreeNode.preorder(), inorder() and postorder() instead.
*/
public function getIterator():Iterator
{
return new NullIterator();
}
/**
* The total number of tree nodes.
*/
public function get size():int
{
if (!root) return 0;
return root.count();
}
/**
* Checks if the BST is empty.
*/
public function isEmpty():Boolean
{
if (root)
return root.count() == 0;
else
return true;
}
/**
* Converts the structure into an array.
*
* @return An array.
*/
public function toArray():Array
{
var a:Array = [];
var copy:Function = function(node:BinaryTreeNode):void
{
a.push(node.data);
}
BinaryTreeNode.inorder(root, copy);
return a;
}
/**
* Returns a string representing the current object.
*/
public function toString():String
{
return "[BST, size=" + size + "]";
}
/**
* Prints out all elements in the queue (for debug/demo purposes).
*/
public function dump():String
{
var s:String = "";
var dumpNode:Function = function (node:BinaryTreeNode):void
{
s += node + "\n";
}
BinaryTreeNode.inorder(root, dumpNode);
return s;
}
}
}