面试题36:二叉搜索树与双向链表(C++)

题目地址:https://leetcode-cn.com/problems/er-cha-sou-suo-shu-yu-shuang-xiang-lian-biao-lcof/

题目描述:

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

题目示例:

二叉搜索树转为双向链表

我们希望将这个二叉搜索树转化为双向循环链表。链表中的每个节点都有一个前驱和后继指针。对于双向循环链表,第一个节点的前驱是最后一个节点,最后一个节点的后继是第一个节点。

 

特别地,我们希望可以就地完成转换操作。当转化完成以后,树中节点的左指针需要指向前驱,树中节点的右指针需要指向后继。还需要返回链表中的第一个节点的指针。 

解题思路

思路1:分析题目可知,首先,循环链表顺序是单调递增,所以,观察二叉搜索树的三种遍历方式,发现二叉搜索树的中序遍历(左子树->根节点->右子树)满足条件,即从小到大遍历树的节点,然后,考虑循环链表的指向问题,这里我们使用双指针pre和head,其中pre表示前驱节点,head表示头节点,cur表示当前节点,tail表示尾节点,则双向链表的指向问题可以表示为pre->right=cur;cur->left=pre;这样我们就构造好了双向链表,最后就是循环链表的问题了,将尾节点的左指针指向头节点,头节点的右指针指向尾节点,即head->left=tail;tail->right=head。

思路2:类似于思路1,不过这里使用数组arr存储中序遍历的每个节点,这样arr数组中元素顺序单调递增,然后利用一层循环使得相邻元素连接构成双向链表,最后改变首尾元素的指向,即可得到循环双向链表。

程序源码

中序遍历+递归

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* left;
    Node* right;

    Node() {}

    Node(int _val) {
        val = _val;
        left = NULL;
        right = NULL;
    }

    Node(int _val, Node* _left, Node* _right) {
        val = _val;
        left = _left;
        right = _right;
    }
};
*/
class Solution {
public:
    Node* pre = nullptr, *head = nullptr, *tail = nullptr;
    Node* treeToDoublyList(Node* root) {
        if(root == nullptr) return nullptr;
         inorder(root);
         //连接首尾节点
         head->left = tail;
         tail->right = head;
         return head;
    }
    void inorder(Node* cur)
    {
        if(cur == nullptr) return; //递归出口
        inorder(cur->left); //遍历左子树
        if(pre != nullptr) pre->right = cur;
        else head = cur;
        cur->left = pre;
        pre = cur;
        tail = cur;
        inorder(cur->right); //遍历右子树
    }
};

数组

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* left;
    Node* right;

    Node() {}

    Node(int _val) {
        val = _val;
        left = NULL;
        right = NULL;
    }

    Node(int _val, Node* _left, Node* _right) {
        val = _val;
        left = _left;
        right = _right;
    }
};
*/
class Solution {
public:
    vector<Node*> arr;
    Node* treeToDoublyList(Node* root) {
        if(root == nullptr) return nullptr;
         inorder(root);
         for(int i = 0; i < arr.size() - 1; i++)
         {
             arr[i]->right = arr[i + 1];
             arr[i + 1]->left = arr[i];
         }
         arr[arr.size() - 1]->right = arr[0];
         arr[0]->left = arr[arr.size() - 1];
         return arr[0];
    }
    void inorder(Node* cur)
    {
        if(cur == nullptr) return; //递归出口
        inorder(cur->left); //遍历左子树
        arr.push_back(cur); //装入当前节点
        inorder(cur->right); //遍历右子树
    }
};

参考文章

https://leetcode-cn.com/problems/er-cha-sou-suo-shu-yu-shuang-xiang-lian-biao-lcof/solution/mian-shi-ti-36-er-cha-sou-suo-shu-yu-shuang-xian-5/

----------------------------------- 心之所向,素履所往;生如逆旅,一苇以航。 ------------------------------------------
原文地址:https://www.cnblogs.com/wzw0625/p/12796134.html