整理自剑指Offer
一:题目描述
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
二:代码实现
在二叉树中,每个节点都有两个指向子结点的指针。在双向链表中,每个节点也有两个指针,他们分别指向前一个结点和后一个节点。
二叉搜索树中左子结点的值都小于父结点的值,右子节点的值总是大于父子结点的值,如果采用中序遍历的方式得到的就是排序好的序列。
现在需要解决的就是如何调整指针,使原先指向左子结点的指针调整为链表中指向前一个结点的指针,原先指向右子节点的指针调整为链表指向后一个节点的指针。
三:代码实现
/*
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==NULL)
return NULL;
stack< TreeNode* > stackOfTree;
TreeNode* pNode=pRootOfTree;//指向要连接到链表的二叉搜索树的结点
TreeNode* pPre=NULL;//指向双向链表的最后一个结点
bool isFirstNode=true;
while(pNode!=NULL || !stackOfTree.empty()){
//指向以本次while循环R=pNode最左结点,因为它是当前子树的最小值
while(pNode!=NULL){
stackOfTree.push(pNode);
pNode=pNode->left;
}
//弹栈,弹出最左结点
pNode=stackOfTree.top();
stackOfTree.pop();
if(isFirstNode){
//如果它是链表第一个节点创建头指针
pRootOfTree=pNode; //因为根节点已经压栈,所以不怕
pPre=pRootOfTree;
isFirstNode=false;
}
else{
//如果不是链表第一个节点,将当前节点链接到链表的后面
//链表最后结点的有指针指向当前节点
pPre->right=pNode;
//当前节点的左指针指向链表最后一个结点
pNode->left=pPre;
//pPre指向链表最后一个结点
pPre=pNode;
}
pNode=pNode->right;
}
pPre->right=NULL;
return pRootOfTree;
}
};
画个图,手动走一边流程