數據結構:二叉搜索樹(Binary Search Tree)

Binary Search Tree(BST)

創作人:ZJUT_YC
測試代碼還沒有加上,後續補齊。

代碼實現

#pragma once
#include <iostream>
using namespace std;

template<class T>
class BST
{
private:
	class Node {
		T m_data;
		Node* m_left;
		Node* m_right;
	};
	Node* m_root;
public:
	bool isEmpty()const;
	bool searchRecursive(const T& item);// 查找某個元素是否在樹中(遞歸版本)
	bool searchNonRecursive(const T& item); // 查找某個元素是否在樹中(非遞歸版本)
	void insert(const T& item);// 將元素插入到二叉樹中
	void remove(const T& item);// 將元素從二叉樹中刪除
	void inOrder(ostream& os);//遍歷樹的方式:中序遍歷
	void leftOrder(ostream& os);//遍歷樹的方式:前序遍歷
	void rightOrder(ostream& os);//遍歷樹的方式:後續遍歷
private:
	bool searchAux(BST<T>::Node* subRoot,const T& item)const; // 查找輔助函數 
	void inOrderAux(ostream& os, BST<T>::Node* subRoot)const; // 中序遍歷Aux
	void leftOrderAux(ostream& os, BST<T>::Node* subRoot)const;// 前序遍歷Aux
	void rightOrderAux(ostream& os, BST<T>::Node* subRoot)const;// 後序遍歷Aux
};

template<class T>
inline bool BST<T>::isEmpty() const
{
	return m_root==nullptr;
}

template<class T>
inline bool BST<T>::searchRecursive(const T& item)
{
	return searchAux(m_root,item);
}

template<class T>
inline bool BST<T>::searchNonRecursive(const T& item)
{
	BST<T>::Node* localptr = m_root;
	while (nullptr != localptr) {
		if (item < localptr->m_data) {
			localptr = localptr->m_left;
		}
		else if (item > localptr->m_data) {
			localptr = localptr->m_right;
		}
		else {
			return true;
		}
	}
	return false;
}

// 二叉樹的插入
template<class T>
inline void BST<T>::insert(const T& item)
{
	BST<T>::Node* ptr = m_root;
	BST<T>::Node* parent=nullptr;
	bool found = false;
	while (!found && ptr!=nullptr) {
		parent = ptr;
		if (item < ptr->m_data)
			ptr = ptr->left;
		else if(item > ptr->right)
			ptr = ptr->right;
		else
			found = true;
	}//1. 先判斷元素item在不在二叉樹中

	// 2. 元素在樹中與否執行相應的操作
	if (found)// 2.1 元素在樹中
		std::cout << "item" << item << " has already exist!\n";
	else {
		// 2.2 元素不在二叉樹中,則插入元素
		// 插入時區分是否爲空樹
		BST<T>::Node* newNode = new BST<T>::Node(item);
		if (parent == nullptr) //一顆空的樹
			m_root = newNode;
		if (item<parent->m_data)
		{
			parent->left = item;
		} 
		else
		{
			parent->right = item;
		}
	}
}

