二叉搜索树与双向链表
题目:
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。
为了让您更好地理解问题,以下面的二叉搜索树为例:
我们希望将这个二叉搜索树转化为双向循环链表。链表中的每个节点都有一个前驱和后继指针。对于双向循环链表,第一个节点的前驱是最后一个节点,最后一个节点的后继是第一个节点。
下图展示了上面的二叉搜索树转化成的链表。“head” 表示指向链表中有最小元素的节点。
特别地,我们希望可以就地完成转换操作。当转化完成以后,树中节点的左指针需要指向前驱,树中节点的右指针需要指向后继。还需要返回链表中的第一个节点的指针。
解答:
二叉搜索树要转成有序链表,只能是中序遍历;粗糙点的方式是先利用临时链表保存该有序列,然后再将left和right指针调整,空间复杂度O(n),时间复杂度翻了一倍,不合适;可以直接在中序遍历的过程中进行左右指针的调整,状态记录利用一个全局的头指针和尾指针:
1 /* 2 // Definition for a Node. 3 class Node { 4 public int val; 5 public Node left; 6 public Node right; 7 8 public Node() {} 9 10 public Node(int _val) { 11 val = _val; 12 } 13 14 public Node(int _val,Node _left,Node _right) { 15 val = _val; 16 left = _left; 17 right = _right; 18 } 19 }; 20 */ 21 class Solution { 22 private Node head; 23 private Node tail; 24 public Node treeToDoublyList(Node root) { 25 if(root == null){ 26 return root; 27 } 28 rec(root); 29 //首尾拼接 30 tail.right = head; 31 head.left = tail; 32 return head; 33 } 34 private void rec(Node root){ 35 if(root == null){ 36 return; 37 } 38 rec(root.left); 39 if(head == null){ 40 head = root; 41 }else{ 42 tail.right = root; 43 root.left = tail; 44 } 45 //尾部跟进 46 tail = root; 47 rec(root.right); 48 } 49 }