二叉搜索樹---使用迭代器

迭代器:它的用法與指針用法相同
使用迭代器實現二叉搜索樹,使用有兩個指針域的頭結點實現,
並且多給BSTree中加入一個雙親結點_pParent。

這裏寫圖片描述

代碼:
BSTIterator.hpp

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

template<class k,class v>
struct BSTNode
{
    BSTNode(const k& key=k(),const v& value=v())
        :_pLeft(NULL)
        ,_pRight(NULL)
        ,_pParent(NULL)
        ,_key(key)
        ,_value(value)
    {}

    BSTNode<k,v>* _pLeft;
    BSTNode<k,v>* _pRight;
    BSTNode<k,v>* _pParent;

    k _key;
    v _value;
};

template<class K, class V, class Ref, class Ptr>
class BSTIterator
{
    typedef BSTNode<K, V> Node;
    typedef BSTIterator<K, V, Ref, Ptr> Self;
public:
    BSTIterator()
        :_pNode(NULL)
    {}
    BSTIterator(Node* pNode)
        :_pNode(pNode)
    {}
    BSTIterator(const Self& s)
        :_pNode(s._pNode)
    {}
    Self& operator++()
    {
        Increment();
        return *this;
    }
    Self operator++(int)
    {
        Self temp(*this);
        Increment();
        return temp;
    }
    Self& operator--()
    {
        Decrement();
        return *this;
    }
    Self operator--(int)
    {
        Self temp(*this);
        Decrement();
        return temp;
    }
    Ref operator*()//解引用
    {
        return _pNode->_key;
    }
    Ptr operator->()//->
    {
        return &(operator*());
    }
    bool operator!=(const Self& s)
    {
        return _pNode!=s._pNode;
    }
    bool operator==(const Self& s)
    {
        return !(*this!=s);
    }

protected:
    // 取當前結點的下一個結點
    void Increment()
    {
        //如果右子樹存在,右子樹中的最小結點就是當前結點的下一個結點
        if(_pNode->_pRight)
        {
            _pNode=_pNode->_pRight;
            while(_pNode->_pLeft)
                _pNode=_pNode->_pLeft;
        }
        else//右子樹不存在
        {
            Node* pParent=_pNode->_pParent;
            while(pParent->_pRight==_pNode)
            {
                _pNode=pParent;
                pParent=pParent->_pParent;
            }
            //特殊情況:根的右子樹不存在,獲取根的下一節點即爲end()
            if(_pNode->_pRight!=pParent)
                _pNode=pParent;
        }
    }

    // --取前一個小的結點,在left子樹中
    void Decrement()
    {
        //左子樹存在
        if(_pNode->_pRight)
        {
            _pNode=_pNode->_pLeft;
            while(_pNode->_pRight)
                _pNode=_pNode->_pRight;
        }
        else
        {
            Node* pParent=_pNode->_pParent;
            while(_pNode==pParent->_pLeft)
            {
                _pNode=pParent;
                pParent=pParent->_pParent;
            }
            _pNode=pParent;
        }

    }

protected:
    Node* _pNode;
};

template<class k,class v>
class BSTree
{
    typedef BSTNode<k,v> Node; 
public:
    typedef BSTIterator<k,v,k&,k*> Iterator;
public:
    BSTree()
    {
        _pHead=new Node();
        _pHead->_pLeft=_pHead;
        _pHead->_pRight=_pHead;
        _pHead->_pParent=NULL;
    }


    Iterator Begin()
    {
        return _pHead->_pLeft;
    }

    Iterator End()
    {
        return _pHead;
    }

    Node* Find(const k& key)
    {
        Node* pCur=GetRoot();
        while(pCur)
        {
            if(key==pCur->_key)
                return pCur;
            else if(key<pCur->_key)
                pCur=pCur->_pLeft;
            else
                pCur=pCur->_pRight;
        }
        return NULL;
    }

