1. 程式人生 > >構造二叉排序樹(BST)+二叉排序樹的刪除

構造二叉排序樹(BST)+二叉排序樹的刪除

主要是刪除操作

二叉排序樹的刪除
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;
}