写在前面
题目:
thinking
1.首先,肯定需要遍历二叉树,对于遍历二叉树,我们一般是选择递归
2.由二叉树变为链表,我们首先要像,这两种数据结构有什么异同,相同点,二叉树的root节点可以认为是链表的head节点,二叉树的每个节点会有两个指针域,分别指向left和right,而链表的每个节点有一个指针域,指向它的下一个节点。
3.我们要把左面的结构变成右边的结构,很显然,需要将根节点的right 指向左子树,而left指向NULL就可以了,
4.递归调用上述方法遍历左右子树,这里,我们需要考虑,左右子树如何连在一起的,对比左右两图,显然,需要将左子树的最后一个节点的right指向右子树,左子树同样置为NULL,
5.上述,只是考虑的一般情况,对于递归,我们需要考虑递归结束的条件,
- 二叉树为空的时候,显然,直接返回,
- 遍历到叶节点时,如何操作
6.4 中提到,需要遍历左右子树,因为,我们不断改变树的结构,所以,遍历之前,需要备份左右子树,还需要保存最后节点的变量,因此,这里,我们需要定义四个节点变量,当我们遍历到左右子树的最后一个节点,也是叶节点,需要一个last节点来保存我们的最后一个节点。所以,5 中的2,只有叶节点时如何操作,就很显然了。
下面第一段代码,是我第一次提交的代码,虽然编译没问题,但submit时有错误,查看details,可以看到,通过了一部分,所以,大致思路是没问题的,提示35行,我们自然会去查看35行,根据信息,我知道,需要对该节点判断是否为空,
1 /** 2 * Definition for a binary tree node. 3 * struct TreeNode { 4 * int val; 5 * TreeNode *left; 6 * TreeNode *right; 7 * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 8 * }; 9 */ 10 class Solution { 11 public: 12 void flatten(TreeNode* root) { 13 TreeNode* last = nullptr; 14 preorder_trs(root,last); 15 } 16 private: 17 void preorder_trs(TreeNode* root,TreeNode* last){ 18 if(root == nullptr) return; 19 if(root->left==nullptr && root->right == nullptr){ 20 last = root; 21 return; 22 } 23 TreeNode* left = root->left; 24 TreeNode* right = root->right; 25 TreeNode* left_last = nullptr; 26 TreeNode* right_last = nullptr; 27 if(left){ 28 preorder_trs(left,left_last); 29 root->left = nullptr; 30 root->right = left; 31 last = left_last; 32 } 33 if(right){ 34 preorder_trs(right,right_last); 35 if(last){ 36 last->left = nullptr; 37 last->right = right; 38 } 39 40 last = right_last; 41 } 42 } 43 };
compile correct,but running error,details as follow
this means the node "last" also the left_last maybe nullptr,so we need judge the node whether nullptr or not,only if it is not null,we can let the right of the node point to the right sunTree.
The Accepted Answer:
1 /** 2 * Definition for a binary tree node. 3 * struct TreeNode { 4 * int val; 5 * TreeNode *left; 6 * TreeNode *right; 7 * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 8 * }; 9 */ 10 class Solution { 11 public: 12 void flatten(TreeNode* root) { 13 TreeNode* last; 14 preorder_trs(root,last); 15 } 16 private: 17 void preorder_trs(TreeNode* root,TreeNode* &last){ 18 if(root ==nullptr) return; 19 if(root->left==nullptr && root->right ==nullptr) { 20 last = root; 21 return; 22 } 23 TreeNode* left = root->left; 24 TreeNode* right = root->right; 25 TreeNode* left_last = nullptr; 26 TreeNode* right_last = nullptr; 27 if(left){ 28 preorder_trs(left,left_last); 29 root->left = nullptr; 30 root->right = left; 31 last = left_last; 32 } 33 if(right){ 34 preorder_trs(right,right_last); 35 if(left_last){ 36 //last->left = nullptr; 37 left_last->right = right; 38 } 39 last = right_last; 40 } 41 } 42 };
Two changes:
first: line 17, pass by value changed to pass by reference()
second,line 35,after I had added the condition to judge the last is nullptr or not ,it was also an wrong answer,so the condition changed to if(left_last){} , It would have been to judge the left_last,because of having assigned left_last to the last,why this is wrong ,I have not knew, Welcome To Dicuss!!!
写在最后
这次认真写博客还有一个收获就是学会了使用graphviz画数据结构的图。我是一个追求高效率的人,看别人的博客数据结构图画的都很美观,我想,不可能都是用PowerPoint或Visio画的吧,那也太费时了,所以,我就Google了,还真Google到了,于是就赶紧安装试了试,但最初画出来的好丑啊,如下:
是不是看着很别扭,于是,我又Google了,看有没有可以改进的办法,找了半天还真找到了,也感谢这篇博客的博主:https://blog.csdn.net/theonegis/article/details/71772334
其实,不用像博主那样保存为.gvpr ,保存为.gv就可以了,还是因为我懒,因为,我不知道博主说的那种格式文件,我安装的graphviz能不能支持(虽然我都是用Sublime作为编辑器,命令行执行),所以,我就写成了graphviz默认的.gv格式了。这就是写博客的好处之一,除了帮你整理思路,还督促你不断学习新东西。