主要是刪除操作
二叉排序樹的刪除
1. 刪除葉結點,直接刪除
2. 刪除結點p只有左子樹或右子樹,讓其子樹替代該結點p即可
3. 刪除結點p既有左子樹又有右子樹,以該結點p爲根,查找中序遍歷下第一個結點t,使這個結點t替換p結點(val覆蓋即可),再遞歸一次刪除這個結點t即可
#include <iostream>
#include <string>
using namespace std;
typedef int ElementType;
typedef struct TreeNode{
ElementType val;
TreeNode* left;
TreeNode* right;
TreeNode(ElementType x):val(x), left(nullptr), right(nullptr){}
}*ThreadTree;
void visit(TreeNode* node)
{
cout << node->val << " ";
}
void inOrder(ThreadTree root)
{
if( root ){
inOrder(root->left);
visit(root);
inOrder(root->right);
}
}
// 非遞歸形式創建、插入BST
// 遞歸形式雖然較簡潔,但若二叉樹深度過大
// 遞歸棧創建過多,其效率就會很低
bool BST_Insert(ThreadTree& root, int n = 0)
{
if( n <= 0 )
return false;
cout << "Please input " << n << " value to insert BST:\n";
while( n-- )
{
ElementType x; cin >> x;
ThreadTree t = new TreeNode(x);
if( root == nullptr ){
root = t;
continue;
}
ThreadTree p = root, pre;
while( p ){
pre = p;
if( x < p->val )
p = p->left;
else if( x > p->val )
p = p->right;
else
break;
}
// BST不存在相同的值
if( p && p->val == x ) continue;
if( x < pre->val )
pre->left = t;
else if( x > pre->val )
pre->right = t;
}
return true;
}
TreeNode* findFirst(ThreadTree root)
{
TreeNode* p = root->right; //右子樹中查找最左下結點
while( p->left )
p = p->left;
return p;
}
// 二叉排序樹的刪除
// 1. 刪除葉結點p,直接刪除
// 2. 結點p只有左子樹或右子樹,讓子樹替代該結點p
// 3. 結點p既有左子樹又有右子樹,以該結點p爲根,查找中序遍歷下第一個結點t
// 使這個結點t替換結點p,再遞歸刪除這個結點t即可
bool Node_Delete(TreeNode*& p, const int& val)
{
if( !p ) return false;
if( p->val > val )
return Node_Delete(p->left, val);
else if( p->val < val )
return Node_Delete(p->right, val);
else{
// 查找到要刪除的結點p
TreeNode* t = p;
// 以下直接更改p的指向,是因爲傳入的參數是引用型
// 引用型是直接對原樹的結點(而非拷貝)進行操作
// 葉結點
if( !p->left && !p->right ){
p = nullptr;
delete t;
}
// 只有左子樹
else if( p->left && !p->right ){
p = p->left;
delete t;
}
// 只有右子樹
else if( !p->left && p->right ){
p = p->right;
delete t;
}
// 左、右子樹均存在
else{
t = findFirst(p);
p->val = t->val;
return Node_Delete(p->right, t->val);
}
}
return true;
}
// 注意這裏root需傳引用類型,因爲可能刪除根結點也是可能的
bool BST_Delete(ThreadTree& root, int val = 0)
{
cout << "delete value " << val << "\n";
return Node_Delete(root, val);
}
int main( )
{
int n;
cin >> n;
//8
//1 2 8 1 10 1 7 3
//8
//6 2 8 1 10 4 7 3
ThreadTree root = nullptr;
BST_Insert(root, n);
inOrder(root); cout << "\n\n";
BST_Delete(root, 2);inOrder(root);
cout << "\n";
BST_Delete(root, 8); inOrder(root);
cout << "\n";
BST_Delete(root, 10); inOrder(root);
cout << "\n";
BST_Delete(root, 1); inOrder(root);
cout << "\n";
return 0;
}