1. 程式人生 > >C++資料結構——二叉搜尋樹(實現自定義迭代器)

C++資料結構——二叉搜尋樹(實現自定義迭代器)



#ifndef BS_Tree_H
#define BS_Tree_H
#include"node.h" 
#include<iostream>
#include<queue>
using namespace std;
template<typename T>


class bs_Tree
{
friend class myIterator;
private:
node<T> *root;
//二叉搜尋樹根節點 


//以後序遍歷方式複製二叉搜尋樹,返回根節點
node<T> * copyBSTree(node<T> *root)
{
node<T> *p=nullptr;
//根節點
node<T> *l=nullptr; //左子樹
node<T> *r=nullptr; //右子樹


if(!root) //遞迴結束條件
{
return nullptr;
}
else
{
l=copyBSTree(root->left); //遞迴複製左子樹
r=copyBSTree(root->right); //遞迴複製右子樹
p=new node<T>(root->val,nullptr,l,r);


if(l)
{
l->parent=p;
}
if(r)
{
r->parent=p;
}
}


return p;
}

//以後序遍歷方式刪除二叉搜尋樹,
void deleteBSTree(node<T>* root)

{
if(!root) //遞迴結束條件
{
return;
}
else
{
deleteBSTree(root->left);
deleteBSTree(root->right);
delete root;
}
}

public:
#include"myIterator.h"
bs_Tree():root(nullptr){}
bs_Tree(bs_Tree &rh)
{
root=copyBSTree(rh.root);
}


bs_Tree& operator=(bs_Tree &rh)
{
if(this==&rh) //自身賦值
{
return *this;
}


deleteBSTree(root);
//釋放原來的空間
root=copyBSTree(rh.root);



return *this;
}



~bs_Tree()
{
deleteBSTree(root);
root=nullptr;
}








//返回迭代器-布林值鍵對
//迭代器指向被插入的位置
//插入成功布爾值為真,否則為假

pair<myIterator,bool> insert(T v) 
{

if(!root) //二叉搜尋樹為空 
{

root=new node<T>(v);
return make_pair(myIterator(root,this),true);
}
else
{
node<T> *tem=root;
node<T> *prt;
while(tem!=nullptr) //查詢合適的插入點 
{
prt=tem;
if(v==tem->val)
{
return make_pair(myIterator(tem,this),false); //存在相同的值則不插入
}
else if(v<tem->val)
{
tem=tem->left;
}
else
{
tem=tem->right;
}
}


node<T> *newNode=new node<T>(v,prt);

if(v<prt->val)
{

prt->left=newNode;  //把新節點作為父節點的左節點
}
else
{
prt->right=newNode; //把新節點作為父節點的右節點
}

return make_pair(myIterator(newNode,this),true);
}


}


void erase(myIterator &pos)
{

node<T> *dNode=pos.curr; //被刪除的節點
node<T> *pNode=dNode->parent; //被刪除節點的父節點
node<T> *rNode=nullptr; //替代節點


//被刪除節點的左子樹和右子樹都為空
if(!dNode->left&&!dNode->right) 
{
if(!pNode) //當只有一個根節點時
{
delete dNode;
root=nullptr; //把根節點賦為空,防止解構函式再次刪除
return;
}

if(dNode->val<pNode->val)
   pNode->left=nullptr;
else if(dNode->val>pNode->val)
   pNode->right=nullptr;

delete dNode;
return;
}


//被刪除節點的左子樹或右子樹為空
else if(!dNode->left||!dNode->right)
{
if(!dNode->left)  //左子樹為空
rNode=dNode->right;
   else if (!dNode->right) //右子樹為空
rNode=dNode->left;


if(rNode) //被刪除節點的左子樹或右子樹為只有一個為空時
{
rNode->parent=pNode;
}
}
else //被刪除節點的左子樹和右子樹非空,選擇該節點右子樹最左邊的節點來替換
{
node<T> *prNode=dNode; //替代節點的父節點

rNode=dNode->right; //進入被刪除節點的右節點

while(rNode->left) //則沿著左子樹下降,直到到達葉子節點
{
prNode=rNode; //記錄替代節點的父節點
rNode=rNode->left;
}



if(prNode==dNode)//說明while沒有執行,即被刪除節點的右節點的左子樹為空
{
rNode->parent=pNode; //替換節點的父節點指向被刪除節點的父節點
rNode->left=dNode->left;//替換節點的左節點指向被刪除節點的左節點
dNode->left->parent=rNode; //被刪除節點的左子樹的父節點指向替換節點
}
else //被刪除節點右節點的左子樹不為空
{
prNode->left=rNode->right; //替換節點的父節點左子樹指向替換節點的右子樹
if(rNode->right) //替換節點不是葉子節點
 rNode->right->parent=prNode;

rNode->parent=pNode; //替換節點的父節點指向被刪除節點的父節點
rNode->left=dNode->left; //替換節點的左子樹指向被刪除節點的左子樹
rNode->right=dNode->right; //替換節點的右子樹指向被刪除節點的右子樹
dNode->left->parent=rNode; //被刪除節點的左子樹的父節點指向替換節點
dNode->right->parent=rNode; //被刪除節點的左子樹的父節點指向替換節點
}
}


if(!pNode) //被刪除節點為根節點
root=rNode; //使替換節點為根節點

//被刪除節點非根節點,使替換節點指向被刪除節點的父節點的左子樹或右子樹
else if(rNode->val<pNode->val)
    pNode->left=rNode;
else
pNode->right=rNode;



delete dNode; //刪除節點
}


myIterator begin() //返回中序遍歷的第一個元素
{
node<T> *tem=root;
while(tem->left)
{
tem=tem->left;
}


return myIterator(tem,this);
}


myIterator end()
{
return myIterator(nullptr,this);
}


};




#endif