數據結構---二叉樹(2)---平衡二叉樹(5 刪除)

0.簡介

刪除平衡二叉樹的結點也需要仔細的研究一下。還有代碼上對上一篇打了些補丁

1.刪除

刪除結點後的結構一般有兩種,一類是刪除後不平衡了,一類是刪除後仍然平衡。這兩類別目前對我們來說,沒有什麼區別,因爲前面已經研究過結點平衡調整的方法,所以可以直接在這裏使用,那麼需要研究的就是如何刪除結點。

我們先從鏈表的角度來看,鏈表刪除比較容易,改變指向下一個結點的指針就好,一般來說,改變一個就可以。

鏈表刪除

二叉樹來說,刪除就麻煩了一些,要有兩個指針需要變化,鏈表只需要考慮下一個元素怎麼連接上就好,樹要考慮子節點誰來連接。

二叉樹刪除結點

我們考慮讓子節點的任意一個來接替位置,我們就一律讓右邊的結點來接替父節點的位置,左節點保持不動,若沒有右結點,在去升左結點的位置。

結點換位

結點換位就要調整指針,這裏爲了方便,可以用另一種辦法,先考慮如下問題,如何刪除單鏈表中指針正在指向的元素,不需要額外變量,只需要將當前結點的下一個結點的內容複製過來,然後刪除下一個結點即可。樹中我也這麼做。

刪除的流程如下

1.找到要刪除的結點

2.將其刪除,並且移動相關結點數據

3.查看樹是否保持平衡,不平衡則調整。

2.實現

#include<iostream>
#include <algorithm>

using namespace std;
struct TreeNode
{
	TreeNode(){}
	TreeNode(int n,int h):num(n),height(h) {}
	int num = 0;
	int height = 0;
	TreeNode* left = nullptr;
	TreeNode* right = nullptr;
	TreeNode* parent = nullptr;
};

inline int getHeight(TreeNode* root)
{
	return root ? root->height : 0;
}

//調整平衡後樹高度
void adjustHeight(TreeNode*T)
{
	if (T->left != nullptr && T->right != nullptr)
		T->height = max(T->left->height + 1, T->right->height + 1);
	else if (T->left != nullptr)
		T->height = T->left->height + 1;
	else if (T->right != nullptr)
		T->height = T->right->height + 1;
	else
		T->height = 1;
}

void condition1(TreeNode*& root)
{
	/*   A
	    /
	   B
	  /
	 C
	*/
	TreeNode* A = root;
	TreeNode* B = root->left;

	A->left = B->right;
	B->parent = A->parent;
	A->parent = B;
	B->right = A;
	root = B;
	//重新計算平衡後,被調整結點的高度記錄
	adjustHeight(A);
	adjustHeight(B);
}

void condition2(TreeNode*& root)
{
	/*A
	   \
	    B
		 \
		  C
	*/
	TreeNode* A = root;
	TreeNode* B = root->right;

	A->right = B->left;
	B->parent = A->parent;
	A->parent = B;
	B->left = A;

	root = B;
	adjustHeight(A);
	adjustHeight(B);
}

void condition3(TreeNode*& root)
{
	/*   A
		/
	   B
	    \
	     C
	*/
	TreeNode* A = root;
	TreeNode* B = root->left;
	TreeNode* C = root->left->right;
	
	A->left = C->right;
	B->right = C->left;
	C->left = B;
	C->right = A;
	C->parent = A->parent;
	B->parent = C;
	A->parent = A;

	root = C;
	adjustHeight(A);
	adjustHeight(B);
	adjustHeight(C);
}

void condition4(TreeNode*& root)
{
	/*   A
		   \
	        B
		   /
		 C
	*/
	TreeNode* A = root;
	TreeNode* B = root->right;
	TreeNode* C = root->right->left;

	A->right = C->left;
	B->left = C->right;
	C->right = B;
	C->left = A;
	C->parent = A->parent;
	B->parent = C;
	A->parent = A;

	root = C;
	adjustHeight(A);
	adjustHeight(B);
	adjustHeight(C);
}

int addNode(TreeNode* &root,int num)
{
	//如果節點的空
	if (root == nullptr)
	{
		//創建節點
		root = new TreeNode(num,1);
		//返回樹高
		return 1;
	}
	int lHeight = getHeight(root->left), rHeight = getHeight(root->right);
	//左子樹
	if (num < root->num)
	{
		//添加節點
		lHeight = addNode(root->left, num);
		//修改父節點
		root->left->parent = root;
	}
	//右子樹
	else
	{
		//添加節點
		rHeight = addNode(root->right, num);
		//修改父節點
		root->right->parent = root;
	}

	//調整樹
	if (abs(lHeight - rHeight) > 1)
	{
		if (lHeight> rHeight)
		{
			if (getHeight(root->left->left) > getHeight(root->left->right))
				condition1(root);
			else
				condition3(root);
		}
		else
		{
			if (getHeight(root->right->right) > getHeight(root->right->left))
				condition2(root);
			else
				condition4(root);
		}
	}
	lHeight = getHeight(root->left);
	rHeight = getHeight(root->right);
	return root->height = max(lHeight , rHeight) + 1;
}

int moveNode(TreeNode*& root)
{
	if (root == nullptr)
		return 0;
	TreeNode*& parent = root;
	int lHeight = getHeight(root->left), rHeight = getHeight(root->right);
	if (root->left != nullptr || root->right != nullptr)
	{
		//將右邊提上來,沒有右邊就提左邊
		
		if (root->right != nullptr)
		{
			root->num = root->right->num;
			rHeight = moveNode(root->right);

		}
		else if (root->left != nullptr)
		{
			root->num = root->left->num;
			lHeight = moveNode(root->left);
		}
		return root->height = max(rHeight, lHeight) + 1;
	}
	else
	{
		//刪除parent
		if (parent != nullptr)
		{
			delete parent;
			parent = nullptr;
			return 0;
		}
	}
}

int deleteNode(TreeNode*& root, int num)
{
	if (root == nullptr)
		return 0;
	//刪除
	TreeNode* parent = nullptr;
	//獲取當前樹的高度
	int lHeight = getHeight(root->left), rHeight = getHeight(root->right);
	if (num > root->num)
		rHeight = deleteNode(root->right,num);
	else if (num < root->num)
		lHeight = deleteNode(root->left, num);
	else if (root->num == num)
		moveNode(root);


	//調整樹
	if (abs(lHeight - rHeight) > 1)
	{
		if (lHeight > rHeight)
		{
			if (getHeight(root->left->left) > getHeight(root->left->right))
				condition1(root);
			else
				condition3(root);
		}
		else
		{
			if (getHeight(root->right->right) > getHeight(root->right->left))
				condition2(root);
			else
				condition4(root);
		}
	}

	//重新計算樹的高度
	if (root != nullptr)
	{
		lHeight = getHeight(root->left);
		rHeight = getHeight(root->right);
		return root->height = max(lHeight, rHeight) + 1;
	}
	else
	{
		lHeight = 0;
		rHeight = 0;
		return 0;
	}
	
	
}
int main()
{
	TreeNode* root = nullptr;
	addNode(root,12);
	addNode(root, 5);
	addNode(root, 15);
	addNode(root,3);
	addNode(root, 8);
	addNode(root, 9);
	addNode(root, 6);
	addNode(root, 20);
	//addNode(root, 21);
	
	deleteNode(root, 20);
	deleteNode(root, 15);
	deleteNode(root, 9);
	deleteNode(root, 12);
	deleteNode(root, 3);
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章