    bool Insert(const k& key,const v& value)
    {
        Node*& pRoot=_pHead->_pParent;
        if(NULL==pRoot)
        {
            pRoot=new Node(key,value);
            pRoot->_pParent=_pHead;
        }
        else
        {
            Node* pCur=pRoot;
            Node* pParent=NULL;
            while(pCur)
           {
               if(key < pCur->_key)//向左插入
               {
                   pParent=pCur;
                   pCur=pCur->_pLeft;
               }
               else if(key > pCur->_key)//向右插入
               {
                   pParent=pCur;
                   pCur=pCur->_pRight;
               }
               else//等於根節點,不需要插入
               {
                   return false;
               }
           }
           //插入到葉子結點後時
           pCur=new Node(key,value);
           if(key<pParent->_key)
               pParent->_pLeft=pCur;
           else
               pParent->_pRight=pCur;
           pCur->_pParent=pParent;
        }
        _pHead->_pLeft=LeftMost();
        _pHead->_pRight=RightMost();
        return true;
    }
    void InOrder()//中序遍歷
    {
        cout<<"InOrder:"<<endl;
        _InOrder(GetRoot());
        cout<<endl;
    }
    const k& GetMaxKey()const//找最右結點(最大)
    {
        Node* pRoot=GetRoot();
        assert(pRoot);
        Node* pCur=pRoot;
        while(pCur->_pRight)
            pCur=pCur->_pRight;
        return pCur->_key;
    }
    const k& GetMinKey()const//找最左結點(最小)
    {
        Node* pRoot=GetRoot();
        assert(pRoot);
        Node* pCur=pRoot;
        while(pCur->_pLeft)
            pCur=pCur->_pLeft;
        return pCur->_key;
    }

    bool Remove(const k& key)//刪除key結點
    {
        Node*& pRoot=GetRoot();
        //樹爲空,不能刪除結點
        if(NULL==pRoot)
            return false;
        //只有一個根節點,要刪除的結點正好是根節點
        if(NULL==pRoot->_pLeft && NULL==pRoot->_pRight && key==pRoot->_key)
        {                                                                     
            delete pRoot;
            _pHead->_pParent=NULL;
        }
        else
        {
            //找待刪除結點
            Node* pCur=pRoot;
            Node* pParent=NULL;
            while(pCur)
           {
               if(key<pCur->_key)
               {
                   pParent=pCur;
                   pCur=pCur->_pLeft;
               }    
               else if(key>pCur->_key)
               {
                   pParent=pCur;
                   pCur=pCur->_pRight;
               }        
               else
                   break;//找到了該節點
            }
            //已找到待刪除結點---》1.沒有左孩子,只有右孩子
                                 //2.沒有右孩子,只有左孩子
                                // 3.左右孩子都沒有
                                 //4.左右孩子都存在
                                 //可以合併1,3 或2,3
            if(NULL==pCur)
                return false;
            else
            {   //1.沒有左孩子,右孩子可能存在,也可能不存在(NULL)
               if(NULL==pCur->_pLeft)
               {
                   if(pCur!=pRoot)
                   {
                       if(pCur==pParent->_pRight)
                           pParent->_pRight=pCur->_pRight;
                       else
                           pParent->_pLeft=pCur->_pRight;
                   }
                   else
                       pRoot=pCur->_pRight;
                }
            //2.沒有右孩子,左孩子可能存在,也可能不存在(NULL)
                else if(NULL==pCur->_pRight)
               {
                   if(pCur!=pRoot)
                   {
                       if(pCur==pParent->_pRight)
                            pParent->_pRight=pCur->_pLeft;
                       else
                            pParent->_pLeft=pCur->_pLeft;
                   }
                   else
                       pRoot=pCur->_pLeft;
                }  
            //3.左右子樹都存在
                else
               {
                    //找中序遍歷的第一個節點,爲右子樹中最小的結點
                    //pParnet一直是firstInOrder的雙親
                    pParent=pCur;//防止在找右子樹中最小結點時,右子樹沒有左孩子,無法進入循環,pParent會一直爲空
                    Node* firstInOrder=pCur->_pRight;
                   //找該節點的右子樹中最左邊的結點,即右子樹中key最小的結點
                    while(firstInOrder->_pLeft)
                    {
                        pParent=firstInOrder;
                        firstInOrder=firstInOrder->_pLeft;
                    }
                //交換key最小結點和根節點的值
                    pCur->_key=firstInOrder->_key;
                    pCur->_value=firstInOrder->_value;
                    if(pParent->_pLeft==firstInOrder)
                        pParent->_pLeft=firstInOrder->_pRight;
                    else
                        pParent->_pRight=firstInOrder->_pRight;
                    pCur=firstInOrder;
                }
                delete pCur;
                pCur=NULL;
            }
        }
        _pHead->_pLeft=LeftMost();
        _pHead->_pRight=RightMost();
        return true;
    }

