面试题27:二叉搜索树与双向链表

/*输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表,要求不能创建任何新的结点,只能调整树中
结点指针的指向*/
#include <iostream>
#include <queue>
using namespace std;
//定义一个二叉树结点
struct BinaryTreeNode
{
    int m_nValue;
    BinaryTreeNode *m_pLeft;
    BinaryTreeNode *m_pRight;
};
//创建二叉树结点
BinaryTreeNode *CreateBinaryTreeNode(int ival)
{
    BinaryTreeNode *OneNode = new BinaryTreeNode();
    OneNode -> m_nValue = ival;
    OneNode -> m_pLeft = NULL;
    OneNode -> m_pRight = NULL;
    return OneNode;
}
//连接二叉树结点
void ConnectBinaryTreeNode(BinaryTreeNode *pRoot, BinaryTreeNode *pLeft, BinaryTreeNode *pRight)
{
    pRoot -> m_pLeft = pLeft;
    pRoot -> m_pRight = pRight;
}
//释放空间(递归实现)
void FreeSpace(BinaryTreeNode *pRoot)
{
    if(pRoot != NULL)
    {
        FreeSpace(pRoot -> m_pLeft);
        FreeSpace(pRoot -> m_pRight);
        delete pRoot;
    }
}
//释放双向链表空间
void DestroyList(BinaryTreeNode *pHeadOfList)
{
    BinaryTreeNode *pNode = pHeadOfList;
    while(pNode != NULL)
    {
        BinaryTreeNode *pNext = pNode -> m_pRight;
        delete pNode;
        pNode = pNext;
    }
}
//改变二叉搜索树的指针为双向排序链表
void ConvertNode(BinaryTreeNode *pRootOfTree, BinaryTreeNode **pLastNodeInList)
{
    if(pRootOfTree == NULL)
    return;
    //定义一个指针指向当前结点
    BinaryTreeNode *pCurrent = pRootOfTree;
    //递归实现左子树指针的转换
    if(pCurrent -> m_pLeft != NULL)
    ConvertNode(pCurrent -> m_pLeft, pLastNodeInList);
    //二叉搜索树当前节点的左指针指向当前最大值,头结点时指向空
    pCurrent -> m_pLeft = *pLastNodeInList;
    //如果当前最大值点不为空,则其右指针指向当前二叉搜索树结点
    if(*pLastNodeInList != NULL)
    (*pLastNodeInList) -> m_pRight = pCurrent;
    //改变pLastNodeInList使其指向当前结点也即最大值结点
    *pLastNodeInList = pCurrent;
    //转换右子树结点指针顺序
    if(pCurrent -> m_pRight != NULL)
    ConvertNode(pCurrent -> m_pRight, pLastNodeInList);
}
//封装后的转换函数,返回转换后的双向链表的头结点
BinaryTreeNode *Convert(BinaryTreeNode *pRootOfTree)
{
    BinaryTreeNode *pLastNodeInList = NULL;
    ConvertNode(pRootOfTree, &pLastNodeInList);
    //pLastNodeList指向双向链表的尾结点(由于ConverNode()用的是指向指针的指针)所以pLastNodeInList的值
    //经过函数调用会改变
    BinaryTreeNode *pHeadOfList = pLastNodeInList;//定义一个指针指向双向链表头结点
    while(pHeadOfList != NULL && pHeadOfList -> m_pLeft != NULL)
    pHeadOfList = pHeadOfList -> m_pLeft;
    return pHeadOfList;
}
//打印树(从上到下)
void PrintTree(BinaryTreeNode *pRoot)
{
    if(pRoot == NULL)
    return;
    //定义一个结点指针的队列
    queue<BinaryTreeNode *> pQueue;
    //根节点入队
    pQueue.push(pRoot);
    //队列大小作为循环条件
    while(pQueue.size())
    {
        //队首元素存储起来
        BinaryTreeNode *pNode = pQueue.front();
        //删除队首元素
        pQueue.pop();
        //输出队首元素
        cout << pNode -> m_nValue << " ";
        //结点的左子节点(非空)入队
        if(pNode -> m_pLeft)
        pQueue.push(pNode -> m_pLeft);
        //结点的右子结点(非空)入队
        if(pNode -> m_pRight)
        pQueue.push(pNode -> m_pRight);
    }

}
//打印双链表
void PrintDoubleLinkedList(BinaryTreeNode *pHeadOfList)
{
    BinaryTreeNode *pNode = pHeadOfList;
    cout << "The nodes from left to right are:" << endl;
    while(pNode != NULL)
    {
       cout << pNode -> m_nValue << " ";
       if(pNode -> m_pRight == NULL)
       break;
       pNode = pNode -> m_pRight;
    }
    cout << endl;
    cout << "The nodes from right to left are:" << endl;
    while(pNode != NULL)
    {
        cout << pNode -> m_nValue << " ";
        //到达头结点则推出循环
        if(pNode -> m_pLeft == NULL)
        break;
        pNode = pNode -> m_pLeft;
    }
    cout << endl;
}
//=======测试代码======
void Test(char *TestName, BinaryTreeNode *pRoot)
{
    if(TestName != NULL)
    cout << TestName << " Begins:" << endl;
    PrintTree(pRoot);
    cout << endl;
    BinaryTreeNode *pHeadOfList = Convert(pRoot);
    PrintDoubleLinkedList(pHeadOfList);
    DestroyList(pHeadOfList);
}
//======测试用例=======
//完全二叉树
//            10
//         /      \
//        6        14
//       /\        /\
//      4  8     12  16
void Test1()
{
    BinaryTreeNode *pNode1 = CreateBinaryTreeNode(10);
    BinaryTreeNode *pNode2 = CreateBinaryTreeNode(6);
    BinaryTreeNode *pNode3 = CreateBinaryTreeNode(14);
    BinaryTreeNode *pNode4 = CreateBinaryTreeNode(4);
    BinaryTreeNode *pNode5 = CreateBinaryTreeNode(8);
    BinaryTreeNode *pNode6 = CreateBinaryTreeNode(12);
    BinaryTreeNode *pNode7 = CreateBinaryTreeNode(16);

    ConnectBinaryTreeNode(pNode1, pNode2, pNode3);
    ConnectBinaryTreeNode(pNode2, pNode4, pNode5);
    ConnectBinaryTreeNode(pNode3, pNode6, pNode7);

    Test("Test1", pNode1);
}
//所有结点位于左子树
//               5
//              /
//             4
//            /
//           3
//          /
//         2
//        /
//       1
void Test2()
{
    BinaryTreeNode *pNode1 = CreateBinaryTreeNode(5);
    BinaryTreeNode *pNode2 = CreateBinaryTreeNode(4);
    BinaryTreeNode *pNode3 = CreateBinaryTreeNode(3);
    BinaryTreeNode *pNode4 = CreateBinaryTreeNode(2);
    BinaryTreeNode *pNode5 = CreateBinaryTreeNode(1);

    ConnectBinaryTreeNode(pNode1, pNode2, NULL);
    ConnectBinaryTreeNode(pNode2, pNode3, NULL);
    ConnectBinaryTreeNode(pNode3, pNode4, NULL);
    ConnectBinaryTreeNode(pNode4, pNode5, NULL);

    Test("Test2", pNode1);
}
//结点都位于右子树
// 1
//  \
//   2
//    \
//     3
//      \
//       4
//        \
//         5
void Test3()
{
    BinaryTreeNode *pNode1 = CreateBinaryTreeNode(1);
    BinaryTreeNode *pNode2 = CreateBinaryTreeNode(2);
    BinaryTreeNode *pNode3 = CreateBinaryTreeNode(3);
    BinaryTreeNode *pNode4 = CreateBinaryTreeNode(4);
    BinaryTreeNode *pNode5 = CreateBinaryTreeNode(5);

    ConnectBinaryTreeNode(pNode1, NULL, pNode2);
    ConnectBinaryTreeNode(pNode2, NULL, pNode3);
    ConnectBinaryTreeNode(pNode3, NULL, pNode4);
    ConnectBinaryTreeNode(pNode4, NULL, pNode5);

    Test("Test3", pNode1);
}
//树中只有一个结点
void Test4()
{
    BinaryTreeNode *pNode1 = CreateBinaryTreeNode(1);
    Test("Test4", pNode1);
}
//树中没有结点
void Test5()
{
    Test("Test5", NULL);
}
int main()
{
    Test1();
    cout << endl;
    Test2();
    cout << endl;
    Test3();
    cout << endl;
    Test4();
    cout << endl;
    Test5();
    return 0;
}
//解决问题的关键在于把一个大的问题分成几个小问题,并递归的解决小问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值