zoukankan      html  css  js  c++  java
  • 25 二叉搜索树与双向链表

    题目描述

    输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
     
    思路:分为循环版本和递归版本。
    循环版本:
    二叉搜索树的中序遍历就是递增序列,所以本题本质就是中序遍历。有两点非常需要注意:
    1)开始自己认为需要对链表的首尾节点进行特殊处理,比如开始节点需要left指向nullptr,但是画个图就会非常明显,中序遍历是左中右的顺序,所以头节点是遍历到最左边的叶子节点才开始处理,此时头结点left和right指针都指向nullptr,同理尾节点也是一样的,所以不需要进行特殊处理,需要注意的时候因为最后需要返回一个头节点,所以需要一个bool变量记录第一次遍历得到的头结点保存起来,后面进行return。
    2)开始自己想的是将中序遍历的结果使用一个数组保存下来,但是不需要这么做,只需要遍历的过程中,进行交换即可,一个传入的root变量,一个pre节点,
     
    root -> left = pre;
    pre -> right = 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* pRootOfTree){
            if(pRootOfTree == nullptr){
                return nullptr;
            }
            //inorder
            stack<TreeNode*> s; 
            TreeNode* pre = nullptr;
            TreeNode* root = pre;
            bool isFirst = true;
            while(!s.empty() || pRootOfTree != nullptr){
                while(pRootOfTree != nullptr){
                    s.push(pRootOfTree);
                    pRootOfTree = pRootOfTree -> left;
                                    
                }
                if(!s.empty()){
                   pRootOfTree = s.top();
                   s.pop();              
                   if(isFirst){
                       isFirst = false;
                       pre = pRootOfTree;
                       root = pre;
                        
                    }
                    else{//举例子,最左边的最右边的节点都是叶子节点,左右都是指向null,所以不需要特殊处理
                        pre -> right = pRootOfTree;
                        pRootOfTree -> left = pre;
                        pre = pRootOfTree;
                    }
                   pRootOfTree = pRootOfTree -> right;
                }
            }
             
            return root;
        }
    };

    2、递归版本

    将左子树转换为有序双向链表,然后找到左子树对应链表的最后一个节点leftLast,将leftLast和root节点连接起来,然后对右子树进行同样的处理,得到右子树对应的链表头结点是rightHead,将root和rightHead连接起来,放回结果的时候需要判断leftHead是否为空,为空的时候需要返回root。

    这里关键的理解就是helper这个递归函数每次返回的是一个链表的头结点,不管是左子树还是右子树调用返回的都是对应部分的头结点。

    /*
    struct TreeNode {
        int val;
        struct TreeNode *left;
        struct TreeNode *right;
        TreeNode(int x) :
                val(x), left(NULL), right(NULL) {
        }
    };*/
    class Solution {
    public:
        TreeNode* helper(TreeNode* root){
            if(root == nullptr){
                return nullptr;
            }
            TreeNode* leftHead = helper(root -> left);
            TreeNode* leftLast = leftHead;
            if(leftLast != nullptr){
                while(leftLast != nullptr && leftLast -> right != nullptr){//find last left node 
                    leftLast = leftLast -> right;
                }
                leftLast -> right = root;
                root -> left = leftLast;
            }
            
            TreeNode* rightHead = helper(root -> right);
            if(rightHead != nullptr){
                root -> right = rightHead;
                rightHead -> left = root;
            }
            
            return (leftHead != nullptr) ? leftHead : root;
        }
        TreeNode* Convert(TreeNode* pRootOfTree){
           if(pRootOfTree == nullptr){
               return nullptr;
           } 
           return helper(pRootOfTree);
        }
    };
  • 相关阅读:
    jquery 实现 html5 placeholder 兼容password密码框
    php返回json的结果
    使用PHP读取远程文件
    Sharepoint 自定义字段
    Sharepoint 中新增 aspx页面,并在页面中新增web part
    【转】Sharepoint 2010 配置我的站点及BLOG
    JS 实现 Div 向上浮动
    UserProfile同步配置
    【转】Import User Profile Photos from Active Directory into SharePoint 2010
    Sharepoint 2010 SP1升级后 FIMSynchronizationService 服务无法开启
  • 原文地址:https://www.cnblogs.com/dingxiaoqiang/p/8025090.html
Copyright © 2011-2022 走看看