一、二叉树结点定义类TreeNode:
class TreeNode{
public int data;
public TreeNode left;
public TreeNode right;
TreeNode(int data){
this.data=data;
}
}
二、插入新的节点这里介绍两种方法,递归与非递归方式:
1.递归方式
<span style="font-size:18px;"> <span style="color:#ff0000;">//添加节点(递归模式)</span>
public static boolean AddTreeNode1(TreeNode root, int data){
TreeNode treeNode=new TreeNode(data);
<span style="color:#ff0000;">//树为空</span>
if(root==null){
root=treeNode;
return true;
}
<span style="color:#ff0000;">//比根节点小,插入到左子树</span>
if(root.data>data){
if(root.left==null){
root.left=treeNode;
return true;
}else
return AddTreeNode1(root.left, data);
}else if(root.data<data){ <span style="color:#ff0000;">//比根节点大,插入到右子树</span>
if(root.right==null){
root.right=treeNode;
return true;
}else
return AddTreeNode1(root.right,data);
}else
return false;
}</span><span style="background-color: rgb(255, 255, 255);"><span style="font-size:18px;"> 点击打开链接</span></span>
2.非递归方式(迭代)
<span style="font-size:18px;"> <span style="color:#ff0000;"> //增加节点非递归模式</span>
public static boolean AddTreeNode2(TreeNode root, int data){
<span style="color:#ff0000;">//树为空</span>
if(root==null){
root=new TreeNode(data);
return true;
}
TreeNode treeNode=new TreeNode(data);
TreeNode currNode=root;
while(true){
if(currNode.data>data){
if(currNode.left!=null)
currNode=currNode.left;
else{
currNode.left=treeNode;
return true;
}
}else if(currNode.data<treeNode.data){
if(currNode.right!=null)
currNode=currNode.right;
else {
currNode.right=treeNode;
return true;
}
}else
return false;
}
}</span>
三、查找:
public static boolean SearchTreeNode(TreeNode root, int data){
if(root==null){
return false;
}else if(root.data==data){
return true;
}else if(root.data>data){
return SearchTreeNode(root.left,data);
}else{
return SearchTreeNode(root.right,data);
}
}
四、删除
删除可为BST问题最为复杂的一部分,需要考虑一下要删除的节点的四种情况:
(1)该节点为叶子节点,删除即可
(2)该节点只有左子树,没有右子树,删除后将该节点的左子树连接到该节点的父节点(主要判断该节点为左节点还是右节点)
(3)该节点只有右子树,没有左子树,删除后将该节点的右子树连接到该节点的父节点(主要判断该节点为左节点还是右节点)
(4)该节点既有左子树,也有右子树,这时候删除比较复杂,可以分为两种情况:
首先,我们知道二叉排序树经过中序遍历后得到的是一个递增有序序列,该节点的前一个即为直接前驱,后一个为直接后继。我们要得到直接前驱和直接后继的节点。
方法一:a.得到该删除节点的左节点,如果此左节点没有右节点,则该左节点即为直接前驱;
b.左节点有右节点,则一直沿最右侧右节点迭代下去,最后面的那个即为直接前驱。
方法二:a.得到该删除节点的右节点,如果此右节点没有左节点,则该右节点即为直接后继;
b.右节点有左节点,则一直沿最左侧左节点迭代下去,最后面的那个即为直接后继。
以上四种情况均要考虑要删除的节点为根节点root的情况。
源代码如下:
<span style="color:#ff0000;"> //删除</span>
public static boolean DeleteNode(TreeNode root, int data){
<span style="color:#ff0000;"> //current为查找得到的节点</span>
TreeNode current=root;
//parent为时刻更新父节点
TreeNode parent=root;
<span style="color:#ff0000;"> //tempParent为同时存在左右子树的迭代临时父节点</span>
TreeNode tempParent=root;
<span style="color:#ff0000;">//isLeft记录current节点的左右属性</span>
boolean isLeft=true;
while(current.data!=data){
parent=current;
<span style="color:#ff0000;">//到左子树查找</span>
if(current.data>data){
isLeft=true;
current=current.left;
}else if(current.data<data){ <span style="color:#ff0000;">//到右子树查找</span>
isLeft=false;
current=current.right;
}
<span style="color:#ff0000;">//查不到,返回false</span>
if(current==null)
return false;
}
<span style="color:#ff0000;">//第一种情况:删除节点为叶节点</span>
if(current.left==null && current.right==null){
if(current==root)
root=null;
if(isLeft) {
parent.left = null;
}else{
parent.right = null;
}
return true;
}else if(current.right==null){ <span style="color:#ff0000;"> //第二种情况:删除节点只有左节点</span>
if(current==root)
root=current.left;
else if(isLeft)
parent.left=current.left;
else
parent.right=current.left;
return true;
}else if(current.left==null){ <span style="color:#ff0000;"> //第三种情况:删除节点只有右节点</span>
if(current==root)
root=current.right;
else if(isLeft)
parent.left=current.right;
else
parent.right=current.right;
return true;
}else{ <span style="color:#ff0000;">//第四种情况:删除节点均存在左节点和右节点</span>
if(current==root){
root=root.left;
}
TreeNode tempNode=current.left;
<span style="color:#ff0000;">//没有左节点</span>
if(tempNode.right==null){
if(isLeft)
parent.left=tempNode;
else
parent.right=tempNode;
}else{ <span style="color:#ff0000;">//存在左节点,迭代到最右侧子节点,即直接前驱</span>
while(tempNode.right!=null){
tempParent=tempNode;
tempNode=tempNode.right;
}
if(isLeft){ <span style="color:#ff0000;">//为左节点,连接</span>
parent.left=tempNode;
parent.left.left=current.left;
}else{ <span style="color:#ff0000;">//为右节点,连接</span>
parent.right=tempNode;
parent.right.left=current.left;
}
<span style="color:#ff0000;">//删除前驱节点,连接</span>
if(tempNode.left==null)
tempParent.right=null;
else
tempParent.right=tempNode.left;
}
return true;
}
}
五、二叉树中序遍历
//二叉树中序遍历
public static void midSort(TreeNode root){
if(root==null){
return;
}
midSort(root.left);
System.out.print(root.data+" ");
midSort(root.right);
}
六、由二叉排序树得到最小值(最大值同理,未加)
//由二叉排序树得到最小值
public static int getMin(TreeNode root){
if(root.left==null) {
return root.data;
}else{
return getMin(root.left);
}
}
综上,测试主函数代码如下:
public static void main(String[] args){
int[] a=new int[]{62,88,58,47,35,73,51,99,37,93};
TreeNode root=new TreeNode(a[0]);
for(int i=1; i<a.length; i++){
AddTreeNode1(root, a[i]);
}
System.out.println("中序遍历结果为:");
midSort(root);
System.out.println("47存在:"+SearchTreeNode(root,47));
AddTreeNode1(root,100);
System.out.println("添加100后,中序遍历结果为:");
midSort(root);
System.out.println("添加100后,100存在:"+SearchTreeNode(root,100));
输出结果为:
中序遍历结果为:
35 37 47 51 58 62 73 88 93 99 47存在:true
添加100后,中序遍历结果为:
35 37 47 51 58 62 73 88 93 99 100 添加100后,100存在:true
删除100后,中序遍历结果为:
35 37 47 51 58 62 73 88 93 99 删除100后,100存在:false
参考博文链接