赞
踩
二叉搜索树,也叫二叉查找树、二叉排序树,顾名思义,这种二叉树是专门用来进行数据查找的二叉树。二叉搜索树的查找其实就是二分查找。
二叉搜索树的定义:
二叉搜索树的操作集:
既然是专门用来进行查找的二叉搜索树的操作集自然就是增删查,没有改,因为二叉搜索树中的元素都是排序好的,如果直接就地改动某个节点很可能破坏有序性,所以当发现插入的数据有误的时候先删除,再重新插入,一定要保证数据经过了插入流程,这样数据才会在对的位置,才能保证整棵的有序性。
- boolean find(Object target);
- Object findMin();
- Object findMax();
- void insert(Object data);
- void delete(Object data);
节点实体如下:
- public class Node {
- //数据域
- private int data;
- //指针域
- private Node left;
- private Node right;
-
- //遍历标志
- private boolean isOrder;
-
- {
- isOrder=false;
- }
-
- public Node(){
-
- }
-
- public Node(int data){
- this.data=data;
- }
- public int getData() {
- return data;
- }
-
- public void setData(int data) {
- this.data = data;
- }
-
- public Node getLeft() {
- return left;
- }
-
- public void setLeft(Node left) {
- this.left = left;
- }
-
- public Node getRight() {
- return right;
- }
-
- public void setRight(Node right) {
- this.right = right;
- }
-
- public boolean isOrder() {
- return isOrder;
- }
-
- public void setOrder(boolean order) {
- isOrder = order;
- }
- }
假设插入35,从根节点开始比较,
35>30,属于30的右子树,30的右孩子不为空,继续向下走,
35<41,属于41的左子树,41的左孩子不为空,继续向下走,
35>33,属于33的右子树。33的右孩子为空,35是33的右孩子。
代码示例:
- //记录根节点
- private static Node root=null;
- //用于寻路的指针
- private static Node flag=null;
- public static void insert(Node node){
- if(root==null){
- System.out.println("我插入"+node.getData()+"作为根节点");
- root=node;
- }
-
- flag=root;
-
- while (node.getData()<flag.getData()){
- if(flag.getLeft()==null) {
- System.out.println("我在"+flag.getData()+"右边插入一个"+node.getData());
- flag.setLeft(node);
- }
- flag = flag.getLeft();
- }
-
- while(node.getData()>flag.getData()){
- if(flag.getRight()==null) {
- System.out.println("我在"+flag.getData()+"右边插入一个"+node.getData());
- flag.setRight(node);
- }
- flag = flag.getRight();
- }
- }
二叉搜索树的查找其实就是借助数据结构实现了二分查找,如果当前节点的值大于要查找的值,说明要查找的值只可能存在于当前节点的右子树,如果当前节点的值小于要查找的值,说明要查找的值只可能存在于当前节点的左子树。不断重复以上过程,遇见两种情况终止:
代码示例:
- public static boolean find(int target){
- //从根节点开始
- flag=root;
- while(true){
- //当前节点值为查找值
- if(flag.getData()==target){
- return true;
- }
- //向右子树查找
- if(target>flag.getData()){
- flag=flag.getRight();
- }
- //向左子树查找
- if(target<flag.getData()){
- flag=flag.getLeft();
- }
- //当前节点是叶节点
- if(flag==null){
- return false;
- }
- }
- }
从根节点开始一直沿着右子树的右孩子进行查找,右子树的最后一个右孩子一定是最大值。
- public static int findMax(){
- flag=root;
- while(flag.getRight()!=null){
- flag=flag.getRight();
- }
- return flag.getData();
- }
从根节点开始一直沿着左子树的左孩子进行查找,左子树的最后一个左孩子一定是最小值。
- public static int findMin() {
- flag = root;
- while (flag.getLeft() != null) {
- flag = flag.getLeft();
- }
- return flag.getData();
- }
被删除的节点有三种情况:
代码示例:
二叉搜索树由于是整体有序的,每个元素的变动都会造成一定范围内需要进行整体的重新排序,且排序过程是重复的,因此这个过程用递归实现更加简洁,用循环会很冗长,此处选用递归实现。
- public static void delete(int target){
- flag=root;
- //由于删除节点会引起树的调整,为了以防万一根节点需要重新指向一下
- root=doDelete(flag,target);
- }
-
- private static Node doDelete(Node node,int target){
- //空树直接返回,或者是递归出口1:已经遍历完整棵树
- if(node == null) {
- return null;
- }
- //递归左子树
- if(target < node.getData()) {
- node.setLeft(doDelete(node.getLeft(), target));
- }
- //递归右子树
- if(target > node.getData()) {
- node.setRight(doDelete(node.getRight(), target));
- }
- //执行到此步,说明已经出递归,并且没有走递归出口1返回,说明找到了目标
- //情况1:被删除节点只有一个孩子节点
- //情况2:被删除节点为叶子节点
- //以上两种情况可以合并成一个逻辑处理,即指向自己的孩子节点即可
- if(node.getLeft() == null) {
- return node.getRight();
- }
- if(node.getRight() == null) {
- return node.getLeft();
- }
- //情况3:被删除节点左右孩子双全,找右子树中最小值接替被删除节点,右子树需递归此过程整体做调整
- Node minNode = findMinNode(node.getRight());
- node.setData(minNode.getData());
- node.setRight(doDelete(node.getRight(),minNode.getData()));
- return node;
- }
-
- private static Node findMinNode(Node node){
- while(node.getLeft() != null)
- node = node.getLeft();
- return node;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。