    Node* LeftMost()
    {
        Node* pCur = GetRoot();
        assert(pCur);
        while(pCur->_pLeft)
            pCur = pCur->_pLeft;

        return pCur;
    }

    Node* RightMost()
    {
        Node* pCur = GetRoot();
        assert(pCur);
        while(pCur->_pRight)
            pCur = pCur->_pRight;

        return pCur;
    }

    Node*& GetRoot()const
    {
        return _pHead->_pParent;
    }

    Node* ToList()//轉化爲雙向鏈表
    {
        //找鏈表頭
        Node* pHead=GetRoot();
        if(NULL==pHead)
            return;
        while(pHead->_pLeft)
            pHead=pHead->_pLeft;

        Node* prev = NULL;
        _ToList(GetRoot(), prev);
        return pHead;
    }
protected:

    void _InOrder(Node* pRoot)
    {
        if(pRoot)
        {
            _InOrder(pRoot->_pLeft);
            cout<<pRoot->_key<<" ";
            _InOrder(pRoot->_pRight);
        }
    }

    void _ToList(Node* pRoot, Node*& prev)
    {
        if(pRoot)
        {
            _ToList(pRoot->_pLeft, prev);

            // 當前節點的左指針域
            pRoot->_pLeft = prev;

            // 上一個結點的右指針域
            if(prev)
                prev->_pRight = pRoot;

            prev = pRoot;
            _ToList(pRoot->_pRight, prev);
        }
    }

private:
    Node* _pHead;
};

測試代碼:


#include"BSTIterator.hpp"
void Test1()
{
    BSTree<int,int> bst;
    int a[]={5,3,4,1,7,8,2,6,0,9};
    for(int idx=0;idx<(sizeof(a)/sizeof(a[0]));++idx)
    {
        bst.Insert(a[idx],idx);
    }
    bst.InOrder();
    bst.Find(8);
    cout<<bst.GetMinKey()<<endl;
    cout<<bst.GetMaxKey()<<endl;
}

void Test2()//情況三①②及情況一
{
    BSTree<int,int> bst;
    int a[]={5,3,4,1,7,8,2,6,0,9};
    //int a[]={5,3,4,1,8,2,6,7,0,9};
    for(int idx=0;idx<(sizeof(a)/sizeof(a[0]));++idx)
    {
        bst.Insert(a[idx],idx);
    }
    bst.Remove(8);
    bst.InOrder();
    bst.Remove(6);
    bst.InOrder();

}
void Test3()//情況三中的③
{
    BSTree<int,int> bst;
    int a[]={5,7,8,6,9};
    for(int idx=0;idx<(sizeof(a)/sizeof(a[0]));++idx)
    {
        bst.Insert(a[idx],idx);
    }
    bst.Remove(5);
    bst.InOrder();
}

void Test4()//情況二
{
    BSTree<int,int> bst;
    int a[]={5,3,4,1,7,6,0};
    for(int idx=0;idx<(sizeof(a)/sizeof(a[0]));++idx)
    {
        bst.Insert(a[idx],idx);
    }
    bst.Remove(1);
    bst.InOrder();
    bst.Remove(7);
    bst.InOrder();

}


void Test5()//情況四
{
    BSTree<int,int> bst;
    int a[]={5,3,4,1,7,8,2,6,0,9};
    for(int idx=0;idx<(sizeof(a)/sizeof(a[0]));++idx)
    {
        bst.Insert(a[idx],idx);
    }
    bst.Remove(5);
    bst.InOrder();
    bst.Remove(7);
    bst.InOrder();

}
void Test6()//情況四
{
    BSTree<int,int> bst;
    int a[]={5,3,4,1,7,8,2,0,9};
    for(int idx=0;idx<(sizeof(a)/sizeof(a[0]));++idx)
    {
        bst.Insert(a[idx],idx);
    }
    bst.Remove(5);
    bst.InOrder();
}
int main()
{
    Test1();
    Test2();
    Test3();
    Test4();
    Test5();
    Test6();
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章