二叉搜索树的实现(查找,插入,删除的递归与非递归)

来源:互联网 发布:php 时间轴源码 编辑:程序博客网 时间:2024/05/18 03:32

BST定义:

二叉搜索树:又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树
1、若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
2、若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
3、它的左右子树也分别为二叉搜索树

除此之外,还有一点值得在意:二叉搜索树的最左节点是所有节点的值中最小值,而最右节点则是最大值。

BST的实现:

1.节点的定义:

template<class K,class V>struct Node{Node(const K& key,const V& value):_key(key),_value(value),_pLeft(NULL),_pRight(NULL){}K _key;V _value;Node<K,V>* _pLeft;Node<K,V>* _pRight;};
2.查找节点中指定key值的节点的实现

①非递归

Node* Find(const K& key)    //外部接口{return _Find(_pRoot,key);}Node* _Find(Node* pRoot,const K& key)  //实现方法{if(pRoot==NULL)return NULL;while(pRoot){if(key<pRoot->_key){pRoot=pRoot->_pLeft;}else if(key>pRoot->_key){pRoot=pRoot->_pRight;}elsereturn pRoot;}return NULL;}

②非递归

Node* Find(const K& key)   //外部接口{return _Find(_pRoot,key);}Node* _Find(Node* pRoot,const K& key)   //实现方法{if(pRoot==NULL)return NULL;if(pRoot->_key==key)return pRoot;else if(key<pRoot->_key)return _Find(pRoot->_pLeft,key);elsereturn _Find(pRoot->_pRight,key);}


3.插入指定key值与value值的节点

由于在这里我们认为key值是区分这些节点的关键字,而且是不能重复的,所以有以下实现:

①非递归

bool Insert(const K& key, const V& value)   //外部接口{return _Insert(_pRoot,key,value);}bool _Insert(Node*& pRoot,const K& key,const V& value)    //实现方法{if(pRoot==NULL){pRoot=new Node(key,value);return true;}Node* pcur=pRoot;Node* parent=NULL;while(pcur){if(pcur->_key==key)return false;else if(key<pcur->_key){parent=pcur;pcur=pcur->_pLeft;}else{parent=pcur;pcur=pcur->_pRight;}}pcur=new Node(key,value);if(key<parent->_key)parent->_pLeft=pcur;elseparent->_pRight=pcur;return true;}

②递归

bool Insert(const K& key, const V& value)   //外部接口{return _Insert(_pRoot,key,value);}bool _Insert(Node*& pRoot,const K& key,const V& value)   //实现方法{if(pRoot==NULL){pRoot=new Node(key,value);return true;}if(pRoot->_key==key)return false;if(key<pRoot->_key)return _Insert(pRoot->_pLeft,key,value);elsereturn _Insert(pRoot->_pRight,key,value);}

4.删除指定key值的节点

对于删除这一操作,我们仔细分析一下当中节点可能的情况:

1.有右孩子无左孩子,且在双亲的右子树中


2.有右孩子无左孩子,且在双亲的左子树中


3.有右孩子无左孩子,且为根节点


4.有左孩子无右孩子,且在双亲的右子树中


5.有左孩子无右孩子,且在双亲的左子树中


6.有左孩子无右孩子,且为根节点


7.有左孩子有右孩子,且为根节点


8.有左孩子有右孩子,但不为根节点


①非递归

bool Remove(const K& key)    //外部接口{return _Remove(_pRoot,key);}bool _Remove(Node*& pRoot,const K& key)     //实现方法{if(pRoot==NULL)return false;Node* pcur=pRoot;Node* parent=NULL;while(pcur){if(key<pcur->_key){parent=pcur;pcur=pcur->_pLeft;}else if(key>pcur->_key){parent=pcur;pcur=pcur->_pRight;}else{if(pcur->_pLeft==NULL){if(pcur==pRoot)pRoot=pcur->_pRight;else if(pcur==parent->_pLeft)parent->_pLeft=pcur->_pRight;elseparent->_pRight=pcur->_pRight;}else if(pcur->_pRight==NULL){if(pcur==pRoot)pRoot=pcur->_pLeft;else if(pcur==parent->_pLeft)parent->_pLeft=pcur->_pLeft;elseparent->_pRight=pcur->_pLeft;}else{Node* pDel=pcur;parent=pcur;pDel=pDel->_pRight;while(pDel->_pLeft){parent=pDel;pDel=pDel->_pLeft;}pcur->_key=pDel->_key;pcur->_value=pDel->_value;if(pDel==parent->_pLeft){parent->_pLeft=pDel->_pRight;}else{parent->_pLeft=pDel->_pRight;}pcur=pDel;}delete pcur;return true;}}return false;}


②递归

bool Remove(const K& key)   //外部接口{return _Remove(_pRoot,key);}bool _Remove(Node*& pRoot,const K& key)    //实现方法{if(pRoot==NULL)return false;if(key<pRoot->_key)return _Remove(pRoot->_pLeft,key);else if(key>pRoot->_key)return _Remove(pRoot->_pRight,key);else{Node* pcur=pRoot;if(pcur->_pLeft==NULL){pRoot=pcur->_pRight;delete pcur;}else if(pcur->_pRight==NULL){pRoot=pcur->_pLeft;delete pcur;}else{Node* pDel=pRoot;pcur=pcur->_pRight;while(pcur->_pLeft){pcur=pcur->_pLeft;}pDel->_key=pcur->_key;pDel->_value=pcur->_value;_Remove(pRoot->_pRight,pcur->_key);}return true;}}







阅读全文
0 0
原创粉丝点击