將二叉搜索樹轉換為排序雙向鏈表


題目描述:有一個搜索二叉樹,對於樹中的任意一個節點,其左子樹的所有值小於該節點的值,而其右子樹的所有值大於該節點的值。要求:在不定義任何新的節點情況下,將該二叉樹轉換成為一個排序雙向鏈表。

假設有上面的二叉樹,那么其轉換為雙向鏈表后的順序應該為:2  3  4  5  6  7  8

對於鏈表頭節點:其直接前驅為空指針,直接后繼為其父節點;

對於鏈表尾節點:其直接前驅為其父節點,直接后繼為空;

對於左子樹的根節點:其直接前驅為其左子樹中的最大值;其直接后繼為其右子樹中的最小值或者父節點的值;

對於右子樹的根節點:其直接前驅為其左子樹中的最大值或者父節點的值;其直接后繼為右子樹中的最大值;

因此,我們可以將二叉樹看作三個部分:根節點、左子樹、右子樹。

如果我們可以遞歸地將左子樹和右子樹轉換成為排序的雙向鏈表,那么整個二叉樹也就被轉換成了排序的雙向鏈表。

示例代碼如下:

#include<iostream>
using namespace std; struct BinTreeNode { int value; BinTreeNode *LeftNode; BinTreeNode *RightNode; }; void ConvertNode(BinTreeNode *pNode, BinTreeNode **pLastNodeInList); BinTreeNode *Convert(BinTreeNode *pRootNode) { BinTreeNode *pLastNodeInList = nullptr; ConvertNode(pRootNode, &pLastNodeInList); BinTreeNode *pHeadOfList = pLastNodeInList; //此時pHeadOfList是二叉樹的頭節點,要返回鏈表頭需要將它向左移,直到到達鏈表頭
    while (pHeadOfList != nullptr&&pHeadOfList->LeftNode != nullptr) { pHeadOfList = pHeadOfList->LeftNode; } //返回鏈表的頭節點
    return pHeadOfList; } void ConvertNode(BinTreeNode *pNode, BinTreeNode **pLastNodeInList) { if (pNode == nullptr) { return; } BinTreeNode *pCurrentNode = pNode; //如果存在左子樹,那么遞歸地修改左子樹節點指向
    if (pCurrentNode->LeftNode != nullptr){ ConvertNode(pNode->LeftNode, pLastNodeInList);} //將當前節點的左子節點指向鏈表尾部元素(因為鏈表尾部元素更小)
    pCurrentNode->LeftNode = *pLastNodeInList; //將鏈表尾部元素的右子節點指向當前節點,與上一步操作類似;
    if (*pLastNodeInList != nullptr){ (*pLastNodeInList)->RightNode = pCurrentNode; } //更新鏈表尾部元素
    *pLastNodeInList = pCurrentNode; //遞歸的修改右子樹的節點指向
    if (pCurrentNode->RightNode != nullptr) { ConvertNode(pCurrentNode->RightNode, pLastNodeInList); } } int main() {}

將上述代碼對上面圖示的二叉樹進行轉換,其轉換過程中的變量變化如下,這能幫助我們理解整個轉換的過程:

在Convert函數中調用ConvertNode()函數結束以后,用來存儲鏈表尾部元素的變量值為二叉樹的根節點的值,即:10。

因此,為了正確地返回鏈表頭部元素,需要將該指針向左移到鏈表頭地位置,最終將這個指針返回。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM