二叉排序树

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

  

 二叉树的定义如下:

//定义二叉查找树的节点
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节


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是二叉排序树的常见操作和算法的设计与实现: 1. 二叉排序树的创建: - 创建一个空的二叉排序树。 - 依次将关键字插入到二叉排序树中,插入时需要保持二叉排序树的性质:左子树的关键字小于根节点的关键字,右子树的关键字大于根节点的关键字。 2. 二叉排序树中增加和删除关键字: - 增加关键字:将关键字插入到二叉排序树中,插入时需要保持二叉排序树的性质。 - 删除关键字:首先在二叉排序树中查找要删除的关键字,如果找到了,则有以下几种情况: - 如果要删除的节点是叶子节点,直接删除即可。 - 如果要删除的节点只有一个子节点,将子节点替换到要删除的节点的位置。 - 如果要删除的节点有两个子节点,可以选择用其前驱或后继节点替换,然后再删除前驱或后继节点。 3. 判别是否是二叉排序树: - 对于一个二叉树,如果它满足以下条件,则可以判别为二叉排序树: - 左子树的所有节点的关键字小于根节点的关键字。 - 右子树的所有节点的关键字大于根节点的关键字。 - 左子树和右子树也都是二叉排序树。 4. 二叉排序树的最大值和第k大的值: - 最大值:二叉排序树的最大值即为最右边的叶子节点或者最右边的子树的根节点。 - 第k大的值:可以通过中序遍历二叉排序树得到一个递增的有序序列,然后取第k个元素即为第k大的值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值