题目
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
思路
考虑不能创建结点,不能辅助空间。使用递归,输出顺序为中序遍历顺序。使用一个辅助指针记录当前结点的上一个结点,从左子树开始调整。
示例
7
/ \
5 10
/ \ / \
3 6 8 12
\ \ /
4 9 11
输入:
通过前序和中序确定一棵搜索二叉树:
前序: 7,5,3,4,6,10,8,9,12,11
中序: 3,4,5,6,7,8,9,10,11,12
输出:
链表元素从头(小)到尾(大)的顺序分别为:
3 4 5 6 7 8 9 10 11 12
代码
#include <iostream>
#include <vector>
using namespace std;
struct TreeNode {
int val;
TreeNode *left, *right;
TreeNode(int x):
val(x),left(nullptr),right(nullptr){
}
};
class Solution {
public:
// 把一棵树通过改变指针变成成一个双链表
TreeNode* PrintMidOder(TreeNode* root){
if (!root)
return root;
// 标记当前根节点位置
TreeNode* re(root);
// 记录当前结点的前一个结点的指针
TreeNode* pre(nullptr);
PrintMidOderAuxiliary(root,pre);
// 找到做左(小)元素,即链表头指针
while (re->left)
re = re->left;
return re;
}
void PrintMidOderAuxiliary(TreeNode* current, TreeNode* &pre){
// 当前结点为空则直接返回
if (!current)
return;
// 先调整当前结点的左子树的指针
PrintMidOderAuxiliary(current->left, pre);
// 把前一个结点设为当前结点的左孩子
current->left = pre;
// 把前一个结点的右孩子设为当前结点
if (pre)
pre->right = current;
// 把当前结点设为前一个结点,开始下一轮调整
pre = current;
// 调整右子树
PrintMidOderAuxiliary(current->right, pre);
}
// 利用前序和中序序列新建一棵树用来测试
TreeNode* CreateTree(vector<int> pre, vector<int> mid){
TreeNode* root(nullptr);
if (!pre.size() || !mid.size())
return root;
root = CreateTree(pre, 0, pre.size()-1, mid, 0, mid.size()-1);
return root;
}
private:
TreeNode* CreateTree(vector<int> pre, int pre_start, int pre_end, vector<int> mid, int mid_start, int mid_end){
TreeNode *root = new TreeNode(0);
if (pre_start > pre_end || mid_start > mid_end)
return nullptr;
for (int i = mid_start; i < mid_end+1; ++i) {
if (mid[i] == pre[pre_start]){
root->val = mid[i];
root->left = CreateTree(pre,pre_start+1, i-mid_start+pre_start, mid, mid_start, i-1);
root->right = CreateTree(pre,i-mid_start+pre_start+1, pre_end, mid, i+1, mid_end);
break;
}
}
return root;
}
};
int main(){
Solution re;
TreeNode *root(nullptr);
vector<int> pre = {7,5,3,4,6,10,8,9,12,11};
vector<int> mid = {3,4,5,6,7,8,9,10,11,12};
root = re.CreateTree(pre,mid);
if (!root)
return 1;
TreeNode* result = re.PrintMidOder(root);
cout << "链表元素从头(小)到尾(大)的顺序分别为: " << endl;
while (result){
cout << result->val << " ";
result = result->right;
}
cout << endl;
}