二叉树系列之二:二叉搜索树
2007-01-01 19:50
274 查看
本文介绍了二叉搜索树的一些必要元素,包括:
search(T key):特定键值的查找;
minimum(): 树中最小键值的查找;
maximum():树中最大键值的查找;
successor(BTNode<T>* x):获得x的下一节点;
predeccessor(BTNode<T>* x):获得x的上一节点;
insert(T data):插入指定的键值;
remove(T data):删除指定的键值;
rotateLeft(BTNode<T>* x):对x节点进行向左旋转;
rotateRight(BTNode<T>* x):对x节点进行向右旋转。
下面是完整的代码:
#ifndef _BS_TREE_H_
#define _BS_TREE_H_
#include "BTree.h"
template <class T>
class BSTree : public BTree<T>
...{
public:
BSTree(T data = T()) : BTree(data), avlnode_(BTNode<T>::nil()), rbnode_(BTNode<T>::nil())...{ }
virtual ~BSTree() ...{ }
public:
BTNode<T>* search(T key) ...{ return search(root_, key); }
BTNode<T>* minimum() ...{ return minimum(root_); }
BTNode<T>* maximum() ...{ return maximum(root_); }
BTNode<T>* successor(BTNode<T>* x)
...{
if (x->rchild_ != BTNode<T>::nil()) return minimum(x->rchild_);
BTNode<T>* y = x->parent_;
while (y != BTNode<T>::nil() && x == y->rchild_)
...{
x = y;
y = x->parent_;
}
return y;
}
BTNode<T>* predeccessor(BTNode<T>* x)
...{
if (x->lchild_ != BTNode<T>::nil()) return maximum(x->lchild_);
BTNode<T>* y = x->parent_;
while (y != BTNode<T>::nil() && x == y->lchild_)
...{
x = y;
y = x->parent_;
}
return y;
}
// The pointer x traces the path, and the pointer y is maintained as the parent of x.
// After initialization, the while loop in lines 3-7 causes these two pointers to move down the
// tree, going left or right depending on the comparison of key[z] with key[x], until x is set to
// NIL. This NIL occupies the position where we wish to place the input item z. Lines 8-13 set
// the pointers that cause z to be inserted.
virtual void insert(T data)
...{
BTNode<T>* y = BTNode<T>::nil(), *x = root_;
// x traces the path, until x is set to BTNode<T>::nil(),
// and y is the parent of x, and at last
// y must be a leaf node with no child
while (x != BTNode<T>::nil())
...{
y = x;
if (data < x->data_) x = x->lchild_;
else x = x->rchild_;
}
BTNode<T>* z = new BTNode<T>(data);
// Insert the z here, let y be the parent of z
z->parent_ = y;
// specify the current node for avltree and rbtree
avlnode_ = z->parent_;
rbnode_ = z;
// let z be the child of y
// y is BTNode<T>::nil(), this is an empty tree
if (y == BTNode<T>::nil()) root_ = z;
// insert z as y's left child
else if (data < y->data_) y->lchild_ = z;
// insert z as y's right child
else y->rchild_ = z;
}
// (a) If z has no children, we just remove it.
// (b) If z has only one child, we splice out z.
// (c) If z has two children, we splice out its successor y,
// which has at most one child, and then replace z's key
// and satellite data with y's key and satellite data
virtual void remove(T data)
...{
BTNode<T> *y = BTNode<T>::nil(), *x = BTNode<T>::nil();
BTNode<T> *z = search(data);
// can't find the node with data
if (z == BTNode<T>::nil()) return;
// at most one child, remove z or splice out z
if (z->lchild_ == BTNode<T>::nil() || z->rchild_ == BTNode<T>::nil()) y = z;
// two children, spice out its successor y
else y = successor(z);
// here we find the child to point when we spice out y
if (y->lchild_ != BTNode<T>::nil()) x = y->lchild_;
else x = y->rchild_;
// spice out y and specify the new parent of child
if (x != BTNode<T>::nil()) x->parent_ = y->parent_;
// specify the current node for rbtree and avltree
if (y->color_ == BLACK) rbnode_ = y->parent_;
else rbnode_ = BTNode<T>::nil();
avlnode_ = y->parent_;
// here we specify the new child of parent
// y is root
if (y->parent_ == BTNode<T>::nil()) root_ = x;
// y is left child
else if (y == y->parent_->lchild_) y->parent_->lchild_ = x;
// y is right child
else y->parent_->rchild_ = x;
// when y is a successor and be spiced out,
// so we replace the z's data with y's data
// and looks like z is deleted
if (y != z) z->data_ = y->data_;
delete y;
}
protected:
// transforms the configuration of the two nodes on the left into the
// configuration on the right by changing a constant number of pointers.
virtual void rotateLeft(BTNode<T>* x)
...{
// the the node is nil_, can't rotate
if (x != BTNode<T>::nil())
...{
BTNode<T> *y = x->rchild_;
// Turn y's left subtree into x's right subtree
x->rchild_ = y->lchild_;
if (y->lchild_ != BTNode<T>::nil()) y->lchild_->parent_ = x;
// Link x's parent to y
y->parent_ = x->parent_;
if (x->parent_ == BTNode<T>::nil()) root_ = y;
else if (x == x->parent_->lchild_) x->parent_->lchild_ = y;
else x->parent_->rchild_ = y;
// Put x on y's left
y->lchild_ = x;
// let y be the parent of x
x->parent_ = y;
}
BTNode<T>::nilify();
}
// transforms the configuration of the two nodes on the right into the
// configuration on the left by changing a constant number of pointers.
virtual void rotateRight(BTNode<T>* x)
...{
// the the node is nil_, can't rotate
if (x != BTNode<T>::nil())
...{
BTNode<T> *y = x->lchild_;
// Turn y's left subtree into x's right subtree
x->lchild_ = y->rchild_;
if (y->rchild_ != BTNode<T>::nil()) y->rchild_->parent_ = x;
// Link x's parent to y
y->parent_ = x->parent_;
if (x->parent_ == BTNode<T>::nil()) root_ = y;
else if (x == x->parent_->lchild_) x->parent_->lchild_ = y;
else x->parent_->rchild_ = y;
// Put x on y's right
y->rchild_ = x;
// let y be the parent of x
x->parent_ = y;
}
BTNode<T>::nilify();
}
private:
BTNode<T>* search(BTNode<T>* x, T key)
...{
while (x != BTNode<T>::nil() && x->data_ != key)
...{
if (key < x->data_) x = search(x->lchild_, key);
else x = search(x->rchild_, key);
}
return (x->data_ == key) ? x : BTNode<T>::nil();
}
BTNode<T>* minimum(BTNode<T>* x)
...{
while (x->lchild_ != BTNode<T>::nil()) x = x->lchild_;
return x;
}
BTNode<T>* maximum(BTNode<T>* x)
...{
while (x->rchild_ != BTNode<T>::nil()) x = x->rchild_;
return x;
}
protected:
BTNode<T>* avlnode_;
BTNode<T>* rbnode_;
};
#endif
search(T key):特定键值的查找;
minimum(): 树中最小键值的查找;
maximum():树中最大键值的查找;
successor(BTNode<T>* x):获得x的下一节点;
predeccessor(BTNode<T>* x):获得x的上一节点;
insert(T data):插入指定的键值;
remove(T data):删除指定的键值;
rotateLeft(BTNode<T>* x):对x节点进行向左旋转;
rotateRight(BTNode<T>* x):对x节点进行向右旋转。
下面是完整的代码:
#ifndef _BS_TREE_H_
#define _BS_TREE_H_
#include "BTree.h"
template <class T>
class BSTree : public BTree<T>
...{
public:
BSTree(T data = T()) : BTree(data), avlnode_(BTNode<T>::nil()), rbnode_(BTNode<T>::nil())...{ }
virtual ~BSTree() ...{ }
public:
BTNode<T>* search(T key) ...{ return search(root_, key); }
BTNode<T>* minimum() ...{ return minimum(root_); }
BTNode<T>* maximum() ...{ return maximum(root_); }
BTNode<T>* successor(BTNode<T>* x)
...{
if (x->rchild_ != BTNode<T>::nil()) return minimum(x->rchild_);
BTNode<T>* y = x->parent_;
while (y != BTNode<T>::nil() && x == y->rchild_)
...{
x = y;
y = x->parent_;
}
return y;
}
BTNode<T>* predeccessor(BTNode<T>* x)
...{
if (x->lchild_ != BTNode<T>::nil()) return maximum(x->lchild_);
BTNode<T>* y = x->parent_;
while (y != BTNode<T>::nil() && x == y->lchild_)
...{
x = y;
y = x->parent_;
}
return y;
}
// The pointer x traces the path, and the pointer y is maintained as the parent of x.
// After initialization, the while loop in lines 3-7 causes these two pointers to move down the
// tree, going left or right depending on the comparison of key[z] with key[x], until x is set to
// NIL. This NIL occupies the position where we wish to place the input item z. Lines 8-13 set
// the pointers that cause z to be inserted.
virtual void insert(T data)
...{
BTNode<T>* y = BTNode<T>::nil(), *x = root_;
// x traces the path, until x is set to BTNode<T>::nil(),
// and y is the parent of x, and at last
// y must be a leaf node with no child
while (x != BTNode<T>::nil())
...{
y = x;
if (data < x->data_) x = x->lchild_;
else x = x->rchild_;
}
BTNode<T>* z = new BTNode<T>(data);
// Insert the z here, let y be the parent of z
z->parent_ = y;
// specify the current node for avltree and rbtree
avlnode_ = z->parent_;
rbnode_ = z;
// let z be the child of y
// y is BTNode<T>::nil(), this is an empty tree
if (y == BTNode<T>::nil()) root_ = z;
// insert z as y's left child
else if (data < y->data_) y->lchild_ = z;
// insert z as y's right child
else y->rchild_ = z;
}
// (a) If z has no children, we just remove it.
// (b) If z has only one child, we splice out z.
// (c) If z has two children, we splice out its successor y,
// which has at most one child, and then replace z's key
// and satellite data with y's key and satellite data
virtual void remove(T data)
...{
BTNode<T> *y = BTNode<T>::nil(), *x = BTNode<T>::nil();
BTNode<T> *z = search(data);
// can't find the node with data
if (z == BTNode<T>::nil()) return;
// at most one child, remove z or splice out z
if (z->lchild_ == BTNode<T>::nil() || z->rchild_ == BTNode<T>::nil()) y = z;
// two children, spice out its successor y
else y = successor(z);
// here we find the child to point when we spice out y
if (y->lchild_ != BTNode<T>::nil()) x = y->lchild_;
else x = y->rchild_;
// spice out y and specify the new parent of child
if (x != BTNode<T>::nil()) x->parent_ = y->parent_;
// specify the current node for rbtree and avltree
if (y->color_ == BLACK) rbnode_ = y->parent_;
else rbnode_ = BTNode<T>::nil();
avlnode_ = y->parent_;
// here we specify the new child of parent
// y is root
if (y->parent_ == BTNode<T>::nil()) root_ = x;
// y is left child
else if (y == y->parent_->lchild_) y->parent_->lchild_ = x;
// y is right child
else y->parent_->rchild_ = x;
// when y is a successor and be spiced out,
// so we replace the z's data with y's data
// and looks like z is deleted
if (y != z) z->data_ = y->data_;
delete y;
}
protected:
// transforms the configuration of the two nodes on the left into the
// configuration on the right by changing a constant number of pointers.
virtual void rotateLeft(BTNode<T>* x)
...{
// the the node is nil_, can't rotate
if (x != BTNode<T>::nil())
...{
BTNode<T> *y = x->rchild_;
// Turn y's left subtree into x's right subtree
x->rchild_ = y->lchild_;
if (y->lchild_ != BTNode<T>::nil()) y->lchild_->parent_ = x;
// Link x's parent to y
y->parent_ = x->parent_;
if (x->parent_ == BTNode<T>::nil()) root_ = y;
else if (x == x->parent_->lchild_) x->parent_->lchild_ = y;
else x->parent_->rchild_ = y;
// Put x on y's left
y->lchild_ = x;
// let y be the parent of x
x->parent_ = y;
}
BTNode<T>::nilify();
}
// transforms the configuration of the two nodes on the right into the
// configuration on the left by changing a constant number of pointers.
virtual void rotateRight(BTNode<T>* x)
...{
// the the node is nil_, can't rotate
if (x != BTNode<T>::nil())
...{
BTNode<T> *y = x->lchild_;
// Turn y's left subtree into x's right subtree
x->lchild_ = y->rchild_;
if (y->rchild_ != BTNode<T>::nil()) y->rchild_->parent_ = x;
// Link x's parent to y
y->parent_ = x->parent_;
if (x->parent_ == BTNode<T>::nil()) root_ = y;
else if (x == x->parent_->lchild_) x->parent_->lchild_ = y;
else x->parent_->rchild_ = y;
// Put x on y's right
y->rchild_ = x;
// let y be the parent of x
x->parent_ = y;
}
BTNode<T>::nilify();
}
private:
BTNode<T>* search(BTNode<T>* x, T key)
...{
while (x != BTNode<T>::nil() && x->data_ != key)
...{
if (key < x->data_) x = search(x->lchild_, key);
else x = search(x->rchild_, key);
}
return (x->data_ == key) ? x : BTNode<T>::nil();
}
BTNode<T>* minimum(BTNode<T>* x)
...{
while (x->lchild_ != BTNode<T>::nil()) x = x->lchild_;
return x;
}
BTNode<T>* maximum(BTNode<T>* x)
...{
while (x->rchild_ != BTNode<T>::nil()) x = x->rchild_;
return x;
}
protected:
BTNode<T>* avlnode_;
BTNode<T>* rbnode_;
};
#endif
相关文章推荐
- 二叉树系列四:Leetcode#98判断二叉树是否为二叉搜索树(BST)
- 二叉树系列 - 二叉搜索树 - [LeetCode] 中序遍历中利用 pre节点避免额外空间。题:Recover Binary Search Tree,Validate Binary Search Tree
- 二叉树系列——判断一个序列是不是一棵二叉搜索树的遍历序列
- 二叉树系列文章之二 二叉树的递归遍历
- 二叉树系列 - 二叉搜索树 - 线性时间内把有序链表转化为BST
- 二叉树系列之二(遍历与查找)
- [算法系列之二]二叉树各种遍历
- [算法系列之二]二叉树各种遍历
- 二叉树系列7:判断整数序列是不是二叉搜索树的后序遍历结果
- 大数据及人工智能基础知识复习系列1 二叉树及二叉搜索树
- [LeetCode] Path Sum II 二叉树路径之和之二
- 判定一棵二叉树是否是二叉搜索树
- ABP(现代ASP.NET样板开发框架)系列之二、ABP入门教程详解
- ASP.NET MVC架构与实战系列之二:理解MVC路由配置
- C#学习笔记系列之二:delegate
- leetcode之二叉树类之二叉树深度系列-----104/111/110/108/109 二叉树最大/最小深度/AVL树的判断和由有序序列生成(牵扯分治相关,OJ105/106)
- STL系列之二 stack栈
- 判定一棵二叉树是否是二叉搜索树
- Openfire代码阅读之二--插件(系列一)
- 每天学习一算法系列(34)(求一个二叉树中任意两个节点间的最大距离,两个节点的距离的定义是这两个节点间边的个数)