depth:n的depth为从root到n的路径的长度
height:n的height为从n到一个leaf的最长路径长度。树的height等于root的depth
preorder traversal: 遍历顺序,根,左子树,右子树
postorder traversal: 遍历顺序,左子树,右子树,根
inorder traversal: 遍历顺序, 左子树,根,右子树
- Bineary search tree
average depth = O(logN)
worst case depth is O(N)
implementation:
struct BinaryNode
{
Object element; //The data in the node
BinaryNode *left; //Left child
BinaryNode *right; //Right child
};
contains:
/*Internam method to test if an item is in a subtree
* x is itemto search for.
* t is the node that roots the subtree
*/
bool contains(const Comparable & x, BinaryNode *t) const
{
if (t == NULL) return false;
else if (x < t->element) return contains(x, t->left);
else if (x > t->element) return contains(x, t->right);
else return true; //match
}
findMin and findMax (recursion and iteration implementation):
//recursion, return node containing the smallest item
BinaryNode * findMin(BinaryNode *t) const
{
if(t == NULL) return NULL;
if(t->left == NULL) return t;
return findMin(t->left);
}
//iteration, return node containing the largest item
BinaryNode * findMax(BinaryNode *t) const
{
if(t != NULL)
{
while (t->right != NULL)
{
t = t->right;
}
}
return t;
}
insert:
/* x is the item to nsert
t is the node that roots the subtree
set the new root of the subtree
*/
void insert(const Comparable & x, BinaryNode * &t)
{
if(t == NULL) t = new BinaryNode(x, NULL, NULL);
else if (x < t->element) insert(x, t->left);
else if (x > t->element) insert(x, t->right);
else ; //duplicate, do nothing
}
remove:
需要考虑多种情况。
如果结点是树叶,可以直接删除。
如果结点有一个child,删除后将child与父结点连接,如下
如果结点有两个child,一般的删除策略是用其右字数中的最小数据代替该节点并递归地删除那个节点。例子如下
实现:
//效率不高,因为沿树两次搜索来查找和删除右子树中的最小节点
//如要提高效率,需要写一个特殊的removeMin
void remove(const Comparable & x, BinaryNode * &t)
{
if(t == NULL) return; //item not found, do nothing
if(x < t->element) remove(x,t->left);
else if(x > t->element) remove(x,t->right);
else if(t->left != NULL && t->right != NULL) //Two children
{
t->element = findMin(t->right)->element;
remove(t->element,t->right);
}
else //node has only one child
{
BinaryNode *oldNode = t;
t = (t->left != NULL) ? t->left : t->right;
delete oldNode;
}
}
makeEmpty and destructor:
~BinarySearchTree()
{
makeEmpty();
}
void makeEmpty(BinaryNode * &t)
{
if (t != NULL)
{
makeEmpty(t->left);
makeEmpty(t->right);
delete t;
}
t = NULL; //important
}
operator= and clone:
//deep copy
const BinarySearchTree & operator=(const BinarySearchTree &rhs)
{
if(this != &rhs)
{
makeEmpty();
root = clone(rhs.root);
}
return *this;
}
//method to clone subtree
BinaryNode *clone(BinaryNode *t) const
{
if(t == NULL) return NULL;
return new BinaryNode(t->element,clone(t->left),clone(t->right));
}
Complexity analysis:
average case:
O(logN) for all operation
actually O(d) for all operations except makeEmpty and operator=
d = depth including the node visited
worst case: O(N)Tree traversal:
O(N) complexity
print tree in sorted order:
//inorder
void printTree(BinaryNode *t) const
{
if(t != NULL)
{
printTree(t->left);
cout << t->element << endl;
printTree(t->right);
}
}
compute height:
int height(BinaryNode *t)
{
if(t == NULL) return -1;
else return 1 + max(height(t->left),height(t->right));
}