1. 程式人生 > >二叉排序樹節點刪除(c++)

二叉排序樹節點刪除(c++)

二叉樹是資料結構中一個重要的概念,而在二叉排序樹的操作中,節點刪除又相對較為複雜。本文把自己寫的演算法做一些總結,同時希望能夠和大家進行交流

首先我們要明白二叉排序樹的性質:

一、二叉排序樹是每個節點最多含有兩個節點的樹,或者是一棵空樹。

二、二叉排序樹中左子節點小於父節點,右子節點大於父節點。

對於如何刪除二叉排序樹中的節點,主要需要考慮三種情況:

一、要刪除的節點是葉子節點,即它沒有左右孩子,這時只需把父節點的指標置為空。(注意需要區分要刪除的節點是父節點的左孩子還是右孩子)。

二、要刪除的節點只有一個孩子,這種情況也比較簡單,只需要把父節點的指標指向被刪除節點的孩子節點(注意此時不僅需要考慮被刪除的節點是父親節點的左孩子還是右孩子,也要考慮被刪除節點是有左子樹還是右子樹)。

三、要刪除的節點即有左孩子也有右孩子,對於這種情況,把被刪除節點的中序後繼節點 替換到刪除節點。

下面我們來看程式:

Binary_Search_Tree.h檔案如下:

template <class T>
struct node{
	T data;
	node *left;
	node *right;

};
先用結構體定義節點。

Binary_Search_Tree.cpp檔案如下:

template<class T>
void Binary_Search_Tree<T>::Delete_Node(node<T> *head,T &x)
{
	node<T> *parent,*p,*Q;
//	Find(head,x);
	//如果為空,則退出
//	if(f==false)
//		return;
	//不為空時
	while(head!=NULL)
	{ 
		if(head->data==x)break;
		parent = head; //得到的是要刪除結點的父結點
		head = (head->data>x)?head->left:head->right;
	}/*此時head指標指向的是要被刪除的節點*/
	 //要刪除的結點為葉子結點
	if(head->left==NULL && head->right==NULL)
        {
		//區分是父親結點的左孩子還是右孩子
		if(parent->left->data==x)
			parent->left=NULL;
		if(parent->right->data==x)
			parent->right=NULL;
		delete(head);
		return;
	}


	//要刪除結點只存在一個孩子 /*如圖二中,B為要刪除的節點,則把父節點指標指向B的左孩子
		// 左孩子不為空,右孩子為空
	if(head->left!=NULL && head->right==NULL)	
	{
		if(parent->left->data==x)
			parent->left = parent->left->left;
		if(parent->right->data==x)
			parent->right = parent->right->left;
		delete(head);
		return;
	}
	//左孩子為空,右孩子不為空
	if(head->left==NULL && head->right!=NULL)
	{
		if(parent->left->data==x)
			parent->left = parent->left->right;
		if(parent->right->data==x)
			parent->right = parent->right->right;

		delete(head);
		return;
	}
	/*要刪除結點左右都不為空*/
	if(head->left!=NULL && head->right!=NULL)
	{
		if(parent->left->data==x)
		{
			p = head->right; //p為要刪除結點的右孩子
			while(p->left!=NULL && p->left->left!=NULL)
				p = p->left;
			if(p->left!=NULL) /*左左孩子為空,此時p->left沒有左子數,此時Q即為刪除節點的後繼節點*/
			{	
				Q = p->left; 
				Q->left = head->left;  /*Q替換到被刪除節點,進行指標的改變*/
				parent->left = Q;  
				p->left = Q->right;   /*本來p->left指向Q,現在指向Q->right,Q->right有可能為空*/
				Q->right=NULL;	
			}
			else
			{
				p->left = head->left;
				parent->left = p;
			}
		}

		if(parent->right->data==x)
		{
			p = head->right; //p為要刪除結點的右孩子
			while(p->left!=NULL && p->left->left!=NULL) 	
	       			p = p->left;
			if(p->left!=NULL)
			{	
				Q = p->left;          		
				Q->left = head->left; 	
				parent->right = Q;
				p->left = Q->right;		
				Q->right=NULL;	
	
			}	
			else
			{
				p->left = head->left;
				parent->right = p;
			}
		}
		delete(head);
		return;
	}
}