迭代器:它的用法與指針用法相同
使用迭代器實現二叉搜索樹,使用有兩個指針域的頭結點實現,
並且多給BSTree中加入一個雙親結點_pParent。
代碼:
BSTIterator.hpp
#pragma once
#include<iostream>
using namespace std;
#include<assert.h>
template<class k,class v>
struct BSTNode
{
BSTNode(const k& key=k(),const v& value=v())
:_pLeft(NULL)
,_pRight(NULL)
,_pParent(NULL)
,_key(key)
,_value(value)
{}
BSTNode<k,v>* _pLeft;
BSTNode<k,v>* _pRight;
BSTNode<k,v>* _pParent;
k _key;
v _value;
};
template<class K, class V, class Ref, class Ptr>
class BSTIterator
{
typedef BSTNode<K, V> Node;
typedef BSTIterator<K, V, Ref, Ptr> Self;
public:
BSTIterator()
:_pNode(NULL)
{}
BSTIterator(Node* pNode)
:_pNode(pNode)
{}
BSTIterator(const Self& s)
:_pNode(s._pNode)
{}
Self& operator++()
{
Increment();
return *this;
}
Self operator++(int)
{
Self temp(*this);
Increment();
return temp;
}
Self& operator--()
{
Decrement();
return *this;
}
Self operator--(int)
{
Self temp(*this);
Decrement();
return temp;
}
Ref operator*()//解引用
{
return _pNode->_key;
}
Ptr operator->()//->
{
return &(operator*());
}
bool operator!=(const Self& s)
{
return _pNode!=s._pNode;
}
bool operator==(const Self& s)
{
return !(*this!=s);
}
protected:
// 取當前結點的下一個結點
void Increment()
{
//如果右子樹存在,右子樹中的最小結點就是當前結點的下一個結點
if(_pNode->_pRight)
{
_pNode=_pNode->_pRight;
while(_pNode->_pLeft)
_pNode=_pNode->_pLeft;
}
else//右子樹不存在
{
Node* pParent=_pNode->_pParent;
while(pParent->_pRight==_pNode)
{
_pNode=pParent;
pParent=pParent->_pParent;
}
//特殊情況:根的右子樹不存在,獲取根的下一節點即爲end()
if(_pNode->_pRight!=pParent)
_pNode=pParent;
}
}
// --取前一個小的結點,在left子樹中
void Decrement()
{
//左子樹存在
if(_pNode->_pRight)
{
_pNode=_pNode->_pLeft;
while(_pNode->_pRight)
_pNode=_pNode->_pRight;
}
else
{
Node* pParent=_pNode->_pParent;
while(_pNode==pParent->_pLeft)
{
_pNode=pParent;
pParent=pParent->_pParent;
}
_pNode=pParent;
}
}
protected:
Node* _pNode;
};
template<class k,class v>
class BSTree
{
typedef BSTNode<k,v> Node;
public:
typedef BSTIterator<k,v,k&,k*> Iterator;
public:
BSTree()
{
_pHead=new Node();
_pHead->_pLeft=_pHead;
_pHead->_pRight=_pHead;
_pHead->_pParent=NULL;
}
Iterator Begin()
{
return _pHead->_pLeft;
}
Iterator End()
{
return _pHead;
}
Node* Find(const k& key)
{
Node* pCur=GetRoot();
while(pCur)
{
if(key==pCur->_key)
return pCur;
else if(key<pCur->_key)
pCur=pCur->_pLeft;
else
pCur=pCur->_pRight;
}
return NULL;
}
bool Insert(const k& key,const v& value)
{
Node*& pRoot=_pHead->_pParent;
if(NULL==pRoot)
{
pRoot=new Node(key,value);
pRoot->_pParent=_pHead;
}
else
{
Node* pCur=pRoot;
Node* pParent=NULL;
while(pCur)
{
if(key < pCur->_key)//向左插入
{
pParent=pCur;
pCur=pCur->_pLeft;
}
else if(key > pCur->_key)//向右插入
{
pParent=pCur;
pCur=pCur->_pRight;
}
else//等於根節點,不需要插入
{
return false;
}
}
//插入到葉子結點後時
pCur=new Node(key,value);
if(key<pParent->_key)
pParent->_pLeft=pCur;
else
pParent->_pRight=pCur;
pCur->_pParent=pParent;
}
_pHead->_pLeft=LeftMost();
_pHead->_pRight=RightMost();
return true;
}
void InOrder()//中序遍歷
{
cout<<"InOrder:"<<endl;
_InOrder(GetRoot());
cout<<endl;
}
const k& GetMaxKey()const//找最右結點(最大)
{
Node* pRoot=GetRoot();
assert(pRoot);
Node* pCur=pRoot;
while(pCur->_pRight)
pCur=pCur->_pRight;
return pCur->_key;
}
const k& GetMinKey()const//找最左結點(最小)
{
Node* pRoot=GetRoot();
assert(pRoot);
Node* pCur=pRoot;
while(pCur->_pLeft)
pCur=pCur->_pLeft;
return pCur->_key;
}
bool Remove(const k& key)//刪除key結點
{
Node*& pRoot=GetRoot();
//樹爲空,不能刪除結點
if(NULL==pRoot)
return false;
//只有一個根節點,要刪除的結點正好是根節點
if(NULL==pRoot->_pLeft && NULL==pRoot->_pRight && key==pRoot->_key)
{
delete pRoot;
_pHead->_pParent=NULL;
}
else
{
//找待刪除結點
Node* pCur=pRoot;
Node* pParent=NULL;
while(pCur)
{
if(key<pCur->_key)
{
pParent=pCur;
pCur=pCur->_pLeft;
}
else if(key>pCur->_key)
{
pParent=pCur;
pCur=pCur->_pRight;
}
else
break;//找到了該節點
}
//已找到待刪除結點---》1.沒有左孩子,只有右孩子
//2.沒有右孩子,只有左孩子
// 3.左右孩子都沒有
//4.左右孩子都存在
//可以合併1,3 或2,3
if(NULL==pCur)
return false;
else
{ //1.沒有左孩子,右孩子可能存在,也可能不存在(NULL)
if(NULL==pCur->_pLeft)
{
if(pCur!=pRoot)
{
if(pCur==pParent->_pRight)
pParent->_pRight=pCur->_pRight;
else
pParent->_pLeft=pCur->_pRight;
}
else
pRoot=pCur->_pRight;
}
//2.沒有右孩子,左孩子可能存在,也可能不存在(NULL)
else if(NULL==pCur->_pRight)
{
if(pCur!=pRoot)
{
if(pCur==pParent->_pRight)
pParent->_pRight=pCur->_pLeft;
else
pParent->_pLeft=pCur->_pLeft;
}
else
pRoot=pCur->_pLeft;
}
//3.左右子樹都存在
else
{
//找中序遍歷的第一個節點,爲右子樹中最小的結點
//pParnet一直是firstInOrder的雙親
pParent=pCur;//防止在找右子樹中最小結點時,右子樹沒有左孩子,無法進入循環,pParent會一直爲空
Node* firstInOrder=pCur->_pRight;
//找該節點的右子樹中最左邊的結點,即右子樹中key最小的結點
while(firstInOrder->_pLeft)
{
pParent=firstInOrder;
firstInOrder=firstInOrder->_pLeft;
}
//交換key最小結點和根節點的值
pCur->_key=firstInOrder->_key;
pCur->_value=firstInOrder->_value;
if(pParent->_pLeft==firstInOrder)
pParent->_pLeft=firstInOrder->_pRight;
else
pParent->_pRight=firstInOrder->_pRight;
pCur=firstInOrder;
}
delete pCur;
pCur=NULL;
}
}
_pHead->_pLeft=LeftMost();
_pHead->_pRight=RightMost();
return true;
}
Node* LeftMost()
{
Node* pCur = GetRoot();
assert(pCur);
while(pCur->_pLeft)
pCur = pCur->_pLeft;
return pCur;
}
Node* RightMost()
{
Node* pCur = GetRoot();
assert(pCur);
while(pCur->_pRight)
pCur = pCur->_pRight;
return pCur;
}
Node*& GetRoot()const
{
return _pHead->_pParent;
}
Node* ToList()//轉化爲雙向鏈表
{
//找鏈表頭
Node* pHead=GetRoot();
if(NULL==pHead)
return;
while(pHead->_pLeft)
pHead=pHead->_pLeft;
Node* prev = NULL;
_ToList(GetRoot(), prev);
return pHead;
}
protected:
void _InOrder(Node* pRoot)
{
if(pRoot)
{
_InOrder(pRoot->_pLeft);
cout<<pRoot->_key<<" ";
_InOrder(pRoot->_pRight);
}
}
void _ToList(Node* pRoot, Node*& prev)
{
if(pRoot)
{
_ToList(pRoot->_pLeft, prev);
// 當前節點的左指針域
pRoot->_pLeft = prev;
// 上一個結點的右指針域
if(prev)
prev->_pRight = pRoot;
prev = pRoot;
_ToList(pRoot->_pRight, prev);
}
}
private:
Node* _pHead;
};
測試代碼:
#include"BSTIterator.hpp"
void Test1()
{
BSTree<int,int> bst;
int a[]={5,3,4,1,7,8,2,6,0,9};
for(int idx=0;idx<(sizeof(a)/sizeof(a[0]));++idx)
{
bst.Insert(a[idx],idx);
}
bst.InOrder();
bst.Find(8);
cout<<bst.GetMinKey()<<endl;
cout<<bst.GetMaxKey()<<endl;
}
void Test2()//情況三①②及情況一
{
BSTree<int,int> bst;
int a[]={5,3,4,1,7,8,2,6,0,9};
//int a[]={5,3,4,1,8,2,6,7,0,9};
for(int idx=0;idx<(sizeof(a)/sizeof(a[0]));++idx)
{
bst.Insert(a[idx],idx);
}
bst.Remove(8);
bst.InOrder();
bst.Remove(6);
bst.InOrder();
}
void Test3()//情況三中的③
{
BSTree<int,int> bst;
int a[]={5,7,8,6,9};
for(int idx=0;idx<(sizeof(a)/sizeof(a[0]));++idx)
{
bst.Insert(a[idx],idx);
}
bst.Remove(5);
bst.InOrder();
}
void Test4()//情況二
{
BSTree<int,int> bst;
int a[]={5,3,4,1,7,6,0};
for(int idx=0;idx<(sizeof(a)/sizeof(a[0]));++idx)
{
bst.Insert(a[idx],idx);
}
bst.Remove(1);
bst.InOrder();
bst.Remove(7);
bst.InOrder();
}
void Test5()//情況四
{
BSTree<int,int> bst;
int a[]={5,3,4,1,7,8,2,6,0,9};
for(int idx=0;idx<(sizeof(a)/sizeof(a[0]));++idx)
{
bst.Insert(a[idx],idx);
}
bst.Remove(5);
bst.InOrder();
bst.Remove(7);
bst.InOrder();
}
void Test6()//情況四
{
BSTree<int,int> bst;
int a[]={5,3,4,1,7,8,2,0,9};
for(int idx=0;idx<(sizeof(a)/sizeof(a[0]));++idx)
{
bst.Insert(a[idx],idx);
}
bst.Remove(5);
bst.InOrder();
}
int main()
{
Test1();
Test2();
Test3();
Test4();
Test5();
Test6();
return 0;
}