將二叉搜尋樹轉換成一個排序的雙向鏈表

來源:互聯網
上載者:User

題目:將二叉搜尋樹轉換成一個排序的雙向鏈表。提示:要求不能建立任何新的結點,只能調整樹中結點指標的指向,也就是left當prev,right當next。–中序線索化的變型。

1、由於要求鏈表是有序的,可以藉助二叉樹中序遍曆,因為中序遍曆演算法的特點就是從小到大訪問結點。當遍曆訪問到根結點時,假設根結點的左側已經處理好,只需將根結點與上次訪問的最近結點(左子樹中最大值結點)的指標串連好即可。進而更新當前鏈表的最後一個結點指標。
2、由於中序遍曆過程正好是轉換成鏈表的過程,即可採用遞迴處理。
中序遍曆該二叉樹的結果:


把二叉搜尋樹看成三部分:根節點,左子樹和右子樹。在把左,右子樹都轉換成排序的雙向鏈表之後再和根節點連結起來,整棵二叉搜尋也就轉換成了排序的雙向鏈表。
二叉搜尋樹的結點:

template<class K, class V>          //索引值隊struct BSTNode{    BSTNode(const K& key, const V& value)        : _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 BinarySearchTree{    typedef BSTNode<K, V> Node;    typedef BinarySearchTree<K, V> Self;public:    BinarySearchTree()        : _pRoot(NULL)    {}    //拷貝建構函式    //BinarySearchTree(const Self& bst);    //賦值運算子多載    //Self& operator=(const Self& bst);    //解構函式    ~BinarySearchTree()    {         _DestroyTree(_pRoot);    }     // 尋找--非遞迴    bool Find_Nor(const K& key)    {        Node* pCur = _pRoot;        while (pCur)  //二叉樹存在        {            if (pCur->_key == key)                return true;            else if (key < pCur->_key)                return pCur = pCur->_pLeft;            else                 pCur = pCur->_pRight;        }        return false;    }    //遞迴尋找    bool Find(const K& key)   {       return _Find(_pRoot, key);   }    // 插入--非遞迴    bool Insert_Nor(const K& key, const V& value)  //插入某元素    {        if (NULL == _pRoot)        {            _pRoot = new Node(key, value);            return true;        }        //找元素插入位置        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 = pParent->_pLeft ;            pParent->_pLeft = pCur;        else if (key > pParent->_key)            //pParent = pParent->_pRight;             pParent->_pRight = pCur;        else             return false;    }//  遞迴--插入    bool Insert(const K& key, const V& value)    {         return _Insert(_pRoot, key, value);  //    }    void InOrder()    {        cout << "InOrder(): " << endl;        _InOrder(_pRoot);        cout << endl;    }    //二叉搜尋樹與雙向鏈表    Node* Convert()  //_pRoot    {        Node* pLastNodeInList = NULL;        ConvertNode(_pRoot, &pLastNodeInList);   //pLastNodeInList-->雙向鏈表的尾結點        //返回頭結點        Node* pHeadOfList = pLastNodeInList;        while (pHeadOfList != NULL && pHeadOfList->_pLeft != NULL)            pHeadOfList =  pHeadOfList->_pLeft;        return pHeadOfList;    }    private:        bool _Find(Node* pRoot, const K& key)        {            if (pRoot)  //二叉樹存在            {                if (key == pRoot->_key)  //尋找的值在左子樹中                    return true;                else if (key < pRoot->_key)                    return  _Find(pRoot->_pLeft, key); // 尋找的值在左子樹中                else                    return _Find(pRoot->_pRight, key);  //尋找的值在右子樹中            }            return false; //樹不存在        }        bool _Insert(Node* &pRoot, const K& key, const V& value)  //---         {            if (NULL == pRoot)  //1)、樹為空白,插入結點作為根結點            {                pRoot = new Node(key, value);                return true;            }            else  //二叉樹存在--插入的結點在左右子樹中            {                if (key < pRoot->_key)                    return _Insert(pRoot->_pLeft, key, value);  //                else if (key > pRoot->_key)                    return _Insert(pRoot->_pRight, key, value);  //                else                    return false;            }        }        void _InOrder(Node* pRoot)  //Node* pRoot--中序遍曆        {            if(pRoot)            {                //遍曆左子樹                _InOrder(pRoot->_pLeft);                cout<<pRoot->_key<<" ";                _InOrder(pRoot->_pRight);  //遍曆右子樹            }        }        //二叉搜尋樹與雙向鏈表        void ConvertNode(Node* pRoot, Node** pLastNodeInList)        {            if (NULL == pRoot)                return;            Node* pCur = pRoot;            if (NULL != pCur->_pLeft)  //遞迴處理左子樹                ConvertNode(pCur->_pLeft, pLastNodeInList);            //pCur--處理當前結點,將當前結點的左指標指向鏈表的尾結點            pCur->_pLeft = *pLastNodeInList;  //pLastNodeInList-->雙向鏈表的尾結點            if (NULL != *pLastNodeInList)                (*pLastNodeInList)->_pRight = pCur;            //更新已經轉換好的鏈表的尾結點            *pLastNodeInList = pCur;            //遞迴處理右子樹            if (NULL != pCur->_pRight)                ConvertNode(pCur->_pRight, pLastNodeInList);        }    void _DestroyTree(Node*& pRoot)    {        if (pRoot)        {            _DestroyTree(pRoot->_pLeft);            _DestroyTree(pRoot->_pRight);            delete pRoot;            pRoot = NULL;        }    }private:    Node* _pRoot;};

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.