二叉查找数

 二叉查找树重要性质:

                                            (1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;

                                            (2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;

                                            (3)左、右子树也分别为二叉排序树;

    现有,如下一棵二叉查找树。

                            

                                                                      (图1)

    现在,若要删除图1中,任意节点,需要考虑如下三种情况:

    (1)需要删除的节点下并没有其他子节点。

    (2)需要删除的节点下有一个子节点(左或右)。

    (3)需要删除的节点下有两个子节点(既左右节点都存在)。

    第一种情况直接删除即可,下面,直接讨论第二种情况。

    若我们要删除的是3号节点,由图1可以看到,它下面还有一个4号子节点。由下图2,可以看出,对于这种办法,我们只需要想办法,让5号节点的左子树的指针指向4就可以了。

                                       

                                                                       (图2)

    第三种情况,既我们要删除的节点下,有2个子节点。如图3,我们先在需要删除的节点的右子树中,找到一个最小的值(因为右子树中的节点的值一定大于根节点)。然后,用找到的最小的值与需要删除的节点的值替换。然后,再将最小值的原节点进行删除(图4)。

                                         

                                                                          (图3)

                                           

                                                                             (图4)

 

 

代码:

template<class T>
void BinarySearchTree<T>::remove(const T& value)
{
	remove(value,m_pRoot);
}
template<class T>
void BinarySearchTree<T>::remove(const T& value, BinaryNode<T>* &t)
{
	if(t == NULL)
		return;
	if ( value < t->m_element) //表示需要删除的节点在左子树
		remove(value,t->m_pLeft);
	else if(value > t->m_element)//表示需要删除的节点在右子树
		remove(value,t->m_pRight);
	else if(value == t->m_element)
	{
		if(t->m_pLeft != NULL && t->m_pRight != NULL)//找到需要删除的节点且节点下面有两个子节点
		{
			//先找到需要删除的节点下,右子树的最小的节点
			//并将它的值赋值给需要删除的节点
			t->m_element = findMin(t->m_pRight)->m_element;
			//删除前面找到的最小的节点。
			remove(t->m_element,t->m_pRight);
		}
		else//需要删除的节点下有一个子节点(左节点或者右节点)
		{
			BinaryNode<T>* oldNode = t;
			t = (t->m_pLeft != NULL) ? t->m_pLeft : t->m_pRight;
			delete oldNode;
		}
	}
}


完整测试代码:

// BinarySearchTree.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
using namespace std;


/*
binary search tree,中文翻译为二叉搜索树、二叉查找树或者二叉排序树。简称为BST

一:二叉搜索树的定义

他的定义与树的定义是类似的,也是一个递归的定义:

1、要么是一棵空树

2、如果不为空,那么其左子树节点的值都小于根节点的值;右子树节点的值都大于根节点的值

3、其左右子树也是二叉搜索树

*/

enum ORDER_MODE 
{     ORDER_MODE_PREV = 0, 
      ORDER_MODE_MID, 
      ORDER_MODE_POST 
};

template<class T>
class BinaryNode
{
public:
	T            m_element; //节点的值
	BinaryNode*  m_pLeft;   //左孩子节点指针
	BinaryNode*  m_pRight;  //右孩子节点指针
	BinaryNode(const T& value,BinaryNode* lt,BinaryNode* rt):m_element(value),m_pLeft(lt),m_pRight(rt)
	{}
};

template<class T>
class BinarySearchTree
{
private:
	BinaryNode<T>*   m_pRoot;

public:
	BinarySearchTree();
	BinarySearchTree(const BinarySearchTree& rhs);
	~BinarySearchTree();

	const T& findMin() const;
	const T& findMax() const;
	
	bool contains(const T& value) const;
	void printTree(ORDER_MODE eOrderMode = ORDER_MODE_PREV)const;
	void makeEmpty();

	void insert(const T& value);
	void remove(const T& value);

private:
	void insert(const T& value, BinaryNode<T>* &t);
	void remove(const T& value, BinaryNode<T>* &t);
	BinaryNode<T>* findMin(BinaryNode<T>* t)const;
	BinaryNode<T>* findMax(BinaryNode<T>* t)const;
	bool contains(const T& value, const BinaryNode<T>* t)const;
	void makeEmpty(BinaryNode<T>* &pValue);
	void printTreeInPrev(BinaryNode<T>* value)const;
	void printTreeInMid(BinaryNode<T>* value)const;
	void printTreeInPost(BinaryNode<T>* value)const;
};


template<class T>
BinarySearchTree<T>::BinarySearchTree()
{
	m_pRoot = NULL;
}
template<class T>
BinarySearchTree<T>::BinarySearchTree(const BinarySearchTree& rhs)
{
	m_pRoot = rhs.m_pRoot;
}
template<class T>
BinarySearchTree<T>::~BinarySearchTree()
{
	makeEmpty();
}

/*
判断此二叉搜索树是不是包含元素value
*/
template<class T>
bool BinarySearchTree<T>::contains(const T& value)const
{
	return contains(value,m_pRoot);
}
template<class T>
bool BinarySearchTree<T>::contains(const T& value, const BinaryNode<T>* t)const
{
	if(t == NULL)
		return false;
	else if(value < t->m_element)
		return contains(value, t->m_pLeft);
	else if(value > t->m_element)
		return contains(value, t->m_pRight);
	else
	    return true;
}

/*
清空删除掉整个树
*/
template<class T>
void  BinarySearchTree<T>::makeEmpty()
{
	makeEmpty(m_pRoot);
}
template<class T>
void BinarySearchTree<T>::makeEmpty(BinaryNode<T>* &pValue)
{
	if (pValue == NULL)
		return;
	makeEmpty(pValue->m_pLeft);
	makeEmpty(pValue->m_pRight);
	delete pValue;
	pValue = NULL;
}

/*
查找二叉搜索树当中的最大值和最小值
*/
//找最小的
template<class T>
 const T& BinarySearchTree<T>::findMin() const
 {
	 return  findMin(m_pRoot)->m_element;
 }
 template<class T>
 BinaryNode<T>* BinarySearchTree<T>::findMin(BinaryNode<T>* t)const
 {
	 if (t == NULL)
		 return NULL;
	 if(t->m_pLeft == NULL)
		 return t;
	 else
		 return findMin(t->m_pLeft);

 }
//找最大的
 template<class T>
 const T& BinarySearchTree<T>::findMax() const
 {
	 return findMax(m_pRoot)->m_element;
 }
 template<class T>
BinaryNode<T>* BinarySearchTree<T>::findMax(BinaryNode<T>* t)const
 {
	 if ( t == NULL)
		 return NULL;
	 if	(t->m_pRight == NULL)
		 return t;
	 else
		 findMax(t->m_pRight);
 
 }

 /*
 插入一个值
 */
 template<class T>
 void BinarySearchTree<T>::insert(const T& value)
 {
	 insert(value,m_pRoot);

 }
 template<class T>
 void BinarySearchTree<T>::insert(const T& value, BinaryNode<T>* &t)
 {
	 if(t == NULL)
		 t = new BinaryNode<T>(value,NULL,NULL);
	 else if (value < t->m_element)
	 {
		 insert(value,t->m_pLeft);
	 }
	 else if(value > t->m_element)
	 {
		 insert(value,t->m_pRight);
	 }
	 else
	 {
		 cout<<"无法插入已经存在的值"<<endl;
	 }
 }
 
 /*
 删除一个值(最复杂的地方)
 */

template<class T>
void BinarySearchTree<T>::remove(const T& value)
{
	remove(value,m_pRoot);
}
template<class T>
void BinarySearchTree<T>::remove(const T& value, BinaryNode<T>* &t)
{
	if(t == NULL)
		return;
	if ( value < t->m_element) //表示需要删除的节点在左子树
		remove(value,t->m_pLeft);
	else if(value > t->m_element)//表示需要删除的节点在右子树
		remove(value,t->m_pRight);
	else if(value == t->m_element)
	{
		if(t->m_pLeft != NULL && t->m_pRight != NULL)//找到需要删除的节点且节点下面有两个子节点
		{
			//先找到需要删除的节点下,右子树的最小的节点
			//并将它的值赋值给需要删除的节点
			t->m_element = findMin(t->m_pRight)->m_element;
			//删除前面找到的最小的节点。
			remove(t->m_element,t->m_pRight);
		}
		else//需要删除的节点下有一个子节点(左节点或者右节点)
		{
			BinaryNode<T>* oldNode = t;
			t = (t->m_pLeft != NULL) ? t->m_pLeft : t->m_pRight;
			delete oldNode;
		}
	}
}

/*
打印二叉搜索树
*/

template <class T>
void BinarySearchTree<T>::printTree(ORDER_MODE eOrderMode /*= ORDER_MODE_PREV*/) const
{
	if (ORDER_MODE_PREV == eOrderMode)
		 printTreeInPrev(m_pRoot);
	else if (ORDER_MODE_MID == eOrderMode)
		 printTreeInMid(m_pRoot);
	else if (ORDER_MODE_POST == eOrderMode)
		 printTreeInPost(m_pRoot);
	else 
		;//do nothing
}

template <class T>
void BinarySearchTree<T>::printTreeInPrev(BinaryNode<T>* t) const
{
	if (t)
	{
		cout << t->m_element<<" ";
		printTreeInPrev(t->m_pLeft);
		printTreeInPrev(t->m_pRight);
	}
}
template <class T>
void BinarySearchTree<T>::printTreeInMid(BinaryNode<T>* t) const
{
	if (t)
	{
		printTreeInPrev(t->m_pLeft);
		cout << t->m_element<<" ";
		printTreeInPrev(t->m_pRight);
	}
}
template <class T>
void BinarySearchTree<T>::printTreeInPost(BinaryNode<T>* t) const
{
	if (t)
	{
		printTreeInPost(t->m_pLeft);
		printTreeInPost(t->m_pRight);
		cout << t->m_element<<" ";
	}
}

 int _tmain(int argc, _TCHAR* argv[])
{
    BinarySearchTree<int> binaryTree;
    binaryTree.insert(7);
    binaryTree.insert(2);
    binaryTree.insert(3);
	binaryTree.insert(4);
    binaryTree.insert(10);
    binaryTree.insert(8);
    binaryTree.insert(11);
	binaryTree.insert(12);
	binaryTree.insert(13);


    bool b = binaryTree.contains(1);
    int x = binaryTree.findMin();
    cout << b << " "<< x <<endl;
    x = binaryTree.findMax();
    cout << x <<endl;
    binaryTree.remove(10);
	 

    binaryTree.printTree(ORDER_MODE_PREV);
    cout <<endl;
    binaryTree.printTree(ORDER_MODE_MID);
    cout <<endl;
    binaryTree.printTree(ORDER_MODE_POST);
    cout <<endl;

	getchar();
    return 0;
}


 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值