面試題27:二叉搜索樹與雙向鏈表


題目:輸入一棵二叉搜索樹,將該二叉搜索樹轉換成一個排序的雙向鏈表。要求不能創建任何新的結點,只能調整樹中結點指針的指向。比如輸入下圖中左邊兒茶搜索樹,則輸出轉換后的排序雙向鏈表。
     10
    /  \
   6    14
  / \   / \
 4   8 12 16
4=6=8=10=12=14=16

 將二叉搜索樹轉化為有序雙向鏈表,類似於中序遍歷,中序遍歷的結果就是一個排序的數字。因此在程序中以中序遍歷樹,當遍歷左子樹到在葉子結點的時候,開始修改指針。 

代碼實例:

View Code
#include<iostream>
#include<stdlib.h>
using namespace std;

struct BinaryTreeNode
{
    int m_nValue;
    BinaryTreeNode* m_pLeft;
    BinaryTreeNode* m_pRight;
};

//創建二叉樹結點
BinaryTreeNode* CreateBinaryTreeNode(int value)
{
    BinaryTreeNode* pNode=new BinaryTreeNode();
    pNode->m_nValue=value;
    pNode->m_pLeft=NULL;
    pNode->m_pRight=NULL;
    return pNode;
}

void ConnectTreeNodes(BinaryTreeNode* pParent,BinaryTreeNode* pLeft,BinaryTreeNode* pRight)
{
    if(pParent!=NULL)
    {
        pParent->m_pLeft=pLeft;
        pParent->m_pRight=pRight;
    }
}

void InOrderPrintTree(BinaryTreeNode* pRoot)//中序遍歷
{
    if(pRoot!=NULL)
    {
        if(pRoot->m_pLeft!=NULL)//
            InOrderPrintTree(pRoot->m_pLeft);

        cout<<"value of this node is "<<pRoot->m_nValue<<endl;

        if(pRoot->m_pRight!=NULL)
            InOrderPrintTree(pRoot->m_pRight);
    }
    else
    {
        cout<<"this node is null."<<endl;
    }

}

void Convert(BinaryTreeNode* pNode,BinaryTreeNode** pLastNodeInList)
{
    if(pNode==NULL)
        return;

    BinaryTreeNode* pCurrent=pNode;
    //左子樹轉換,遍歷到左子樹的葉子結點
    if(pCurrent->m_pLeft!=NULL)//遍歷左子樹
        Convert(pCurrent->m_pLeft,pLastNodeInList);

    pCurrent->m_pLeft=*pLastNodeInList;
    if((*pLastNodeInList)!=NULL)
        (*pLastNodeInList)->m_pRight=pCurrent;

    *pLastNodeInList=pCurrent;
    //右子樹轉換
    if(pCurrent->m_pRight!=NULL)//遍歷右子樹
        Convert(pCurrent->m_pRight,pLastNodeInList);

}

BinaryTreeNode* Convert(BinaryTreeNode* pRoot)
{
    BinaryTreeNode* pLastNodeInList=NULL;//指向雙向鏈表的尾結點
    Convert(pRoot,&pLastNodeInList);//轉換排序二叉樹為雙向鏈表

    //求雙向鏈表的頭結點
    BinaryTreeNode* pHeadOfList=pLastNodeInList;
    while(pHeadOfList!=NULL&&pHeadOfList->m_pLeft!=NULL)
        pHeadOfList=pHeadOfList->m_pLeft;
    return pHeadOfList;

}

//輸出雙向鏈表
void PrintList(BinaryTreeNode* pRoot)
{
    BinaryTreeNode* pNode = pRoot;
    while(pNode != NULL)
    {
        printf("%d\t", pNode->m_nValue);
        pNode = pNode->m_pRight;
    }
    printf("\nPrintList ends.\n");
}

void main()
{
//            10
//         /      \
//        6        14
//       /\        /\
//      4  8     12  16
    //創建樹結點
    BinaryTreeNode* pNode10 = CreateBinaryTreeNode(10);
    BinaryTreeNode* pNode6 = CreateBinaryTreeNode(6);
    BinaryTreeNode* pNode14 = CreateBinaryTreeNode(14);
    BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4);
    BinaryTreeNode* pNode8 = CreateBinaryTreeNode(8);
    BinaryTreeNode* pNode12 = CreateBinaryTreeNode(12);
    BinaryTreeNode* pNode16 = CreateBinaryTreeNode(16);
    //連接樹結點
    ConnectTreeNodes(pNode10, pNode6, pNode14);
    ConnectTreeNodes(pNode6, pNode4, pNode8);
    ConnectTreeNodes(pNode14, pNode12, pNode16);

    //PrintTree(pNode10);
    InOrderPrintTree(pNode10);//中序遍歷
    BinaryTreeNode* pHeadOfList=Convert(pNode10);//獲取雙向鏈表頭結點
    PrintList(pHeadOfList);//輸出鏈表

    system("pause");
}


免責聲明!

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



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