1. 程式人生 > >【資料結構】平衡二叉樹[AVL樹](二)——刪除

【資料結構】平衡二叉樹[AVL樹](二)——刪除

前面介紹了平衡二叉樹的插入操作:平衡二叉樹的插入,這裡來介紹平衡二叉樹的刪除,平衡二叉樹是一棵帶有平衡條件的二叉查詢樹,其刪除操作是在二叉查詢樹的基礎上新增平衡調整演算法。

先看一下示意圖()

/*二叉查詢樹的性質讓我們可以很方便的查詢最小最大鍵值*/
/*查詢最小鍵值節點:直接遞迴遍歷左子樹葉子節點*/
AvlNode* AvlTree::findMin(AvlNode *node)
{
	if (NULL == node)
		return NULL;

	else if (NULL == node->leftchild)
		return node;

	else
		return findMin(node->leftchild);
}

/*非遞迴實現查詢最大鍵值節點*/
AvlNode* AvlTree::findMax(AvlNode *node)
{
	if (node != NULL)
	{
		while (node->rightchild)
			node = node->rightchild;
	}

	return node;
}

void AvlTree::Delete(int val)
{
	if(NULL == Root)
		return;
	else
		Delete(Root, val);
}

//節點的刪除就是不斷的交換資料,更改刪除節點,最後定位到葉子節點
//
void AvlTree::Delete(AvlNode *&node, int val)
{
	AvlNode *tempnode = NULL;
	if(NULL == node)
		return;

	else if(val < node->data)
		Delete(node->leftchild, val);
	else if(val > node->data)
		Delete(node->rightchild, val);

	//find the val
	else if(node->leftchild && node->rightchild)
	{
		tempnode = findMin(node->rightchild);
		node->data = tempnode->data;
		Delete(node->rightchild, node->data);   //理解!待刪除節點鍵值變換
	}                                           //此後要刪除的鍵值節點不是val
	else
	{
		if(node->leftchild && (NULL == node->rightchild))
		{
			tempnode = findMax(node->leftchild);
			node->data = tempnode->data;
			Delete(node->leftchild, node->data);
		}
		else if (node->rightchild && (NULL == node->leftchild))
		{
			tempnode = findMin(node->rightchild);
			node->data = tempnode->data;
			Delete(node->rightchild, node->data);
		}
		else
		{
			delete(node);
			node = NULL;
		}
	}

	if (node)   //必須新增這個條件,利用遞迴的力量,調整平衡
	{  
		//平衡判斷
		if (2 == Height(node->leftchild) - Height(node->rightchild))
		{
			//情況判斷
			if (Height(node->leftchild->leftchild) >= Height(node->leftchild->rightchild))
				RotationLeftOnce(node);
			else
			{
				RotationRightOnce(node->leftchild);
				RotationLeftOnce(node);
			}
		}

		if (2 == Height(node->rightchild) - Height(node->leftchild))
		{
			if (Height(node->rightchild->rightchild) >= Height(node->rightchild->leftchild))
				RotationRightOnce(node);
			else
			{
				RotationLeftOnce(node->rightchild);
				RotationRightOnce(node);
			}
		}
	}
}

上面的刪除操作具體參見:二叉查詢樹的刪除,另外平衡二叉樹的查詢,遍歷與二叉查詢樹一樣。

二、清空二叉樹(解構函式)

void AvlTree::MakeEmpty(AvlNode *&node)
{
	if (node)
	{
		MakeEmpty(node->leftchild);
		MakeEmpty(node->rightchild);
		delete node;
	}
	node = NULL;
}
三、平衡二叉樹時間複雜度分析

平衡二叉樹在二叉查詢樹的基礎上添加了旋轉演算法,但是旋轉操作僅僅改變少數指標的指向,耗費常數時間,平衡二叉樹加入了平衡機制,所以其深度為logN,查詢、插入和刪除在平均和最壞情況下都是O(logN)。對比二叉查詢樹,時間上穩定了很多。