二叉搜索树的实现

来源:互联网 发布:开淘宝网店计划书 编辑:程序博客网 时间:2024/05/27 16:42

概念:

二叉搜索树:又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树

1、若它的左子树不为空,则左子树上所有节点的值都小于根节点的值

2、若它的右子树不为空,则右子树上所有节点的值都大于根节点的值

3、它的左右子树也分别为二叉搜索树二叉树的插入:向二插搜索树中插入新的元素,必须先检测者个元素是否在树中已经存在,若存在就不能插入,否则将新元素插入到搜索停止的位置。

1. _pRoot= =NULL 树为空,直接插入,返回true

2.插入已存在元素,返回flase

3.找到插入位置,直接插入

首先查找元素是否在二叉搜索树中,如果不存在,则返回;

否则要删除的结点可能分下面四种情况:

1.要删除的节点有无孩子结点。

2.要删除的节点只有左孩子。

3.要删除的节点只有右孩子。

4.要删除的节点有左右孩子。(可能还会存在有单支的情况)。

对应的情况,解决办法如下:

1.直接删除结点

2.删除该节点并且将该节点的双亲节点的指向该节点的左孩子。

3.删除该节点并且将该节点的双亲节点指向该节点的右孩子。

4.将该节点的值与该节点的右孩子的最左值交换,(也就是他的右子树中序遍历下的第一个数),再来处理该节点的删除问题。全部代码实现如下:

#include <queue>
#include <iostream>
using namespace std;
template<class T>
struct BSTNode
{
BSTNode* _pLeft;
BSTNode* _pRight;
T _key;
BSTNode(const T& key)
:_pLeft(NULL)
,_pRight(NULL)
,_key(key)
{}
};




template<class T>
class BinarySeachTree
{

public:
BinarySeachTree()
:_pRoot(NULL)
{}
BinarySeachTree(T *arr, size_t size)
{
_pRoot = NULL;
for(int i=0;,i<size; i++)
{
Insert(arr[i]);
}
}
bool Insert(const T& data)
{
if(NULL == _pRoot)
{
_pRoot = new BSTNode<T>(data);
return true;
}
BSTNode<T>* pCur = _pRoot;
BSTNode<T>* pParent = NULL;
while(pCur)
{
pParent = pCur;
if(pCur->_key < data)
pCur = pCur->_pRight;
else if(pCur->_key > data)
pCur = pCur->_pLeft;
else
return false;
}
if(pParent->_key < data)
pParent->_pRight = new BSTNode<T>(data);
if(pParent->_key > data)
pParent->_pLeft = new BSTNode<T>(data);
return true;
}
BSTNode<T>* Find(const T& data)
{
BSTNode<T>* pCur = _pRoot;
while(pCur)
{
if(pCur->_key == data)
return pCur;
if(pCur->_key <data)
pCur = pCur->_pRight;
else
pCur = pCur->_pLeft;
}
return NULL;
}
bool Remove(const T& data)
{
BSTNode<T>* pCur = _pRoot;
BSTNode<T>*pParent  = NULL;
while(pCur)
{
//寻找删除节点
if(pCur->_key < data)
{
pParent = pCur;
pCur = pCur->_pRight;
}
else if(pCur->_key > data)
{
pParent = pCur;
pCur = pCur->_pLeft;
}
else 
{
//左孩子为NULL
if(NULL == pCur->_pLeft)
{
//判断是否为根节点;
if(pParent == NULL)
{
_pRoot = pCur->_pRight;
}
else
{
if(pParent->_pLeft == pCur)
pParent->_pLeft = pCur->_pRight;
else
pParent->_pRight = pCur->_pRight;
}
delete pCur;
}
else if(NULL == pCur->_pRight)   //当前节点的右孩子为NULL
{
if(NULL == pParent)
{
_pRoot = pCur->_pLeft;
}
else
{
if(pParent->_pLeft == pCur)
pParent->_pLeft = pCur->_pLeft;
else
pParent->_pRight = pCur->_pLeft;
}
delete pCur;
}
else 
{
//左右孩子都存在,将右子树的最左节点与当前节点交换
BSTNode<T>* temp = pCur->_pRight;
BSTNode<T>* pPre = pCur;
while(temp->_pLeft)
{
pPre = temp;
temp = temp->_pLeft;
}
swap(temp->_key, pCur->_key);
if(temp == pPre->_pRight)   //当前节点的右孩子可能是个右单支情况
{
pCur->_pRight = temp->_pRight;
}
else if(temp == pPre->_pLeft)  
pPre->_pLeft = temp->_pRight;
delete pCur;
}
return true;
}
}
return false;
}


BinarySeachTree<T>& operator =(BinarySeachTree<T>& tree)
{
if(this != tree)
{
BinarySeachTree<T> tmp(tree);
swap(_pRoot,tmp._pRoot);
}
return *this;
}


BinarySeachTree(const BinarySeachTree<T>& tree)
:_pRoot(NULL)
{
if(tree._pRoot ==NULL)
return;
queue<BSTNode<T>*> q;
        q.push(tree._pRoot);
while(!q.empty())
{
BSTNode<T>* pCur = q.front();
Insert(pCur->_key);
q.pop();
if(pCur->_pLeft)
q.push(pCur->_pLeft);
if(pCur->_pRight)
q.push(pCur->_pRight);
}
}






~BinarySeachTree()
{
_Destory(_pRoot);
}


BSTNode<T>* FindMin()
{
BSTNode<T>* pCur = _pRoot;
while(pCur->_pLeft)
{
pCur = pCur->_pLeft;
}
return pCur; 
}
BSTNode<T>* FindMax()
{
BSTNode<T>* pCur = _pRoot;
while(pCur->_pRight)
pCur = pCur->_pRight;
return pCur;
}
private:
void _Destory(BSTNode<T>* pRoot)
{
if(pRoot == NULL)
return;
_Destory(pRoot->_pLeft);
_Destory(pRoot->_pRight);
delete pRoot;
}
private:
BSTNode<T>* _pRoot;
};


插入和删除操作的主体部分是查找,查找效率代表了二叉排序中上各个操作的性能。对有n个结点的
二叉排序树,若每个元素查找的概率相等,则二叉搜索树平均查找长度是结点在二叉搜索树的深
度的函数,即结点越深,则比较次数越多

C(i)为查找到第i个数据元素时关键字的比较次数

当二叉搜索树是完全二叉树是:

当二叉搜索树是一支单支退化二叉搜索树时:


因此最坏情况下,二叉排序树的平均查找长度为O(n),一般情况下平均查找长度为O(lbn)

0 0