二叉搜索树的详细实现

来源:互联网 发布:哈尔滨软件开发 编辑:程序博客网 时间:2024/06/05 06:49

  本代码实现了:

  1. 插入
  2. 删除
  3. 非递归的中序遍历、前序遍历、后序遍历
  4. 从前序遍历与中序遍历中恢复二叉树
  本代码在 Clang 3.6 for Windows 与 Visual Studio 2015 CTP 6 下编译通过。头文件无警告。
//BinarySearchTree.h#pragma once#include <new>#include <vector>#include <stack>#include <algorithm>template<typename Type>class BinarySearchTree{template<typename ValueType>struct TreeNode{ValueType value;TreeNode* leftPtr;TreeNode* rightPtr;TreeNode* parentPtr;};public:using value_type = Type;using pointer = value_type*;using reference = value_type&;using tree_type = BinarySearchTree<value_type>;using node_type = TreeNode<value_type>;using node_pointer = node_type*;using container_type = std::vector<value_type>;using container_iterator_type = typename container_type::const_iterator;//ADTBinarySearchTree(){headPtr = nullptr;}~BinarySearchTree(){Clear(headPtr);headPtr = nullptr;}BinarySearchTree(const tree_type& rhs){headPtr = CopyNode(rhs.headPtr,nullptr);}BinarySearchTree(tree_type&& rhs){headPtr = rhs.headPtr;rhs.headPtr = nullptr;}void swap(const tree_type& rhs){std::swap(headPtr, rhs.headPtr);}tree_type& operator= (const tree_type& rhs){if (this != &rhs){this->~BinarySearchTree();headPtr = CopyNode(rhs.headPtr, nullptr);}return *this;}tree_type& operator= (tree_type&& rhs){headPtr = rhs.headPtr;rhs.headPtr = nullptr;return *this;}node_pointer find(const value_type& _value){auto findPtr = headPtr;while (findPtr != nullptr && GetValue(findPtr)!=_value){if (_value < GetValue(findPtr)) findPtr = GetLeftChild(findPtr);else findPtr = GetRightChild(findPtr);}return findPtr;}node_pointer insert(const value_type& _value){if (headPtr == nullptr){headPtr = GetNoChildrenNode();new (&GetValue(headPtr)) value_type(_value);new (&GetParent(headPtr)) node_pointer(nullptr);return headPtr;}else{node_pointer parentPtr = nullptr;node_pointer childPtr = headPtr;bool isLeft = false;while (childPtr!=nullptr){parentPtr = childPtr;if (_value < GetValue(childPtr)){childPtr = GetLeftChild(childPtr);isLeft = true;}else{childPtr = GetRightChild(childPtr);isLeft = false;}}childPtr = GetNoChildrenNode(_value);auto tempPtr = isLeft ? &(GetLeftChild(parentPtr)) : &(GetRightChild(parentPtr));new (tempPtr) node_pointer(childPtr);new (&GetParent(childPtr)) node_pointer(parentPtr);return childPtr;}}void erase(const value_type& _value){auto deletePtr = find(_value);if (GetLeftChild(deletePtr) == nullptr){Transplant(deletePtr, GetRightChild(deletePtr));}else if (GetRightChild(deletePtr) == nullptr){Transplant(deletePtr,  GetLeftChild(deletePtr));}else{// two childrennode_pointer minPtr = GetMinimum(GetRightChild(deletePtr));if (minPtr != GetRightChild(deletePtr)){Transplant(minPtr, GetRightChild(minPtr));GetRightChild(minPtr) = GetRightChild(deletePtr);GetParent(GetRightChild(minPtr)) = minPtr;}Transplant(deletePtr, minPtr);GetLeftChild(minPtr) = GetLeftChild(deletePtr);GetParent(GetLeftChild(minPtr)) = minPtr;}GetValue(deletePtr).~value_type();delete deletePtr;}void insert(std::initializer_list<value_type> iList){for (auto&& v: iList){insert(v);}}container_type preorder_tree_walk() const{container_type resContainer;if (headPtr != nullptr){node_pointer tempPtr;std::stack<node_pointer> pointerStack;pointerStack.push(headPtr);while (!pointerStack.empty()){tempPtr = pointerStack.top();resContainer.push_back(GetValue(tempPtr));pointerStack.pop();if(GetRightChild(tempPtr)) pointerStack.push(GetRightChild(tempPtr));if(GetLeftChild(tempPtr)) pointerStack.push(GetLeftChild(tempPtr));}}return resContainer;}container_type inorder_tree_walk() const{container_type resContainer;if (headPtr != nullptr){std::stack<node_pointer> pointerStack;node_pointer tempPtr = headPtr;while (tempPtr|| !pointerStack.empty()){if (GetLeftChild(tempPtr)){pointerStack.push(tempPtr);tempPtr = GetLeftChild(tempPtr);}else{resContainer.push_back(GetValue(tempPtr));tempPtr = GetRightChild(tempPtr);while (!tempPtr && !pointerStack.empty()){tempPtr = pointerStack.top();resContainer.push_back(GetValue(tempPtr));tempPtr = GetRightChild(tempPtr);pointerStack.pop();}}}}return resContainer;}container_type postorder_tree_walk() const{using node_info_type = std::pair<node_pointer, bool>;//true indicates "its right child has been visited"container_type resContainer;if (headPtr != nullptr){node_pointer tempPtr = headPtr;std::stack<node_info_type> pointerStack;node_info_type tempInfo;while (tempPtr){pointerStack.push({ tempPtr,false });tempPtr = GetLeftChild(tempPtr);}while (!pointerStack.empty()){tempInfo = pointerStack.top();if (GetRightChild(tempInfo.first) == nullptr || tempInfo.second == true){resContainer.push_back(GetValue(tempInfo.first));pointerStack.pop();}else{pointerStack.top().second = true;tempPtr = GetRightChild(tempInfo.first);while (tempPtr){pointerStack.push({ tempPtr,false });tempPtr = GetLeftChild(tempPtr);}}}}return resContainer;}static tree_type get_tree_from_pre_in(const container_type& preContainer,const container_type& inContainer){auto beginIter = std::begin(preContainer);auto head = ResumeTree(beginIter, std::end(preContainer),std::begin(inContainer), std::end(inContainer),nullptr);return tree_type(head);}private:node_pointer headPtr;BinarySearchTree(node_pointer _head){headPtr = _head;}static node_pointer ResumeTree(container_iterator_type& preBegin, container_iterator_type preEnd,container_iterator_type inBegin, container_iterator_type inEnd,node_pointer parentPtr){if (inBegin != inEnd && preBegin != preEnd ){auto it = std::find(inBegin, inEnd, *preBegin);auto nodePtr = tree_type::AllocateNode();new (&GetValue(nodePtr)) value_type(*preBegin);new (&GetParent(nodePtr)) node_pointer(parentPtr);new (&GetLeftChild(nodePtr)) node_pointer(ResumeTree(++preBegin, preEnd, inBegin, it,nodePtr));if(--preBegin != preEnd)new (&GetRightChild(nodePtr)) node_pointer(ResumeTree(++preBegin, preEnd, ++it, inEnd,nodePtr));return nodePtr;}else return nullptr;}static node_pointer& GetLeftChild(node_pointer p) noexcept{return p->leftPtr;}static node_pointer& GetRightChild(node_pointer p) noexcept{return p->rightPtr;}static node_pointer& GetParent(node_pointer p) noexcept{return p->parentPtr;}static reference GetValue(node_pointer p) noexcept{return p->value;}static node_pointer AllocateNode(){return static_cast<node_pointer>(::operator new(sizeof(node_type)));}node_pointer GetNoChildrenNode() const{auto ptr = AllocateNode();new (&GetLeftChild(ptr)) node_pointer(nullptr);new (&GetRightChild(ptr)) node_pointer(nullptr);return ptr;}node_pointer GetNoChildrenNode(const value_type& _value) const{auto ptr = GetNoChildrenNode();new (&GetValue(ptr)) value_type(_value);return ptr;}void Transplant(node_pointer des, node_pointer source) noexcept{if (GetParent(des) == nullptr) headPtr = source;else if (GetLeftChild(GetParent(des)) == des){//des is leftGetLeftChild(GetParent(des)) = source;}else GetRightChild(GetParent(des)) = source;if(source != nullptr) GetParent(source) = GetParent(des);}node_pointer GetMinimum(node_pointer p) const noexcept{while (GetLeftChild(p)!=nullptr){p = GetLeftChild(p);}return p;}void Clear(node_pointer p){if (p == nullptr) return;else{Clear(GetLeftChild(p));Clear(GetRightChild(p));GetValue(p).~value_type();delete p;}}node_pointer CopyNode(node_pointer p,node_pointer parentPtr){if (p == nullptr) return nullptr;auto nodePtr = AllocateNode();new (&GetValue(nodePtr)) value_type(GetValue(p));new (&GetParent(nodePtr)) node_pointer(parentPtr);new (&GetLeftChild(nodePtr)) node_pointer(CopyNode(GetLeftChild(p),nodePtr));new (&GetRightChild(nodePtr)) node_pointer(CopyNode(GetRightChild(p),nodePtr));return nodePtr;}};

//main.cpp#include "BinarySearchTree.h"#include <iostream>//struct Helper//{//~Helper()//{//_CrtDumpMemoryLeaks();//}//};//Helper h;int main(){BinarySearchTree<int> bst;bst.insert({ 6,2,8,1,4,3 });auto ptr = bst.find(10);bst.erase(6);auto v = bst.preorder_tree_walk();auto v2 = bst.inorder_tree_walk();auto v3 = bst.postorder_tree_walk();auto bst2 = BinarySearchTree<int>::get_tree_from_pre_in(v, v2);auto bst3 = bst2;for (auto& x : v) std::cout << x << " ";return 0;}


0 0
原创粉丝点击