前驱节点
前驱节点的值小于该节点的值,是该节点左子树中值最大的
后继节点
后继节点的值大于该节点的值,是该节点右子树中值最小的
因为二叉搜索树的中序遍历出来的结果就是一棵树节点上的值的升序排序,所以一个数的前驱节点的值就是比它小一个的数,后继节点的值就是比它大一个的节点
找前驱节点有以下情况:
(1) 该节点有左子树,那么该节点的前驱节点就是其左子树中最大的那个。例如 10 它有左孩子,它的前驱节点就是左孩子中最大的也就是 8 。
(2) 该节点没有左子树,那么就又有两种情况: 1. 该节点是其父节点的右孩子,那么它的前驱就是他的父节点; 例如 17 它的前驱就是16
2. 该节点是其父节点的左孩子,那么就得往其祖辈寻找直到找到它祖辈是左孩子为止,如果没找到,那么说明该节点没有前驱节点。 例如 8 它是左孩子,所以它的前驱不是它的父亲,就得往上找,
而它的父亲是他爷爷的右孩子,所以 8 的前驱就应该是它的爷爷 7 。
找后继节点有以下情况:
(1) 该节点有右子树,那么该节点的后继节点就是其右子树中最小的那个。例如 10 它有右子树 它的后继就是右子树中最小的那个 14 。
(2) 该节点没有右子树,那么它的后继节点也要往祖辈里面找,也是分两种情况 : 1. 该节点是其父节点的左子树,那么它的后继节点就是他的父亲; 2. 该节点是父节点的左子树,
那么往上找,直到找到该节点的祖辈是左孩子为止,如果找不到,那么该节点没有后继节点。例如图中的 17 它是父亲的右孩子,往上找,发现它父亲也是它爷爷的右孩子,而它爷爷没有父辈了,所以该节点没有后继。
具体java实现的代码如下:
1 /** 2 * 找给定节点的后继节点 3 * @param node 给定树中的节点 4 * @return 返回该节点存在中序遍历顺序下的后继节点,有则返回后继节点,无则返回null 5 * 6 */ 7 public TreeNode successor(TreeNode node){ 8 if(node==null){ return null;} 9 //若该节点的右子树不为空,则后继节点就是右子树中的最小关键字节点 10 if(node.rightChild!=null){ 11 try { 12 return minElemNode(node.rightChild); 13 } catch (Exception e) { 14 e.printStackTrace(); 15 } 16 } 17 //若该节点右子树为空 18 TreeNode parentNode=node.parent; 19 while(parentNode !=null && node==parentNode.rightChild){ 20 node=parentNode; 21 parentNode=parentNode.parent; 22 } 23 return parentNode; 24 } 25 26 /** 27 * 找出给定节点的后继节点 28 * @param node 给定节点 29 * @return 后继节点 30 */ 31 public TreeNode precessor(TreeNode node) throws Exception { 32 if(node==null){ return null;} 33 //若该节点有左子树,则前驱节点就是左子树中最大的那个 34 if(node.leftChild!=null){return maxElemNode(node.leftChild);} 35 //若该节点没有左子树 36 TreeNode parentNode=node.parent; 37 if(parentNode!=null&&node==parentNode.leftChild){ 38 node=parentNode; 39 parentNode=parentNode.parent; 40 } 41 return parentNode; 42 }