题目描述
面试题36:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
思路
调整指针
原先指向左子节点的指针调整为链表中指向前一个节点的指针
原先指向右子节点的指针调整为链表中指向后一个节点的指针
如何调整
考虑根节点和左右子树的根本情况,因为如果用递归,这种根本情况考虑就可以去将同样的方法用到左右子树上
对于这种基本情况,可以分成三个部分来看,根节点10,左子树,右子树,需要做的就是将10与左子树中的最大值连起来,然后把10与右子树中的最小值连起来
现在有个问题就是我们并不知道左子树中的最大值和右子树中的最小值,如果我们知道就好了。但是想到递归,递归到左子树中,如果左子树已转换为双向链表,那么双向链表的最后一个节点就是我们想要的,而右子树中的第一个节点也是我们想要的
C++ 实现
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
TreeNode* Convert(TreeNode* pRootOfTree){
if(pRootOfTree == nullptr)
return nullptr;
// 双向链表尾节点
TreeNode* pLast = nullptr;
// 递归建立双向链表
ConvertNode(pRootOfTree,pLast);
// 查找双向链表首节点
while(pLast->left != nullptr)
pLast = pLast->left;
// 返回双向链表的首节点
return pLast;
}
// 对BST中序遍历,得到有序序列;调整序列元素的指针,将有序序列调整为双向链表
void ConvertNode(TreeNode* cur,TreeNode*& pLast){ // 注意形参
// 边界条件(递归出口)
if(cur == nullptr)
return ;
// 遍历左子树
if(cur->left != nullptr)
ConvertNode(cur->left,pLast);
// 建立双向链接
cur->left = pLast; // 单侧链接,当前节点左侧指向前一个节点
if(pLast != nullptr)
pLast->right = cur; // 单侧链接,前一个节点右侧指向当前节点
pLast = cur; //移动pLast
//遍历右子树
if(cur->right != nullptr)
ConvertNode(cur->right,pLast);
}
};
明确Convert函数的功能。
输入:输入一个二叉搜索树的根节点。
过程:将其转化为一个有序的双向链表。
输出:返回该链表的头节点。
明确成员变量pLast的功能。
pLast用于记录当前链表的末尾节点。
明确递归过程。
递归的过程就相当于按照中序遍历,将整个树分解成了无数的小树,然后将他们分别转化成了一小段一小段的双向链表。再利用pLast记录总的链表的末尾,然后将这些小段链表一个接一个地加到末尾。