二叉排序树又名二叉查找树,其定义如下:
二叉树的定义如下:
//定义二叉查找树的节点
template<typename T>
struct TreeNode
{
T key;
TreeNode * lchild;
TreeNode * rchild;
};
二叉排序树的查找算法如下:
//在二叉树head中查找关键字为key的元素,
//若存在返回true,p指向该节点
//若不存在返回false,p指向该插入到的节点
template <typename T>
bool SearchBST(TreeNode<T> * head,T key,TreeNode<T> * f,TreeNode<T> * &p)
{
//f指向T的双亲
if(head==NULL)//查找不成功,最开始f为NULL
{
p=f;
return false;
}
else if(head->key==key)
{
p=head;
return true;
}
else if(key<head->key)
{
return SearchBST(head->lchild,key,head,p);
}
else
{
return SearchBST(head->rchild,key,head,p);
}
}
//SearchBST的非递归实现
template <typename T>
bool SearchBST(TreeNode<T> * head,T key,TreeNode<T> * &p)
{
TreeNode<T> * parent=NULL;
TreeNode<T> * q=head;
while(q!=NULL && q->key!=key)
{
parent=q;
if(key<q->key)
q=q->lchild;
else
q=q->rchild;
}
if(q==NULL)//查找不成功
{
p=parent;
return false;
}
else//q!=NULL 查找成功
{
p=q;
return true;
}
}
二叉排序树插入操作算法
//当二叉排序树head中不存在关键字为key的数据元素时,插入key返回true
template<typename T>
bool InsertBST( TreeNode<T> * & head,T key)
{
TreeNode<T> * p;
if(SearchBST(head,key,p)==false)
{
//开始创建一个节点
TreeNode<T> * node=new TreeNode<T>;
node->key=key;
node->lchild=NULL;
node->rchild=NULL;
if(p==NULL)//如果开始树为空
head=node;
else
{
if(key<(p->key))
p->lchild=node;
else
p->rchild=node;
}
return true;
}
return false;
}
二叉排序树删除操作(二叉树的难点)
下面算法采用如下方法删除节点;
1,若果p(要删除节点)的左子树为空,则令p的右子树成为p的双亲f的左子树或者右子树(根据p的key值与f的key值判断)。即用p的右子树代替p.
2,若果p(要删除节点)的右子树为空,则令p的左子树成为p的双亲f的左子树或者右子树(根据p的key值与f的key值判断)。即用p的左子树代替p.
3,如果p的左右子树都不为空,则找到二叉树中序遍历时p的直接前驱pre,用pre代替p。
执行如下操作: (a):p->key=pre->key; (b) s->rchild=pre->lchild (s为pre的双亲) (c)删除s
//删除关键字为key的元素(递归实现)
template<typename T>
bool DeleteBST(TreeNode<T> * &head,T key)
{
if(!head)
return false;
else
{
if(key==head->key)
return DeleteBST(head);
else if(key<head->key)
return DeleteBST(head->lchild,key);
else
return DeleteBST(head->rchild,key);
}
}
template <typename T>
bool DeleteBST(TreeNode<T> * &p)//执行实际的删除操作
{
if(!(p->lchild))//p的左子树为空
{
TreeNode<T> * q=p;
p=p->rchild;
delete q;
}
else if(!p->rchild)//p的右子树为空
{
TreeNode<T> * q=p;
p=p->lchild;
delete q;
}
else//p的左右子树都不为空
{
TreeNode<T> * q=p;//
//求p的直接前驱s
TreeNode <T> * s=p->lchild;
while(s->rchild)
{
q=s;//q记录s的父节点
s=s->rchild;
}
//用s代替p
p->key=s->key;
if(p!=q)
q->rchild=s->lchild;
else//p==q
q->lchild=s->lchild;
delete s;
}
return true;
}
//删除关键字为key的元素(非递归实现)
template<typename T>
bool _DeleteBST(TreeNode<T> * &head,T key)
{
TreeNode<T> * parent=NULL;//待删除节点的父节点
TreeNode<T> * p=head;//待删除的节点
while(p && p->key!=key)
{
parent=p;
if(key<p->key)
p=p->lchild;
else
p=p->rchild;
}
if(!p)
return false;//关键字为key的元素不存在
//else存在
if(!p->lchild)//p的左孩子不存在
{
if(!parent)//根节点即为p
head=p->rchild;
else
{
if(p->key<parent->key)
parent->lchild=p->rchild;
else
parent->rchild=p->rchild;
}
}
else if(!p->rchild)//p的右孩子不存在
{
if(!parent)
head=p->lchild;
else
{
if(p->key<parent->key)
parent->lchild=p->lchild;
else
parent->rchild=p->lchild;
}
}
else //p的左右孩子都存在
{
//计算p的中序遍历的前驱pre
TreeNode<T> * pre=p->lchild;//待删除节点中序遍历的直接前驱节点
TreeNode<T> * q=p;//直接前驱节点的父节点
while(pre->rchild)
{
q=pre;
pre=pre->rchild;
}
p->key=pre->key;
if(q!=p)
q->rchild=pre->lchild;
else
q->lchild=pre->lchild;
p=pre;
}
delete p;
return true;
}
总体代码如下:
// 二叉查找树
#include "stdafx.h"
#include <iostream>
using namespace std;
//定义二叉查找树的节点
template<typename T>
struct TreeNode
{
T key;
TreeNode * lchild;
TreeNode * rchild;
};
//在二叉树head中查找关键字为key的元素,
//若存在返回true,p指向该节点
//若不存在返回false,p指向该插入到的节点
template <typename T>
bool SearchBST(TreeNode<T> * head,T key,TreeNode<T> * f,TreeNode<T> * &p)
{
//f指向T的双亲
if(head==NULL)//查找不成功,最开始f为NULL
{
p=f;
return false;
}
else if(head->key==key)
{
p=head;
return true;
}
else if(key<head->key)
{
return SearchBST(head->lchild,key,head,p);
}
else
{
return SearchBST(head->rchild,key,head,p);
}
}
//SearchBST的非递归实现
template <typename T>
bool SearchBST(TreeNode<T> * head,T key,TreeNode<T> * &p)
{
TreeNode<T> * parent=NULL;
TreeNode<T> * q=head;
while(q!=NULL && q->key!=key)
{
parent=q;
if(key<q->key)
q=q->lchild;
else
q=q->rchild;
}
if(q==NULL)//查找不成功
{
p=parent;
return false;
}
else//q!=NULL 查找成功
{
p=q;
return true;
}
}
//当二叉排序树head中不存在关键字为key的数据元素时,插入key返回true
template<typename T>
bool InsertBST( TreeNode<T> * & head,T key)
{
TreeNode<T> * p;
if(SearchBST(head,key,p)==false)
{
//开始创建一个节点
TreeNode<T> * node=new TreeNode<T>;
node->key=key;
node->lchild=NULL;
node->rchild=NULL;
if(p==NULL)//如果开始树为空
head=node;
else
{
if(key<(p->key))
p->lchild=node;
else
p->rchild=node;
}
return true;
}
return false;
}
//删除关键字为key的元素(递归实现)
template<typename T>
bool DeleteBST(TreeNode<T> * &head,T key)
{
if(!head)
return false;
else
{
if(key==head->key)
return DeleteBST(head);
else if(key<head->key)
return DeleteBST(head->lchild,key);
else
return DeleteBST(head->rchild,key);
}
}
template <typename T>
bool DeleteBST(TreeNode<T> * &p)//执行实际的删除操作
{
if(!(p->lchild))//p的左子树为空
{
TreeNode<T> * q=p;
p=p->rchild;
delete q;
}
else if(!p->rchild)//p的右子树为空
{
TreeNode<T> * q=p;
p=p->lchild;
delete q;
}
else//p的左右子树都不为空
{
TreeNode<T> * q=p;//
//求p的直接前驱s
TreeNode <T> * s=p->lchild;
while(s->rchild)
{
q=s;//q记录s的父节点
s=s->rchild;
}
//用s代替p
p->key=s->key;
if(p!=q)
q->rchild=s->lchild;
else//p==q
q->lchild=s->lchild;
delete s;
}
return true;
}
//删除关键字为key的元素(非递归实现)
template<typename T>
bool _DeleteBST(TreeNode<T> * &head,T key)
{
TreeNode<T> * parent=NULL;//待删除节点的父节点
TreeNode<T> * p=head;//待删除的节点
while(p && p->key!=key)
{
parent=p;
if(key<p->key)
p=p->lchild;
else
p=p->rchild;
}
if(!p)
return false;//关键字为key的元素不存在
//else存在
if(!p->lchild)//p的左孩子不存在
{
if(!parent)//根节点即为p
head=p->rchild;
else
{
if(p->key<parent->key)
parent->lchild=p->rchild;
else
parent->rchild=p->rchild;
}
}
else if(!p->rchild)//p的右孩子不存在
{
if(!parent)
head=p->lchild;
else
{
if(p->key<parent->key)
parent->lchild=p->lchild;
else
parent->rchild=p->lchild;
}
}
else //p的左右孩子都存在
{
//计算p的中序遍历的前驱pre
TreeNode<T> * pre=p->lchild;//待删除节点中序遍历的直接前驱节点
TreeNode<T> * q=p;//直接前驱节点的父节点
while(pre->rchild)
{
q=pre;
pre=pre->rchild;
}
p->key=pre->key;
if(q!=p)
q->rchild=pre->lchild;
else
q->lchild=pre->lchild;
p=pre;
}
delete p;
return true;
}
//中序遍历二叉查找树
template <typename T>
void printBST(TreeNode<T> * head)
{
if(head==NULL)
return ;
printBST(head->lchild);
cout<<head->key<<" ";
printBST(head->rchild);
}
int _tmain(int argc, _TCHAR* argv[])
{
TreeNode<int> * head=NULL;
TreeNode<int> * p=NULL;
InsertBST(head,45);
InsertBST(head,24);
InsertBST(head,53);
InsertBST(head,45);
InsertBST(head,12);
InsertBST(head,24);
InsertBST(head,90);
printBST(head);//构造的二叉树如下图所示
cout<<endl;
//SearchBST(head,10,(TreeNode<int> *)NULL,p);
cout<<SearchBST(head,12,p)<<endl;
_DeleteBST(head,24);
printBST(head);
system("PAUSE");
return 0;
}
本文参考 数据结构(C语言版 严蔚敏) 9.21节