1. 程式人生 > >C++實現二叉排序樹BSTree --插入刪除摧毀查詢等操作

C++實現二叉排序樹BSTree --插入刪除摧毀查詢等操作

#ifndef _BSTREE_H
#define _BSTREE_H

#include <iostream>
#include <assert.h>
using namespace std;

template <typename T>
class BSTree;

template <typename T>
class TreeNode{
	friend class BSTree<T>;
public:
	TreeNode() : m_data(T()), leftChild(NULL), rightChild(NULL)
	{}
	TreeNode(T data, TreeNode<T> *left = NULL, TreeNode<T> *right = NULL)
			: m_data(data), leftChild(left), rightChild(right)
	{}
	~TreeNode() = default;
private:
	T m_data;
	TreeNode<T> *leftChild;
	TreeNode<T> *rightChild;
};

template <typename T>
class BSTree{
	typedef TreeNode<T> node_type;
public:
	BSTree() :root(NULL)
	{}
	~BSTree();
public:
	BSTree<T>& operator=(const BSTree<T>&);

	void insert_elem(const T&);
	bool remove_elem(const T&);
	void inorder_traverse()const;

	T find_max()const;
	T find_min()const;
	node_type *search_elem(const T&)const;
protected:
	node_type *copy_tree(node_type *);

	void insert_elem(node_type *&, const T&);
	bool remove_elem(node_type *&, const T&);
	void inorder_traverse(node_type *)const;
	void destroy_tree(node_type *&);

	T find_max(node_type *)const;
	T find_min(node_type *)const;
	node_type *search_elem(node_type *, const T&)const;
private:
	node_type *root;
};

//public interface 

template <typename T>
BSTree<T>& BSTree<T>::operator=(const BSTree<T>& bst)
{
	if(this != &bst){
		root = copy_tree(bst.root);
	}
	return *this;
}

template <typename T>
BSTree<T>::~BSTree()
{
	destroy_tree(root);
}

template <typename T>
void BSTree<T>::insert_elem(const T& val)
{
	insert_elem(root, val);
}

template <typename T>
bool BSTree<T>::remove_elem(const T& val)
{
	remove_elem(root, val);
}

template <typename T>
void BSTree<T>::inorder_traverse()const
{
	inorder_traverse(root);
}

template <typename T>
T BSTree<T>::find_max()const
{
	return find_max(root);
}

template <typename T>
T BSTree<T>::find_min()const
{
	return find_min(root);
}

template <typename T>
TreeNode<T>* BSTree<T>::search_elem(const T& target)const
{
	search_elem(root, target);
}

//protected interface

template <typename T>
TreeNode<T>* BSTree<T>::copy_tree(node_type *t)
{
	node_type *tmp;
	if(t != NULL){
		tmp = new node_type(t->m_data);
		tmp->leftChild = copy_tree(t->leftChild);  //不能用tmp = copy_tree(t->leftChild)這樣會導致新生成二叉樹只掛有一個根節點
		tmp->rightChild = copy_tree(t->rightChild);
	}
	return tmp;
}

template <typename T>
void BSTree<T>::insert_elem(node_type *&t, const T& val)
{
	if(t == NULL){
		t = new node_type(val);
		return ;
	}
	
	if(t->m_data > val)
		insert_elem(t->leftChild, val);
	else if(t->m_data < val)
		insert_elem(t->rightChild, val);
	else 
		return ;
}

template <typename T>
void BSTree<T>::inorder_traverse(node_type *t)const
{	
	if(t != NULL){
		inorder_traverse(t->leftChild);
		cout << t->m_data << " ";
		inorder_traverse(t->rightChild);
	}
}

template <typename T>
bool BSTree<T>::remove_elem(node_type *&t, const T& val)
{
	if(t == NULL)
		return false;

	if(t->m_data > val)
		remove_elem(t->leftChild, val);
	else if(t->m_data < val)
		remove_elem(t->rightChild, val);
	else{
		if(t->leftChild != NULL && t->rightChild != NULL){
			node_type *tmp = t;
			tmp = t->rightChild;
			while(tmp->leftChild != NULL)
				tmp = tmp->leftChild; //選擇右子樹的最左邊葉子結點替換方式
			t->m_data = tmp->m_data;
			remove_elem(t->rightChild, t->m_data);
			//delete tmp;           //error,此處不能直接delete,否則只能釋放該節點,但該節點仍舊連結在二叉樹上,需通過t指標釋放並更改二叉樹,另外一個原因是如果tmp元素有一個孩子,Remove遞迴會呼叫刪除有一個孩子節點的情況,下面的else。例:上面圖中38元素若存在一個右孩子39元素,就屬於此類情況
		}
		else{
			node_type *tmp = t;
			if(t->leftChild != NULL)
				t = t->leftChild;
			else 
				t = t->rightChild;
			delete tmp;
		}
		return true;
	}
}

template <typename T>
void BSTree<T>::destroy_tree(node_type *&t)
{
	if(t != NULL){
		destroy_tree(t->rightChild);
		destroy_tree(t->leftChild);
		delete t;
	}
}

template <typename T>
T BSTree<T>::find_max(node_type *t)const
{
	while(t->leftChild != NULL)
		t = t->leftChild;
	return t->m_data;
}

template <typename T>
T BSTree<T>::find_min(node_type *t)const
{
	while(t->rightChild != NULL)
		t = t->rightChild;
	return t->m_data;
}

template <typename T>
TreeNode<T>* BSTree<T>::search_elem(node_type *t, const T& target)const
{
	if(t == NULL)
		return NULL;	
	else if(t->m_data > target)
		search_elem(t->leftChild, target);
	else if(t->m_data < target)
		search_elem(t->rightChild, target);
	else
		return t;
}

#endif /*BSTree.h*/