二叉排序树

    二叉排序树又名二叉查找树,其定义如下:

  

 二叉树的定义如下:

//定义二叉查找树的节点
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张图片二叉排序树_第2张图片

下面算法采用如下方法删除节点;

 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;
}

二叉排序树_第3张图片

本文参考 数据结构(C语言版 严蔚敏) 9.21节


你可能感兴趣的:(二叉查找树,二叉排序树)