二叉查找树特点:
1、如果它的左子树不为空,则左子树节点的值都小于根节点。
2、如果它的右子树不为空,则左子树节点的值都大于根节点。
3、子树同样也要遵循以上两点
4、中序遍历有序。
5、后继节点:根据中序找第一个比当前节点大的数
6、前继节点:根据中序找第一个比当前节点小的数
二叉树增删查;
1、增:插入的时候每次都是和根节点比较。一直要找到它应该插入的位置,并且只能插在叶子节点上(O(nlogn))
2、删:
1、叶子节点可以直接删除(O(1))
2、要删除的结点只有一个子树(O(1))。
3、删除的结点有两个子树:找后继结点,而且后继结点左子树一定为空(O(logn))。
3、查询(O(logn))
package com.example.demo;
public class MyTwoQueryTree {
int data;
private MyTwoQueryTree left;
private MyTwoQueryTree right;
public MyTwoQueryTree(int data){
this.data = data;
this.left = null;
this.right = null;
}
/**
* 插入
*/
public void insert(MyTwoQueryTree root,int data){
//大于根放右
if(root.data < data){
if(root.right == null){
root.right = new MyTwoQueryTree(data);
}else {
insert(root.right,data);
}
}else{ //其它放左
if(root.left == null){
root.left = new MyTwoQueryTree(data);
}else {
insert(root.left,data);
}
}
}
/**
* 查询
* @param root
* @param data
*/
public void query(MyTwoQueryTree root,int data){
if(root != null){
if(root.data < data){
query(root.right,data);
}else if(root.data > data){
query(root.left,data);
}else {
System.out.println("值为:"+root.data);
return;
}
}else {
System.out.println("值为:"+data+"不存在");
}
}
/**
* 根节点删除
* @param root
* @param no
* @return
*/
public boolean deleteRoot(MyTwoQueryTree root,int no) {
// 要删除的节点是根节点
if (root.data == no) {
// 要删除的根节点,没有左子树和右子树
if (root.left == null && root.right == null) {
root = null;
// 要删除的根节点,都有左右子树
} else if (root.left != null && root.right != null) {
MyTwoQueryTree left = root.left;
root = root.right;// 实现删除原来的 root
combinationBinaryTreeTry(root, left);
// 要删除的根节点,只有左子树
} else if (root.left != null) {
root = root.left;
// 要删除的根节点,只有右子树
} else {
root = root.right;
}
return true;
}
return false;
}
public void combinationBinaryTreeTry(MyTwoQueryTree parent, MyTwoQueryTree left) {
// 如果parent的左子节点为空,那么left的no 一定小于等于 parent的no
if (parent.left == null) {
parent.left = left;
// 如果这个条件满足,证明parent的左子节点不为空,那么left的no 一定小于等于 parent的no
// 所以left不能作为parent右子节点
} else if (parent.right == null) {
combinationBinaryTree(parent.left, left);
// parent的左右子节点不为空
} else {
combinationBinaryTree(parent.left, left);
}
}
/**
*
* @param parent
* @param child
* @return
*/
public boolean combinationBinaryTree(MyTwoQueryTree parent, MyTwoQueryTree child) {
int childNo = child.data;
int parentNo = parent.data;
// 如果 “将要作为父节点” 的序号大于等于 “将要作为子节点”的序号
// 并且 “将要作为父节点” 的左子节点是空的
if (childNo <= parentNo && parent.left == null) {
parent.left = child;
return true;
// 如果 “将要作为父节点” 的序号小于于 “将要作为子节点”的序号
// 并且 “将要作为父节点” 的右子节点是空的
} else if (childNo > parentNo && parent.right == null) {
parent.right = child;
return true;
}
boolean result = false;
if (parent.left != null) {
// 递归调用 combinationBinaryTree 方法,有可能要将child挂载在parent的左子节点
//如果已经挂载成功,就不必在遍历 右子节点了,也就是不去执行注释1的代码了
result = combinationBinaryTree(parent.left, child);
if (result) {
return true;
}
}
//1、
if (parent.right != null) {
// 递归调用 combinationBinaryTree 方法,有可能要将child挂载在parent的右子节点
result = combinationBinaryTree(parent.right, child);
}
return result;
}
/**
* 非根节点
* @param node 二叉树中的当前节点
* @param no 要删除的节点的序号
* @return 返回 true 表示删除成功
*/
public boolean deleteNode(MyTwoQueryTree node, int no) {
// 如果删除的是当前节点的左子节点(非叶子节点来的),当前节点的左子节点又有左右子节点
if (node.left != null && node.left.data == no
&& node.left.left != null
&& node.left.right != null) {
MyTwoQueryTree parent = node.left.right;
MyTwoQueryTree child = node.left.left;
node.left = parent;//重置当前节点的左子节点
combinationBinaryTree(parent, child);
return true;
// 如果删除的是当前节点的左子节点(非叶子节点来的),当前节点的左子节点只有左子节点
} else if (node.left != null && node.left.data == no
&& node.left.left != null
&& node.left.right == null) {
MyTwoQueryTree child = node.left.left;
node.left = null;
combinationBinaryTree(node, child);
return true;
// 如果删除的是当前节点的左子节点(非叶子节点来的),当前节点的左子节点只有右子节点
} else if (node.left != null && node.left.data == no
&& node.left.left == null
&& node.left.right != null) {
MyTwoQueryTree child = node.left.right;
node.left = null;//重置当前节点的左子节点
combinationBinaryTree(node, child);
return true;
// 如果删除的是当前节点的右子节点(非叶子节点来的),当前节点的右子节点又有左右子节点
} else if (node.right != null && node.right.data == no
&& node.right.left != null
&& node.right.right != null) {
MyTwoQueryTree parent = node.right.right;
MyTwoQueryTree child = node.right.left;
node.right = parent;//重置当前节点的右子节点
combinationBinaryTree(parent, child);
return true;
// 如果删除的是当前节点的右子节点(非叶子节点来的),当前节点的右子节点只有左子节点
} else if (node.right != null && node.right.data == no
&& node.right.left != null
&& node.right.right == null) {
MyTwoQueryTree child = node.right.left;
node.right = null;//重置当前节点的右子节点
combinationBinaryTree(node, child);
return true;
// 如果删除的是当前节点的右子节点(非叶子节点来的),当前节点的右子节点只有右子节点
} else if (node.right != null && node.right.data == no
&& node.right.left == null
&& node.right.right != null) {
MyTwoQueryTree right = node.right.right;
node.right = right;
return true;
// 删除的是当前节点的左子节点(叶子节点来的)
} else if (node.left != null && node.left.data == no) {
node.left = null;
return true;
// 删除的是当前节点的右子节点(叶子节点来的)
} else if (node.right != null && node.right.data == no) {
node.right =null;
return true;
}
boolean deleteResult = false;
//向左子节点递归
if (node.left != null) {
deleteResult = deleteNode(node.left, no);
if (deleteResult) {
return true;
}
}
//向右子节点递归
if (node.right != null) {
deleteResult = deleteNode(node.right, no);
}
return deleteResult;
}
public static void main(String[] args) {
MyTwoQueryTree myTwoQueryTree = new MyTwoQueryTree(10);
myTwoQueryTree.insert(myTwoQueryTree,5);
myTwoQueryTree.insert(myTwoQueryTree,11);
myTwoQueryTree.query(myTwoQueryTree,12);
myTwoQueryTree.deleteNode(myTwoQueryTree,11);
myTwoQueryTree.query(myTwoQueryTree,11);
}
}