java前驱后继,数据结构-二叉搜索树的前驱和后继节点

什么是二叉树的前驱节点和后继节点?

某节点的前驱节点的val值小于该节点的val值并且值是最大的那个节点。

某节点的后继节点的val值大于该节点的val值并且值是最小的那个节点。

下面给出一个二叉树节点类,和一个例子来说明。

package com.dzqc.yx.tree;

/**

* 节点类

* @author jiajia

* @param

* @param

*/

public class Node {

/**

* 用于查找数据时比较的key

*/

public Integer key;

/**

* 数据

*/

public E e;

/**

* 父节点引用

*/

public Node parent;

/**

* 左子节点引用

*/

public Node left;

/**

* 右子节点引用

*/

public Node right;

public Node(Integer key, E e) {

super();

this.key = key;

this.e = e;

}

public Node(Integer key, E e, Node parent) {

super();

this.key = key;

this.e = e;

this.parent = parent;

}

public E setValue(E e) {

return this.e=e;

}

}

a1e7e277d4f34d087ef2f7d4557c39f5.png

如上图:

1的前驱节点是0,4的前驱节点是3,6的前驱节点是5,3的前驱节点是2.

7的后继节点是8,9的后继节点是10,4的后继节点是5,2的后继节点是3

注意:上述的节点类都有对父节点的引用,如果没有父节点的引用将会用先序遍历的方式求,将会加大时间复杂度。

算法过程

某节点的前驱节点

若该节点有左子树,那么该节点的前驱节点是其左子树中val值最大的那个节点。

若该节点没有左子树,则判断该节点和其父节点的关系。

若该节点是其父节点的右子树,那么该节点的前驱结点就是其父节点。

若该节点是其父节点的左子树,那么沿着其父亲节点一直向树的顶端寻找,直到找到一个节点P,P节点是其父节点Q的右子树,那么节点Q就是该节点的后继节点。

某节点的后继节点

若该节点有右子树,那么该节点的后继节点是其右子树中val值最小的那个节点。

若该节点没有右子树,则判断该节点和其父节点的关系。

若该节点是其父节点的左子树,那么该节点的后继结点就是其父节点  。

若该节点是其父节点的右子树,那么沿着其父亲节点一直向树的顶端寻找,直到找到一个节点P,P节点是其父节点Q的左子树,那么节点Q就是该节点的后继节点。

java代码实现

前驱节点代码实现

/**

* 寻找前驱节点

* @param t

* @return

*/

public Node precursor(Node t){

if(t!=null) {

if(t.left!=null) {

Node p=t.left;

while(p.right!=null)

p=p.right;

return p;

}else {

if(t==t.parent.right) {

return t.parent;

}else {

Node p=t.parent;

while(p!=null&&p!=p.parent.right) {

p=p.parent;

}

return p.parent;

}

}

}else {

return null;

}

}

前驱节点测试

/**

* 前驱节点

*/

@Test

public void test24() {

Node n6=new Node<>(6,6,null);

Node n1=new Node<>(1,1,n6);

Node n5=new Node<>(5,5,n1);

Node n3=new Node<>(3,3,n5);

Node n2=new Node<>(2,2,n3);

Node n4=new Node<>(4,4,n3);

Node n7=new Node<>(7,7,n6);

Node n9=new Node<>(9,9,n7);

Node n8=new Node<>(8,8,n9);

Node n10=new Node<>(10,10,n9);

n6.left=n1;

n6.right=n7;

n1.right=n5;

n5.left=n3;

n3.left=n2;

n3.right=n4;

n7.right=n9;

n9.left=n8;

n9.right=n10;

System.out.println(precursor(n10).key);

}

后继节点代码实现

/**

* 寻找后继节点

* @param t

* @return

*/

public Node successor(Node t) {

if (t == null)

return null;

else if (t.right != null) {

Node p = t.right;

while (p.left != null)

p = p.left;

return p;

} else {

Node p = t.parent;

Node ch = t;

while (p != null && ch == p.right) {

ch = p;

p = p.parent;

}

return p;

}

}

后继节点测试

/**

* 后继节点

*/

@Test

public void test23() {

Node n6=new Node<>(6,6,null);

Node n1=new Node<>(1,1,n6);

Node n5=new Node<>(5,5,n1);

Node n3=new Node<>(3,3,n5);

Node n2=new Node<>(2,2,n3);

Node n4=new Node<>(4,4,n3);

Node n7=new Node<>(7,7,n6);

Node n9=new Node<>(9,9,n7);

Node n8=new Node<>(8,8,n9);

Node n10=new Node<>(10,10,n9);

n6.left=n1;

n6.right=n7;

n1.right=n5;

n5.left=n3;

n3.left=n2;

n3.right=n4;

n7.right=n9;

n9.left=n8;

n9.right=n10;

System.out.println(successor(n10));

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值