关于剑指offer上“二叉搜索树与双向链表”题的理解

版权声明:本文为博主原创文章,转载请标明原文地址,谢谢 ^_^ https://blog.csdn.net/xiaoquantouer/article/details/77963378

题目描述:

输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。


一、递归的思路

对于函数TreeNode* Convert(TreeNode* root),传入的是需要转换的二叉树的头结点,返回的是已经转换好的双向链表的头结点。从root结点来看,以递归的思路就是将左孩子和右孩子做黑盒处理,left = Convert(root->left)返回的就是以左孩子为根节点的树已经转化好的双向链表的头结点,right = Convert(root->right)返回的就是以右孩子为根节点的树已经转化好的双向链表的头结点,只要left和right不为空,使用left找到左孩子双向链表的最后一个结点node,将node,root,right一连接,问题解决!


步骤:

1、根节点为root,递归root的左孩子,将左子树构成双向链表,并返回链表头结点left

2、使用left头结点遍历到左子树双链表的最后一个结点node

3、如果左子树链表不为空,将node和root连接起来

4、同理将右子树构成双向链表,并返回链表头结点right

5、如果右子树链表不为空,将root和right连接起来

6、如果left不为空,返回left,否则返回root


代码如下:

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
public:
    TreeNode* Convert(TreeNode* root)
    {
        if(root == NULL){
            return NULL;
        }
        if(root->left == NULL && root->right == NULL){
            return root;
        }
        //1、根节点为root,递归root的左孩子,将左子树构成双向链表,并返回链表头结点left
        TreeNode* left = Convert(root->left);
        TreeNode* node = left;
        //2、使用left头结点遍历到左子树双链表的最后一个结点node
        while(node != NULL && node->right != NULL){
            node = node->right;
        }//while
        //3、如果左子树链表不为空,将node和root连接起来
        if(left != NULL){
            node->right = root;
            root->left = node;
        }
        //4、同理将右子树构成双向链表,并返回链表头结点right
        TreeNode* right = Convert(root->right);
        //5、如果右子树链表不为空,将root和right连接起来
        if(right != NULL){
            root->right = right;
            right->left = root;
        }
        //6、如果left不为空,返回left,否则返回root
        return left == NULL?root:left;
    }
};


二、非递归思路

按照二叉树中序遍历非递归的思路


代码:

struct TreeNode{
    int val;
    TreeNode* left;
    TreeNode* right;
};

//对比,二叉树的非递归中序遍历求法
void inorder(TreeNode* root){
    //非递归版中序遍历
    if(NULL == root){
        return;
    }
    stack<TreeNode*> data;
    TreeNode* node = root;
    while(node!=NULL || !data.empty()){
        while(node != NULL){
            data.push(node);
            node = node->left;
        }//while
        if(!data.empty()){
            node = data.top();
            data.pop();
            cout<<node->val<<endl;
            node = node->right;
        }
    }//while
    return;
}

TreeNode* Convert(TreeNode* root){
    if(NULL == root){
        return NULL;
    }
    if(root->left == NULL && root->right == NULL){
        return root;
    }
    stack<TreeNode*> data;
    TreeNode* node = root;
    TreeNode* pre = NULL;  //用于保存中序遍历序列的上一个结点
    bool isFirst = true;
    while(node != NULL || !data.empty()){
        while(node != NULL){
            data.push(node);
            node = node->left;
        }
        node = data.top();
        data.pop();
        if(isFirst){
            root = node;   //将中序遍历中的第一个结点记为root
            pre = root;
            isFirst = false;
        }else{
            pre->right = node;
            node->left = pre;
            pre = node;
        }
        node = node->right;
    }
    return root;
}


牛客网题目地址:

https://www.nowcoder.com/practice/947f6eb80d944a84850b0538bf0ec3a5?tpId=13&tqId=11179&rp=2&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking


猜你喜欢

转载自blog.csdn.net/xiaoquantouer/article/details/77963378