C++實現二叉排序樹BSTree --插入刪除摧毀查詢等操作
阿新 • • 發佈:2019-02-01
#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*/