剑指offer 37- 二叉搜索树与双向链表
2021-05-23 本文已影响0人
顾子豪
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。
要求不能创建任何新的结点,只能调整树中结点指针的指向。
注意:
- 需要返回双向链表最左侧的节点。
例如,输入下图中左边的二叉搜索树,则输出右边的排序双向链表。

分析:
算法一:对中序递归遍历的改进
1.定义一个pre指针用来保存中序遍历的前一个结点。
注:
- 中序遍历,遍历顺序就是双线链表的建立顺序;
2.递归遍历左子树
3.修改left指针和right指针(令当前结点left指针指向pre,pre的right指针指向当前结点),移动pre指针到当前结点
4.递归遍历右子树
5.最后需要一直向左找到双向链表的头结点。
/**
* 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* pre = nullptr;//这里没有违背题目要求,因为并没有开辟新的空间指向新的Node
TreeNode* head;
TreeNode* convert(TreeNode* root) {
dfs(root);
// while(root && root->left) root = root->left;
return head;
}
void dfs(TreeNode* root) {
if(!root) return;
dfs(root->left);
root->left = pre;//修改left指针
if(pre) pre->right = root;//修改right指针
else head = root;
pre = root;//移动pre指针到当前结点
dfs(root->right);
}
};
算法二:
/**
* 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* convert(TreeNode* root) {
if(!root) return root;
auto sides = dfs(root);
return sides.first;
}
pair<TreeNode*, TreeNode*> dfs(TreeNode* root) {
if(!root->left && !root->right) return {root, root};
if(root->left && root->right) {
auto lside = dfs(root->left), rside = dfs(root->right);
lside.second->right = root, root->left = lside.second;
rside.first->left = root, root->right = rside.first;
return {lside.first, rside.second};
}
if(root->left) {
auto lside = dfs(root->left);
lside.second->right = root, root->left = lside.second;
return {lside.first, root};
}
if(root->right) {
auto rside = dfs(root->right);
rside.first->left = root, root->right = rside.first;
return {root, rside.second};
}
}
};