1. 程式人生 > >BinarySearchTree ----資料結構與演算法分析第四版的

BinarySearchTree ----資料結構與演算法分析第四版的

/*************************************************************************
	> File Name: BinarySearchTree.h
	> Author:keson 
	> Mail:[email protected] 
	> Created Time: 2014年11月22日 星期六 21時11分46秒
 ************************************************************************/

#ifndef _BINARYSEARCHTREE_H
#define _BINARYSEARCHTREE_H

#include"dsexceptions.h"
#include<algorithm>
using namespace std;

//BinarySearchTree class
//
//CONSTRUCTOR: zero parameter
//
//***************PUBLIC OPERATIONS********************
//void insert(x)           -->Insert x
//void remove(x)           -->Remove x
//bool contains(x)         -->Return true if x is present
//Comparable findMin()     -->Return smallest item
//Comparable findMax()     -->return largest item
//boolean isEmpty()        -->return true if empty.else false
//void makeEmpty()         -->Remove all items
//void printTree()         -->Print tree in sorted order
//***************ERRORS*******************************

template<typename Comparable>
class BinarySearchTree
{
public:
    //constructor
    BinarySearchTree():root(nullptr) {}

    //copy constructor
    BinarySearchTree(const BinarySearchTree &rhs)
    {
        root=clone(rhs.root);
    }

    //move constructor
    BinarySearchTree(BinarySearchTree &&rhs);
    //Deconstructor
    ~BinarySearchTree()
    {
        makeEmpty();
    }

    const Comparable& findMin() const
    {
        if(isEmpty())
            throw UnderflowException{};
        return findMin(root)->element;
    }

    const Comparable& findMax() const
    {
        if(isEmpty())
           throw UnderflowException{};
        return findMax(root)->element;
    }

    bool contains(const Comparable &x)const 
    {
        return contains(x,root);
    }

    bool isEmpty() const
    {
        return root==nullptr;
    }

    void printTree(ostream &out=cout) const
    {
        if (isEmpty())
           out<<"Empty tree"<<endl;
        else
           printTree(root,out);
    }

    void makeEmpty()
    {
        makeEmpty(root);
    }

    /**
     * Insert x into the tree ,duplicates are ignored.
     */
    void insert(const Comparable &x)
    {
        insert(x,root);
    }

    void insert(Comparable &&x)
    {
        insert(std::move(x),root);
    }

    /**
     * Remove x from the tree.Nothing is done if x is not found
     */
    void remove(const Comparable &x)
    {
        remove(x,root);
    }

    
    //copy assignment
    BinarySearchTree &operator=(const BinarySearchTree &rhs)
    {
        BinarySearchTree copy=rhs;
        std::swap(*this,copy);
        return *this;
    }

    //move assignment
    BinarySearchTree &operator=(BinarySearchTree &&rhs)
    {
        std::swap(root,rhs.root);
        return *this;
    }

private:
    struct BinaryNode
    {
        Comparable element;
        BinaryNode *left;
        BinaryNode *right;
        
        //constructor
        BinaryNode(const Comparable &theElement,BinaryNode *lt,BinaryNode *rt)
        :element{theElement},left{lt},right{rt} {}

        //move constructor
        BinaryNode(Comparable &&theElement,BinaryNode *lt,BinaryNode *rt)
        :element{std::move(theElement)},left{lt},right{rt} {}
    };

    BinaryNode *root;

    /**
     * Internal method to insert into a subtree.
     * x is the item to insert.
     * t is the node that roots the subtree.
     * set the new root of the subtree.
     * pass the reference,so can change the original node's 
     * left and right node point to new node.
     */
    void insert(const Comparable &x,BinaryNode * &t)
    {
        if (t==nullptr)
           t=new BinaryNode{x,nullptr,nullptr};
        else if(x<t->element)
           insert(x,t->left);
        else if(t->element<x)
           insert(x,t->right);
        else
           ;   //duplicates;do nothing
    }


    void insert(Comparable &&x,BinaryNode * &t)
    {
        if(t==nullptr)
          t=new BinaryNode{std::move(x),nullptr,nullptr};
        else if(x<t->element)
          insert(std::move(x),t->left);
        else if(t->element<x)
          insert(std::move(x),t->right);
        else
           ;   //duplicates;do nothing
    }

    /**
     * Internal method to remove from a subtree.
     * x is the item to remove.
     * t is the node that roots the subtree.
     * set the new root of the subtree.
     */

    void remove(const Comparable &x,BinaryNode * &t)
    {
        if(t==nullptr)
           return;  //item not found;do nothing
        if(x<t->element)
           remove(x,t->left);
        else if(t->element<x)
           remove(x,t->right);
        else if(t->left!=nullptr && t->right!=nullptr)  //two children
        {
            t->element=findMin(t->right)->element;
            remove(t->element,t->right);   //one child or leave
        }
        else                                    //one child or leave    
        {
            BinaryNode *oldNode=t;
            t=(t->left!=nullptr)? t->left:t->right;
            delete oldNode;
        }
    }   

    //pass the value ,only the copy of the pointer

    /**
     * Internal method to find the smallest item in s subtree t.
     * return node containing the smallest item
     * Recursive implementation
     */
    BinaryNode *findMin(BinaryNode *t) const
    {
        if(t==nullptr)
          return nullptr;
        if(t->left==nullptr)
          return t;
        return findMin(t->left);
    }

    /**
     * Internal method to find the largest item in a subtree t
     * Return node containing the largest item.
     * Nonrecursive implementation 
     * pass value ,so t is just the copy of the pointer
     * we change don't just the original
     */
    BinaryNode *findMax(BinaryNode *t) const
    {
        if(t!=nullptr)
           while(t->right!=nullptr)
               t=t->right;
        return t;
    }

    /**
     * Internal method to test if an item is in a subtree.
     * x is item to search for.
     * t is the node that roots the subtree
     */
    bool contains(const Comparable &x,BinaryNode *t) const
    {
        if(t==nullptr)
           return false;  //leave's left node and right node are nullptr
        else if(x<t->element)
           return contains(x,t->left);
        else if(t->element<x)
           return contains(x,t->right);
        else
           return true;   //match
    }



   /**
    * Internal method to make subtree empty.
    */
    void makeEmpty(BinaryNode * &t)
    {
        if(t!=nullptr)
        {
            makeEmpty(t->left);
            makeEmpty(t->right);
            delete t;
        }
        t=nullptr;
    }



    void printTree(BinaryNode *t,ostream &out) const
    {
        if(t!=nullptr)
        {
            printTree(t->left,out);
            out<<t->element;
            printTree(t->right,out);
        }
    }


    /**
     * Internal method to subtree.
     */
    BinaryNode *clone(BinaryNode *t) const
    {
        if(t==nullptr)
           return nullptr;
        else
           return new BinaryNode{t->element,clone(t->left),clone(t->right)};
    }

};
#endif