構造二叉排序樹(BST)+二叉排序樹的刪除
阿新 • • 發佈:2019-01-05
主要是刪除操作
二叉排序樹的刪除
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; }