BinaryTreeNode: 節點類
BinaryTree:二叉排序樹類
//刪除一個節點自身
template<typename T>
BinaryTreeNode<T>* BinaryTreeNode<T>::RemoveSelf() {
//分三種情況
//第一種情況:要刪除的是葉子節點,改變父節點的指向,刪除該節點
if (nullptr == pLeft && nullptr == pRight)
{
//判斷當前節點是父節點的左節點還是右節點
if (pParent->pLeft == this)
{
pParent->pLeft = nullptr;
cout << "是左節點" << endl;
}
else
{
pParent->pRight = nullptr;
}
delete this;//釋放當前節點的內存
return nullptr;//返回刪除後的當前位置的新節點
}
//第二種情況:要刪除的節點有一個節點,可再細分爲只有左節點或者右節點
//只有左節點沒有右節點
else if (nullptr == pRight)
{
BinaryTreeNode<T>* pNode = pLeft;
//判斷當前節點是父節點的左節點還是右節點
if (pParent->pLeft == this)
{
pParent->pLeft = pLeft;
}
else
{
pParent->pRight = pLeft;
}
pLeft->pParent = pParent;
delete this;//釋放當前節點的內存
return pNode;//返回刪除後的當前位置的新節點,即當前節點的左節點
}
//只有右節點沒有左節點
else if (nullptr == pLeft)
{
BinaryTreeNode<T>* pNode = pRight;
//判斷當前節點是父節點的左節點還是右節點
if (pParent->pLeft == this)
{
pParent->pLeft = pRight;
}
else
{
pParent->pRight = pRight;
}
pRight->pParent = pParent;
delete this;//釋放當前節點的內存
return pNode;//返回刪除後的當前位置的新節點,即當前節點的右節點
}
//第三種情況:要刪除的節點既有左節點,又有右節點,找到一個後繼節點的值,賦給要刪除的節點值,然後刪除這個後繼節點
//找到一個後繼節點值比要刪除的節點大,但是最接近要刪除的節點,即爲要刪除的節點的右子樹中的最小值,
//或要刪除的節點的左子樹中的最大值,這樣纔可保證替換要刪除的節點的值,還能滿足左小右大。
else
{
//1.查找右子樹中數據最小的節點
BinaryTreeNode<T>* pMin = this->finMinDataNode();
//2.將最小數據覆蓋要刪除節點的數據
this->val = pMin->val;
//3.遞歸刪除最小數據節點
pMin->RemoveSelf();
return this; //返回刪除後的當前位置的新節點,因爲當前節點只是值被替換,所以還是當前節點
}
//注:第三種情況將找到的這個後繼節點的值賦給要刪除的節點值後 ,此時應該要刪除這個後繼節點,
//如果不使用遞歸,則是以下兩種情況
//1.如果沒有右節點,問題變成整個問題的第一種情況,因爲後繼節點是個葉子節點,直接刪除
//2.如果有右節點,問題變成整個問題的第二種情況
}
template<typename T> //查找當前結點的右子樹的最小數據結點
BinaryTreeNode<T>* BinaryTreeNode<T>::finMinDataNode()
{
BinaryTreeNode<T> * pMin = this->pRight;
while (pMin->pLeft != nullptr)
{
pMin = pMin->pLeft;//一直往左邊找
}
return pMin;
}
template<typename T>//根據節點值查找節點
BinaryTreeNode<T>* BinaryTreeNode<T>::findNode(const T& val)
{
BinaryTreeNode<T>* pNode = this;//當前結點
while (pNode != nullptr)
{
//判斷val與pNode的數據進行比較
if (val < pNode->val)
{
pNode = pNode->pLeft;
}
else if (val > pNode->val)
{
pNode = pNode->pRight;
}
else
{
return pNode;
}
}
return pNode;
}
template<typename T>
void BinaryTree<T>::Remove(const T& val)
{
if (pRoot != nullptr)
{
if (pRoot->val != val)
{
BinaryTreeNode<T>* pNode = pRoot->findNode(val);//查找結點
pNode->RemoveSelf();//移除結點
}
else//要刪除的是根結點
{
pRoot = pRoot->RemoveSelf();
}
}
}