剑指offer之二叉搜索树与双向链表

本文介绍如何将二叉搜索树转换为排序的双向链表,提供两种方法:一是利用中序遍历和vector保存节点指针,二是递归调整节点指针。两种方法均不创建新节点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.问题描述

题目:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
二叉树结构类型:

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

2.分析

例如:

        2
       / \
      1   3 

方法一:

使用一个vector来保存所有节点的指针,之后再遍历vector中的每一个指针,分别改变节点每个指针指向的方向。为了保存节点的指针有序,根据二叉搜索树的特点,我们应该使用中序遍历。vector中保存的是节点的指针,并不会创建新的节点,所以满足要求。
如上面:
保存在vector中顺序应该是1,2,3,之后改变指针方向

方法二:

使用递归的方法
如上面的例子:2是根节点,1是左子树,也是左子树最后一个节点3是右子树,也是右子树的第一个节点,根节点(2)的左指针指向左子树的最后一个节点(1);同时,使根节点(1)的右指针指向右子树的第一个节点(3)。这是一个递归的定义,之后分别对左子树,右子树进行同样的处理。

3.源代码:

方法一:

void moveInVec(BinaryTreeNode* pNode,vector<BinaryTreeNode*> & nodes)
{
    if(pNode == nullptr)
        return;
    if(pNode->m_pLeft !=nullptr)
        moveInVec(pNode->m_pLeft,nodes);

   // BinaryTreeNode* rightNode = pNode->m_pRight;
    nodes.push_back(pNode);

    if(pNode->m_pRight !=nullptr)
        moveInVec(pNode->m_pRight,nodes);

}
BinaryTreeNode* Convert(BinaryTreeNode* pRootOfTree)
{
    if(pRootOfTree == nullptr)
        return nullptr;

    vector<BinaryTreeNode*> nodes;
    moveInVec(pRootOfTree,nodes);

    //连接各个节点
    for(auto & node:nodes)
    {
        if(PreNode !=nullptr)
            PreNode->m_pRight = node;

        node->m_pLeft = PreNode;
        PreNode = node;
    }

    //数组中的第一个元素就是我们要找的头指针
    return nodes.front();

}

方法二:

void ConvertNode(BinaryTreeNode* pHead, BinaryTreeNode** pLastNode)
{
    if(pHead == nullptr)
        return;

    BinaryTreeNode* pNode = pHead;

    if(pNode->m_pLeft !=nullptr)
        ConvertNode(pNode->m_pLeft, pLastNode);

    //连接当前节点
    if(*pLastNode !=nullptr)
        (*pLastNode)->m_pRight = pNode;
    pNode->m_pLeft = *pLastNode;
    *pLastNode = pNode;

    if(pNode->m_pRight !=nullptr)
        ConvertNode(pNode->m_pRight, pLastNode);


}
BinaryTreeNode* Convert_2(BinaryTreeNode* pRootOfTree)
{
    if(pRootOfTree == nullptr)
        return nullptr;
    //链表中第一个节点的左指针应该指向nullptr
    BinaryTreeNode* pLastNode = nullptr;
    ConvertNode(pRootOfTree, &pLastNode);

    for(;pLastNode !=nullptr && pLastNode->m_pLeft!= nullptr;pLastNode = pLastNode->m_pLeft);

    return pLastNode;

}

4.结论:

  • 如果采用第一种方法,会简单不少,没有那么麻烦,这个用到了二叉树的中序遍历,这里使用了递归的方法;
  • 这是一个比较复杂的问题,我们需要画一个图来分析;
  • 我们把问题分成根节点,左子树,右子树。再讨论左子树,右子树,这个可以问题化小,方便我们处理这个问题,这里也使用了递归的方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值