输入描述:
二叉树的根节点
返回值描述:
双向链表的其中一个头节点。
方法一
已知将二叉搜索树进行中序遍历可以得到由小到大的顺序排列,因此本题最直接的想法就是进行中序遍历。
将中序遍历的结果用数组存储下来,得到的数组是有从小到大顺序的。最后将数组中的结点依次连接即可。
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
vector<int>v;
void dfs(TreeNode* root){
if(root==nullptr)return;
dfs(root->left);
v.push_back(root->val);
dfs(root->right);
}
TreeNode* Convert(TreeNode* pRootOfTree) {
if(pRootOfTree==nullptr){
return nullptr;
}
dfs(pRootOfTree);
TreeNode* pre=new TreeNode(v[0]);
TreeNode* dummy=pre;
for(int i=1;i<v.size();i++){
TreeNode *newNode=new TreeNode(v[i]);
pre->right=newNode;
newNode->left=pre;
pre=newNode;
}
return dummy;
}
};
方法二:
依旧采取中序遍历。
根据题目的要求1,不能创建新的结点,而方法一的数组中存储的其实是结点,并不满足题意;所以需要在中序遍历的过程中,直接对结点的指针进行调整。
调整的思路如下:
(1)使用一个指针preNode指向当前结点root的前继。(例如root为指向10的时候,preNode指向8,如图所示:)
(2)对于当前结点root,有root->left要指向前继preNode(中序遍历时,对于当前结点root,其左孩子已经遍历完成了,此时root->left可以被修改。);同时,preNode->right要指向当前结点(当前结点是preNode的后继),此时对于preNode结点,它已经完全加入双向链表。
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
TreeNode* preNode;//preNode一定是全局变量。
TreeNode* Convert(TreeNode* pRootOfTree) {
if (!pRootOfTree) return pRootOfTree;
TreeNode* p = pRootOfTree;
while (p->left) p = p->left;//找到双向链表的开头。
inorder(pRootOfTree);
return p;
}
void inorder(TreeNode* root){
if (!root) return;
inorder(root->left);
//当前结点中需要进校的调整。
root->left = preNode;
if (preNode){
preNode->right = root;
}
preNode = root;//更新preNode,指向当前结点,作为下一个结点的前继。
inorder(root->right);
}
};