携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第17天,点击查看活动详情
二叉排序树是什么
二叉排序树又称二叉查找树(Binary Search Tree),亦称二叉搜索树。
二叉排序树或者是一棵空树,或者是具有下列特点的二叉树
- 若左子树不空,则左子树上所有结点的值均小于或等于它的根结点的值;
- 若右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值;
- 左、右子树也分别为二叉排序树;
二叉搜索树的特征
1.中序遍历的序列是递增的序列
public LinkedList inorder(TreeNode root, LinkedList arr) {
if (root == null) return arr;
inorder(root.left, arr);
arr.add(root.val);
inorder(root.right, arr);
return arr;
}
2.中序遍历的下一个节点,称后继节点,即比当前节点大的最小节点
public int successor(TreeNode root) {
root = root.right;
while (root.left != null) root = root.left;
return root;
}
3.中序遍历的前一个节点,称前驱节点,即比当前节点小的最大节点
public int predecessor(TreeNode root) {
root = root.left;
while (root.right != null) root = root.right;
return root;
}
二叉树的操作
1.添加节点
思路:
- 检查该二差排序树是否为空,如果为空,则将新节点指定为根节点,否则将新节点与根节点进行比较;
- 根据比较结果,确定新节点应该插入根节点的左子树还是右子树,之后我们将应该被插入的左右子树作为新的研究对象,重复1过程
代码实现:
public Node add(Node root, int value) {
if(root == null){
//走到叶子节点添加
root = new Node(value);
size++;
return root;
}
//比较value和根节点的大小
if(value < root.val){
root.left = add(root.left,value);
}else{
root.right = add(root.right,value);
}
return root;
}
2.查询节点 思路:
二叉排序树中进行指定值的节点查找非常简便,这个查找过程实际上就是一个二分搜索的过程,我们首先创建一个遍历指针,让这个指针指向排序树的根节点,如果根节点值等于我们想要查找的值,那么我们就直接进行返回操作即可,如果不等于,那么根节点必定大于或者小于我们要查找的值,此时我们根据具体情况在根节点的左子树或者右子树中继续查询,这里是一个递归过程.
代码实现:
public TreeNode search(TreeNode node, int value){
if(node == null){
return null;
}
if(node.getValue()>value){
if(node.getLeftTreeNode() == null)
return null;
return search(node.getLeftTreeNode(),value);
}else if(node.getValue()<value){
if(node.getRightTreeNode() == null)
return null;
return search(node.getRightTreeNode(),value);
}else{
return node;
}
}
3.删除节点
分几种情况:
- 删除叶子节点
基本思路:
1. 找到要删除的节点targeNode
2. 找到删除节点的父节点parent节点
3. 判断targeNode节点是parent节点的左子树还是右子树
4. 根据上述情况进行删除
左子节点:parent.left = null;
右子节点:parent.right = null;
2. 删除只有一个子树的结点(左子树,右子树)
1.找到要删除的节点targeNode
2.找到删除节点的父节点parent节点
3.确定要删除的节点的子节点是左子节点还是右子节点
4.判断targeNode节点是parent节点的左子树还是右子树
5.如果target有左子节点
target是parent的左子节点 parent.left = target.left
target是parent的右子节点 parent.right = target.right
6.如果target有右子节点
target是parent的左子节点 parent.left = target.right
target是parent的右子节点 parent.right = target.left
3. 删除有两个子树的结点
1.找到要删除的节点targeNode
2.找到删除节点的父节点parent节点(考虑是否有父节点)
3.从targetNode的右子树去找最小值(或左子树的最大值)
4.右子树去找最小值(或左子树的最大值)和要删除的节点 target值进行替换
5.删除.右子树去找最小值(或左子树的最大值)
代码实现:
/**
*
* @param value 希望删除啊的节点值
* @return 如果找到返回该节点值,找不到返回null
*/
public TreeNode search(TreeNode node,int value){
if(root == null){
return null;
}
// 找到的就是这个节点
if(value == node.getValue()){
return node;
}else if(value < node.getValue()){ //如果查找的值小于当前节点向左子树递归查找
// 判断左子树是否为空
if(node.getLeftTreeNode() == null){
return null;
}
return search(node.getLeftTreeNode(),value);
}else {
if(node.getRightTreeNode() == null){
return null;
}
return search(node.getRightTreeNode(),value);
}
}
4.遍历节点 采用二叉树的中序遍历