搜索
写经验 领红包
 > 财经

二叉搜索树与双向链表(双向链表和二叉链表的区别)

导语:算法系列之双向链表和二叉搜索树

二叉搜索树与双向链表(双向链表和二叉链表的区别)

01 题目描述

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

树结构的定义如下

class BinaryTreeNode { int value; BinaryTreeNode leftChild; BinaryTreeNode rightChild; BinaryTreeNode(){ } BinaryTreeNode(BinaryTreeNode leftChild, BinaryTreeNode rightChild, int value){ this.leftChild = leftChild; this.rightChild = rightChild; this.value = value; }}

双向链表和树结构有着相同的结果,所以我们用leftNode表示链表的前一个节点。rightNode表示链表的下一个节点。

02 解题

看到此题,我们首先回忆一下二叉搜索树的性质

左孩子节点的值 < 根节点 < 右孩子节点,我们按照中序遍历得到的结果刚好就是有序的。

我们可以在中序遍历的同时,将二叉搜索树转换为双向链表吗?

现在我们尝试在遍历的过程中,将二叉搜索树转为双向链表。

1.首先循环遍找到第一个节点,最左节点4

当前被访问的变量currentNode=4;因为它是第一个节点,所以currentNode.leftNode=null;

下一个需要访问的节点还不确定,所以currentNode的rightNode不确定。

2.回退到节点6 currentNode=6

6的前一个节点(leftChild)是它的左孩子节点4.

那么对于下图这种情况,6的前一个节点应该是多少呢?读者考虑下

对于节点6的左子树来说,中序遍历的最后一个节点5,所以6的前一个节点(leftChild)应该是5。

思考下,怎么才能把6的leftChild指针,连到5上呢?

我们需要一个变量lastVisitNode记录上一次被访问到的节点,那么lastVisitNode=5或者4。

然后我们就可以方便的赋值了

currentNode.left=lastVisitNode;

lastVisitNode.right = currentNode.

3.在访问完节点6之后,6存在右孩子节点,所以此时应该访问6的右孩子节点8。

lastVisitNode=6;

currentNode=8;

currentNode.left=lastVisitNode;

lastVisitNode.right = currentNode. 将 6和8互连。

4. 8节点访问完,回到节点10. 重复同样的步骤

5.接下来访问12节点。10节点访问完,按照中序遍历,应该访问右孩子节点上的最左节点即12节点。 10的右孩子节点为12,12的右孩子节点为10

lastVisitNode = 10;

currentNode= 12;

执行连接操作

currentNode.left=lastVisitNode;

lastVisitNode.right = currentNode.

6.按照上述操作执行到将树节点访问完。

03 总结

通过上述步骤的分析当中,我们可以发现,对于一个节点A来说

最后一个被访问到的节点永远都是A的前一个节点。A.pre = lastVisitNode

最后一个被访问的节点的下一个节点时A. lastVisitNode.next = A;

遍历过程为中序遍历。

04 代码

转换代码public static BinaryTreeNode convert(BinaryTreeNode currentNode, BinaryTreeNode pLastVisitNode) { if (currentNode == null) { return null; } // 遍历最左节点 if (currentNode.leftChild != null) { pLastVisitNode = convert (currentNode.leftChild, pLastVisitNode); } // 更新当前节点的前一个节点为pLastVisitNode currentNode.leftChild = pLastVisitNode; if (pLastVisitNode != null) { pLastVisitNode.rightChild = currentNode; } // 更新最后一个被访问为当前节点。 pLastVisitNode = currentNode; // 访问右孩子节点 if (currentNode.rightChild != null) { pLastVisitNode = convert(currentNode.rightChild, pLastVisitNode); } return pLastVisitNode;}

调用代码:

public static BinaryTreeNode convertToDoublyLinked(BinaryTreeNode root) { BinaryTreeNode pHead = root; while (pHead.leftChild != null) { pHead = pHead.leftChild; } convert(root, null); return pHead;}

测试用例

 public static void main(String[] args) { // 边界一测试 =纯左子节点 BinaryTreeNode treeNode0 = new BinaryTreeNode(null, null, 0); BinaryTreeNode treeNode11 = new BinaryTreeNode(treeNode0, null, 1); BinaryTreeNode treeNode12 = new BinaryTreeNode(treeNode11, null, 2); BinaryTreeNode treeNode13 = new BinaryTreeNode(treeNode12, null, 3); BinaryTreeNode treeNode14 = new BinaryTreeNode(treeNode13, null, 4); BinaryTreeNode treeNode15 = new BinaryTreeNode(treeNode14, null, 5); BinaryTreeNode treeNode16 = new BinaryTreeNode(treeNode15, null, 6); BinaryTreeNode treeNode17 = new BinaryTreeNode(treeNode16, null, 7); BinaryTreeNode head = convertToDoublyLinked(treeNode17); // 边界2测试 纯右孩子节点 BinaryTreeNode treeNode27 = new BinaryTreeNode(null, null, 7); BinaryTreeNode treeNode26 = new BinaryTreeNode(null, treeNode27, 6); BinaryTreeNode treeNode25 = new BinaryTreeNode(null, treeNode26, 5); BinaryTreeNode treeNode24 = new BinaryTreeNode(null, treeNode25, 4); BinaryTreeNode treeNode23 = new BinaryTreeNode(null, treeNode24, 3); BinaryTreeNode treeNode22 = new BinaryTreeNode(null, treeNode23, 2); BinaryTreeNode treeNode21 = new BinaryTreeNode(null, treeNode22, 1); BinaryTreeNode treeNode01 = new BinaryTreeNode(null, treeNode21, 0); BinaryTreeNode head01 = convertToDoublyLinked(treeNode01); // 普通的二叉搜索树// BinaryTreeNode treeNode37 = new BinaryTreeNode(null, null, 7); BinaryTreeNode treeNode36 = new BinaryTreeNode(null, null, 16); BinaryTreeNode treeNode35 = new BinaryTreeNode(null, null, 12); BinaryTreeNode treeNode34 = new BinaryTreeNode(null, null, 8); BinaryTreeNode treeNode33 = new BinaryTreeNode(null, null, 4); BinaryTreeNode treeNode32 = new BinaryTreeNode(treeNode35, treeNode36, 14); BinaryTreeNode treeNode31 = new BinaryTreeNode(treeNode33, treeNode34, 6); BinaryTreeNode treeNode03 = new BinaryTreeNode(treeNode31, treeNode32, 10); BinaryTreeNode head02 = convertToDoublyLinked(treeNode03); }

本文内容由快快网络小快创作整理编辑!