二叉排序樹的創建,插入,遍歷,節點刪除,整個刪除的封裝

#include<iostream>
using namespace std;

typedef struct BSTree
{
	int key;
	struct BSTree *LChild , *RChild;
}BSTree;

class CBSTree
{
private:
	BSTree *root;	//二叉排序樹的根節點,可以代表一個樹
	bool SearchKey(int key,BSTree **node,BSTree *root,BSTree *Father);
	void traverse(BSTree *root2);
	bool DeleteKey(int key,BSTree **root);
public:
	CBSTree();
	~CBSTree();
	bool search(int key, BSTree**node,BSTree *Father); //對SearchKey 函數的一個封裝,減少參數
	bool InsertKey( int key);
	void Traverse();	//對遍歷函數traverse的一個封裝,減少參數
	void CreateBSTree(int data[],int length);
	void DeleteCBSTree(BSTree **root);
	void DeleteOperation(BSTree **node);
	bool DeleteKeyEx(int key);	// 對DeleteKey的一個封裝減少參數
};

CBSTree::CBSTree()
{
	root = NULL;	//對樹進行初始化,爲空樹
}

CBSTree::~CBSTree()
{
	DeleteCBSTree(&root);
}

bool CBSTree::SearchKey(int key,BSTree **node,BSTree *root,BSTree *Father)
{
	if(!root)	//如果爲空
	{
		*node = Father;
		return false;
	}
	else
	{
		if(key > root->key)
		{
			Father = root;
			return SearchKey( key, node,root->RChild, root);
		}
		else if(key < root->key)
		{
			Father = root;
			return SearchKey(key , node, root->LChild, root);
		}
		else
		{
			*node = root;	//把root指針的地址數據傳給node,這樣函數外部node對應的變量就能獲取當前root本身,而不是副本
			return true;
		}
	}
}

void CBSTree::traverse(BSTree *root2)
{
	if(root2)
	{
		traverse(root2->LChild);
		cout << root2->key <<" ";
		traverse(root2->RChild);
	}
}

bool CBSTree::search(int key, BSTree**node,BSTree *Father = NULL)
{
	return SearchKey(key,node,root,Father);
}

bool CBSTree::InsertKey( int key)	
{
	if(!this->root)	//先判斷當前root是否爲空,爲空就把root作爲根節點,左右孩子爲空
	{
		this->root = new BSTree;
		this->root->key = key;
		this->root->LChild = NULL;
		this->root->RChild = NULL;
		return true;
	}
	else	//root不爲空
	{
		BSTree *temp = NULL;	//temp保存search到的key對應的節點指針,如果沒有search到則保存沿着路線查找的最後一個節點
		if(search(key,&temp))
		{
			cout << key << "已經存在"<< endl;
			return false;
		}
		else
		{
			if(key > temp->key)
			{
				temp->RChild = new BSTree;
				temp->RChild->key = key;
				temp->RChild->LChild = NULL;
				temp->RChild->RChild = NULL;
				return true;
			}
			else
			{
				temp->LChild = new BSTree;
				temp->LChild->key = key;
				temp->LChild->LChild = NULL;
				temp->LChild->RChild = NULL;
				return true;
			}
		}
	}
}

void CBSTree::Traverse()	//對遍歷函數traverse的一個封裝,減少參數
{
	traverse(root);
}
void CBSTree::CreateBSTree(int data[],int length)	//創建二叉排序樹的過程就是把一次次插入新節點的過程
{
	for(int i = 0; i < length; i++)
	{
		InsertKey(data[i]);
	}
}
void CBSTree::DeleteCBSTree(BSTree **root)	//刪除整個樹
{
	if(*root)
	{
		DeleteCBSTree(&(*root)->LChild);
		DeleteCBSTree(&(*root)->RChild);
		delete *root;
		*root = NULL;

	}
}

void CBSTree::DeleteOperation(BSTree **node)	//刪除某個指針對應節點的具體操作
{
	if(!(*node)->LChild && !(*node)->RChild)	//如果該節點沒有左右孩子,則直接刪除,並複製爲空
	{
		delete(*node);		//關鍵點是該函數傳進來的參數*node必須是root這個二叉樹內的真實節點,非拷貝
		*node = NULL;	//因爲要對root內部的真實節點進行操作
	}
	else if((*node)->LChild && !(*node)->RChild)	//如果只有左孩子
	{
		BSTree *temp = *node;
		(*node) = (*node)->LChild;	//則把指向該節點的指針指向節點左孩子
		delete temp;
	}
	else if((*node)->RChild && !(*node)->LChild)	//如果只有右孩子,參考上面
	{
		BSTree *temp = (*node)->RChild;
		delete (*node);
		(*node) = temp;

	}
	else	//如果左右孩子都有
	{
		BSTree*temp = (*node)->RChild;
		while(temp->LChild->LChild)	//尋找*node右子樹下最靠左的葉子節點也就是最小的節點,也就是中序遍歷下*node的後繼,獲取它的父節點
		{
			temp = temp->LChild;	//關鍵點:如果不獲取父節點,而是直接獲取最小節點的話,temp存儲的是該節點的一個拷貝,不能直接進行操作
		}
		(*node)->key = temp->LChild->key;	//通過最小節點的父節點temp指向最小節點這個不是拷貝,而是直接操作了root裏的節點
		DeleteOperation(&temp->LChild);
	}
}

bool CBSTree::DeleteKey(int key,BSTree **root)	//找到要刪除的節點的指針,調用具體操作的函數刪除
{
	if(!*root)	//如果爲空
	{
		cout << "未找到" << key << endl;
		return false;
	}
	else
	{
		if(key > (*root)->key)
		{
			return DeleteKey( key,&(*root)->RChild);
		}
		else if(key < (*root)->key)
		{
			return DeleteKey(key , &(*root)->LChild);
		}
		else
		{
			DeleteOperation(&*root);
			return true;
		}
	}
}

bool CBSTree::DeleteKeyEx(int key)
{
	return DeleteKey(key,&root);
} 

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