这章主要讲了二叉查找树及其相关性质。二叉搜索树的结点结构,插入,搜索,删除,结点后继,结点前驱,遍历代码如下。
结点结构:
struct node{
Type element;//存储的关键字
node* parent;//母结点
node* left;//左孩子结点
node* right;//右孩子结点
node(const Type& e=Type(),node* p=0,node* l=0,node* r=0):element(e),parent(p),left(l),right(r){}
};
插入:
- 非递归插入:
template<class Type>
bool binarySearchTree<Type>::noRecursiveInsertion(const Type& val,node*& rootNode)//根节点引用是必须的,因为可能对根节点直接赋值
{
node* preNode=0;
node* currNode=rootNode;
while(currNode!=0){
preNode=currNode;
if(val<currNode->element)
currNode=currNode->left;
else if(currNode->element<val)
currNode=currNode->right;
else
return false;//假设树中只能插入不同的元素
}
actualSize++;//树中存储的元素实际个数
if(preNode==0)//插入前根结点为0
rootNode=new node(val);
else if (val<preNode->element)
preNode->left=new node(val,preNode);
else
preNode->right=new node(val,preNode);
return true;
}
- 递归插入:
template<class Type>
bool binarySearchTree<Type>::recursiveInsertion(const Type& val,node*& rootNode)
{
if(rootNode!=0){
if(val<rootNode->element){
if(rootNode->left==0){
rootNode->left=new node(val,rootNode);
return true;
}
else
return recursiveInsertion(val,rootNode->left);
}
else if(rootNode->element<val){
if(rootNode->right==0){
rootNode->right=new node(val,rootNode);
return true;
}
else
return recursiveInsertion(val,rootNode->right);
}
else
return false;
}
else{
rootNode=new node(val);
return true;
}
}
搜索:
template<class Type>
typename binarySearchTree<Type>::node* binarySearchTree<Type>::search(const Type& val,node* rootNode) const
{
while(rootNode!=0&&rootNode->element!=val)
if(val<rootNode->element)
rootNode=rootNode->left;
else
rootNode=rootNode->right;
return rootNode;
}
删除:
删除操作有点麻烦,详细可见算法导论第三版中文版P166。现给出代码:
// node v is used to replace node u;
template<class Type>
void binarySearchTree<Type>::transplant(node* u,node* v)
{
if(u->parent==0)
root=v;
else if(u==u->parent->right)
u->parent->right=v;
else
u->parent->left=v;
if(v!=0)
v->parent=u->parent;
}
template<class Type>
bool binarySearchTree<Type>::remove(const Type& val)
{
node* objectNode=search(val,root);
if(objectNode==0)
return false;
else{
if(objectNode->left==0)
transplant(objectNode,objectNode->right);
else if(objectNode->right==0)
transplant(objectNode,objectNode->left);
else{
node* minNode=minimum(objectNode->right);
if(minNode->parent!=objectNode){
transplant(minNode,minNode->right);
minNode->right=objectNode->right;
minNode->right->parent=minNode;
}
transplant(objectNode,minNode);
minNode->left=objectNode->left;
minNode->left->parent=minNode;
}
}
actualSize--;
delete objectNode;
return true;
}
结点后继:
一个结点x的后继结点被定义为大于x.key的最小关键字的结点。
template<class Type>
typename binarySearchTree<Type>::node* binarySearchTree<Type>::successor(node* currNode) const
{
//右子树不为空,找到右子树的最小节点
if(currNode->right!=0)
return minimum(currNode->right);
//右子树为空的情况:
node* parentNode=currNode->parent;
while(parentNode!=0&&currNode==parentNode->right){
currNode=parentNode;
parentNode=parentNode->parent;
}
return parentNode;
}
结点前驱:
结点前驱与结点后继是对称的。
template<class Type>
typename binarySearchTree<Type>::node* binarySearchTree<Type>::predecessor(node* currNode) const
{
if(currNode->left!=0)
return maximum(currNode->left);
else{
node* parentNode=currNode->parent;
while(parentNode!=0&&currNode==parentNode->left){
currNode=parentNode;
parentNode=parentNode->parent;
}
return parentNode;
}
}
遍历:
- 递归的前序,中序,后续遍历:
template<class Type>
void binarySearchTree<Type>::preorderTreeWalk(node* rootNode) const
{
if(rootNode!=0){
cout<<rootNode->element<<" ";
preorderTreeWalk(rootNode->left);
preorderTreeWalk(rootNode->right);
}
}
template<class Type>
void binarySearchTree<Type>::inorderTreeWalk(node* rootNode) const
{
if(rootNode!=0){
inorderTreeWalk(rootNode->left);
cout<<rootNode->element<<" ";
inorderTreeWalk(rootNode->right);
}
}
template<class Type>
void binarySearchTree<Type>::postorderTreeWalk(node* rootNode) const
{
if(rootNode!=0){
postorderTreeWalk(rootNode->left);
postorderTreeWalk(rootNode->right);
cout<<rootNode->element<<" ";
}
}
- 用栈实现的非递归遍历。可参考该博客教科书上的非递归遍历那一段落。
template<class Type>
void binarySearchTree<Type>::preorderTreeWalkWithStack(node* rootNode) const
{
stack<node*> s;
node* currentNode=rootNode;
while(currentNode!=0||!s.empty()){
while(currentNode!=0){
cout<<currentNode->element<<" ";
s.push(currentNode);
currentNode=currentNode->left;
}
if(!s.empty()){
currentNode=s.top();
s.pop();
currentNode=currentNode->right;
}
}
}
template<class Type>
void binarySearchTree<Type>::inorderTreeWalkWithStack(node* rootNode) const
{
stack<node*> s;
node* currentNode=rootNode;
while(currentNode!=0||!s.empty()){
while(currentNode!=0){
s.push(currentNode);
currentNode=currentNode->left;
}
if(!s.empty()){
currentNode=s.top();
s.pop();
cout<<currentNode->element<<" ";
currentNode=currentNode->right;
}
}
}
template<class Type>
void binarySearchTree<Type>::postorderTreeWalkWithStack(node* rootNode) const
{
struct postNode{
node* treeNode;
bool isFirst;
postNode(node* n=0,bool isF=true):treeNode(n),isFirst(isF){}
};
stack<postNode*> s;
node* currentNode=rootNode;
postNode* tmp;
while(currentNode!=0||!s.empty()){
while(currentNode!=0){
tmp=new postNode(currentNode);
s.push(tmp);
currentNode=currentNode->left;
}
if(!s.empty()){
tmp=s.top();
s.pop();
if(tmp->isFirst==true){
tmp->isFirst=false;
s.push(tmp);
currentNode=tmp->treeNode->rightNode;
}
else{
cout<<tmp->treeNode->element<<" ";
delete tmp;
currentNode=0;
}
}
}
}
- morris遍历。可参考该博客
template<class Type>
void binarySearchTree<Type>::preorderTreeWalkWithMorris(node* rootNode)
{
node* currentNode=rootNode;
node* tmp;
while(currentNode!=0){
if(currentNode->left==0){
cout<<currentNode->element<<" ";
currentNode=currentNode->right;
}
else{
tmp=currentNode->left;
while(tmp->right!=0&&tmp->right!=currentNode)
tmp=tmp->right;
if(tmp->right==0){
cout<<currentNode->element<<" ";
tmp->right=currentNode;
currentNode=currentNode->left;
}
else{
tmp->right=0;
currentNode=currentNode->right;
}
}
}
}
template<class Type>
void binarySearchTree<Type>::inorderTreeWalkWithMorris(node* rootNode)
{
node* currentNode=rootNode;
node* tmp;
while(currentNode!=0){
if(currentNode->left==0){
cout<<currentNode->element<<" ";
currentNode=currentNode->right;
}
else{
tmp=currentNode->left;
while(tmp->right!=0&&tmp->right!=currentNode)
tmp=tmp->right;
if(tmp->right==0){
tmp->right=currentNode;
currentNode=currentNode->left;
}
else{
cout<<currentNode->element<<" ";
tmp->right=0;
currentNode=currentNode->right;
}
}
}
}
template<class Type>
void binarySearchTree<Type>::postorderTreeWalkWithMorris(node* rootNode)
{
node* dump=new node();
dump->left=rootNode;
node* currentNode=dump;
node* tmp;
while(currentNode!=0){
if(currentNode->left==0)
currentNode=currentNode->right;
else{
tmp=currentNode->left;
while(tmp->right!=0&&tmp->right!=currentNode)
tmp=tmp->right;
if(tmp->right==0){
tmp->right=currentNode;
currentNode=currentNode->left;
}
else{
printReverse(currentNode->left,tmp);
tmp->right=0;
currentNode=currentNode->right;
}
}
}
delete dump;
}
template<class Type>
void binarySearchTree<Type>::reverse(node* startNode,node* finalNode)
{
if(startNode==finalNode)
return;
node* x=startNode;
node* y=startNode->right;
node* z=0;
while(x!=finalNode){
z=y->right;
y->right=x;
x=y;
y=z;
}
}
template<class Type>
void binarySearchTree<Type>::printReverse(node* startNode,node* finalNode)
{
reverse(startNode,finalNode);
node* currentNode=finalNode;
while(true){
cout<<currentNode->element<<" ";
if(currentNode==startNode)
break;
currentNode=currentNode->right;
}
reverse(finalNode,startNode);
}