template<class T>
inline void BST<T>::remove(const T& item)
{
	BST<T>::Node* localptr = m_root;
	BST<T>::Node* parent_of_localptr = nullptr;
	bool leftNode = true;
	while (nullptr != localptr) {
		parent_of_localptr = localptr; // localptr的父節點
		if (item < localptr->m_data) {
			localptr = localptr->m_left;
			leftNode = true;
		}
		else if(item>localptr->m_data){
			localptr = localptr->m_right;
			leftNode = false;
		}
		else {
			break; // 此時localptr保存的是item所在元素的值
		}
	}

	if (nullptr == localptr) {
		return; // 表示沒有這個元素
	}
	else { // 在BST中找到元素item
		// 分情況討論
		// 1.localptr指向的節點是葉子節點
		if (localptr->m_left == nullptr && localptr->m_right == nullptr) {
			if (leftNode) {
				parent_of_localptr->m_left = nullptr;
				delete localptr;  // 將空間釋放,當然也可以將參數放在函數的參數列表中,由外層進行釋放
			}
			else {
				parent_of_localptr->m_right = nullptr;
				delete localptr;
			}
		}
		// 2.1 localptr指向的節點只有一個子節點,且爲右子節點
		if (localptr->m_left == nullptr && localptr->m_right != nullptr) {
			if (leftNode) { // localptr是parent的左子節點
				parent_of_localptr->m_left = localptr->m_right;
			}
			else
			{
				parent_of_localptr->m_right = localptr->m_right;
			}
			// 將待刪除節點和其子節點解綁,回收內存
			localptr->m_right = nullptr;
			delete localptr; //想象一下刪除的過程
		}
		// 2.2 localptr指向的節點只有一個子節點,且爲左子節點
		if (localptr->m_left != nullptr && localptr->m_right == nullptr) {
			if (leftNode)
				parent_of_localptr->m_left = localptr->m_left;
			else
				parent_of_localptr->m_right = localptr->m_left;

			localptr->m_left = nullptr;
			delete localptr;
		}
		// 3.localptr指向的節點有兩個子節點
		if (localptr->m_left!=nullptr && localptr->m_right!=nullptr) {
			BST<T>::Node* ptr = localptr->m_right;
			BST<T>::Node* ptr_parent = localptr;
			bool noLeftNodeOfLocalptrRight = true;
			while (nullptr != ptr->m_left) {
				noLeftNodeOfLocalptrRight = false;
				ptr_parent = ptr;
				ptr = ptr->m_left;
			}

			// 待刪除節點的右子節點沒有左子節點,即localptr->m_right->left=nullptr
			if (noLeftNodeOfLocalptrRight) { // localptr->m_right沒有左子樹
				localptr->m_right->left = localptr->m_left;
				localptr->m_leftptr=localptr->m_right = nullptr;
				delete localptr;
			}
			else { // localptr->m_right有左子節點,成功到達其左子樹,ptr表示後驅節點,parent是ptr的父節點
				localptr->m_data = ptr->m_data; // 待刪除節點不需要刪除,只要將其值改爲其後驅節點的值即可
				// ptr存在右子節點
				if (ptr->m_right != nullptr) { // 後驅節點沒有左子節點:由它的定義決定的
					ptr_parent->m_left = ptr->m_right;
					ptr->m_right = nullptr; //將後驅節點和它的右子節點解綁
					delete ptr;
				}
				else {//ptr不存在右子節點
					ptr_parent->m_left = nullptr;
					delete ptr;
				}
			}
		}
	}
}

template<class T>
inline void BST<T>::inOrder(ostream& os)
{
	inOrderAux(os, m_root);
}

template<class T>
inline void BST<T>::leftOrder(ostream& os)
{
	leftOrderAux(os, m_root);
}

template<class T>
inline void BST<T>::rightOrder(ostream& os)
{
	rightOrderAux(os, m_root);
}


template<class T>
inline bool BST<T>::searchAux(BST<T>::Node* subRoot, const T& item) const
{
	if (subRoot == nullptr) return false;
	if (subRoot != nullptr) {
		if (item > subRoot->m_data) {
			searchAux(subRoot->m_right, item);
		}
		else if (item < subRoot->m_data) {
			searchAux(subRoot->m_left, item);
		}
		else {
			return true;
		}
	}
}

// 中序遍歷Aux
template<class T>
inline void BST<T>::inOrderAux(ostream& os, BST<T>::Node* subRoot) const
{
	if (subRoot != nullptr) {
		inOrderAux(os, subRoot->left);
		os << subRoot->m_data << "  ";
		inOrderAux(os, subRoot->right);
	}
	
}

//前序遍歷Aux
template<class T>
inline void BST<T>::leftOrderAux(ostream& os, BST<T>::Node* subRoot) const
{
	if (subRoot != nullptr) {
		std::cout << subRoot->data;
		leftOrderAux(os, subRoot->left);
		leftOrderAux(os, subRoot->right);
	}
}

//後序遍歷Aux
template<class T>
inline void BST<T>::rightOrderAux(ostream& os, BST<T>::Node* subRoot) const
{
	if (subRoot != nullptr) {
		rightOrderAux(os, subRoot->left);
		rightOrderAux(os, subRoot->right);
		std::cout << subRoot->m_data << "  ";
	}
}

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