Given a binary tree, flatten it to a linked list in-place.
For example,
Given
1 / \ 2 5 / \ \ 3 4 6
The flattened tree should look like:
1 \ 2 \ 3 \ 4 \ 5 \ 6
解题思路:
将一颗二叉树转变成一个链表,如上图,看起来是一个链表,其实也还是一棵树,只不过左子树全部都是空的。
方法一:
由上面例子可知,新的树的链表读取顺序为原树的前序遍历。则我们设定一个额外的最初的节点。然后依次加入前序遍历的各节点即可。代码如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* prenode=NULL;
void preorder(TreeNode* root)
{
if(root)
{
TreeNode* leftnode=root->left;
TreeNode* rightnode=root->right;
if(prenode==NULL)//当这棵新树为空时,我们就将这棵树的根节点定位原树节点
prenode=root;
else
{
prenode->right=root;
prenode->left=NULL;
prenode=root;
}
preorder(leftnode);
preorder(rightnode);
}
}
void flatten(TreeNode* root) {
if(root==NULL) return;
preorder(root);
}
};
注意:
我们采用的是递归的方法来实现前序遍历,为什么不用迭代呢?我尝试过,不过迭代的时候我们用一个栈存储一棵树的所有节点,需要根据之前入栈节点的左右节点来确定后来的节点,在此题中我们是要改变节点的左右节点的,所以这种方法再不重新开辟空间(生成新节点)的情况下是很难实现的。
方法二
由上面例子可知,我们将根节点的由节点先存储right,之后找到左子树的最右边的节点,将righta加到此节点的右边。左节点置空。这就处理完了根节点,之后再处理根节点的右节点,依次便可完成新节点的生成。
eg
代码如下:
class Solution {
public:
void flatten(TreeNode* root) {
if(root==NULL) return;
if(root->right==NULL&&root->left==NULL) return;
while(root)
{
if(root->left)
{
TreeNode* le=root->left;
while(le->right)
le=le->right;
le->right=root->right;
root->right=root->left;
root->left=NULL;
}
root=root->right;
}
}
};