二叉搜索树的实现(包含插入、查找、遍历、删除等)【Java版】

package com.BinarySearchTree;
import java.util.LinkedList;
/**
*实现二分搜索树
*O(logn)
*适用于查找表(字典)

//定义树的结点
    private class Node {
        private Key  key; //键,相当于字典中的单词
        private Value  value;//值,与键对应,相当于字典中单词的含义
        private Node left; //左孩子结点
        private Node right; //右孩子结点
//结点的构造函数
        public Node(Key key,Value value) {
            this.key=key;
            this.value=value;
            this.left=null;
            this.right=null;
        }
}

//树的根节点
private Node root;
//树中结点的个数
private int count;
//树中结点的总数
public int size() {
        return count;
    }
    public boolean isEmpty() {
        return count==0;
    }

**

1.向二叉搜索树中插入新的节点,

//递归实现,也可以用非递归来实现
    public void insert(Key key,Value value) {
        root=insert(root,key, value);
    }
    //重写,向以node为根节点的二叉搜索树中插入新节点<key,value>,
    //返回插入新节点后二叉搜索树的根
    private Node insert(Node node,Key key,Value value) {
        //处理递归到底的情况
        if(node==null) {
            count++;
            return new Node(key, value);
        }
        //不支持重复元素,如果有重复,就更新
        if(key==node.key) {
            node.value=value;
        }else if(node.key.compareTo(key)<0) {
            node.right=insert(node.right, key, value);
        }else {
            node.left=insert(node.left, key, value);
        }
        return node;
    }

2.在二叉搜索树中看是否包含键值为key的元素

public boolean contain(Key key) {
        //递归实现,查找以root为根节点的树中是否包含key
        return contain(root,key);
    }
    private boolean contain(Node node, Key key) {
        //处理递归到底的情况
        if(node==null)
            return false;
        if(key==node.key)
            return true;
        else if (node.key.compareTo(key)>0) {
            return contain(node.left,key);
        }else {
            return contain(node.right, key);
        }
    }

3.在二叉搜索树中查找节点[找出key所对应的value]

public Value search(Key key) {
        return search(root,key);
    }
    //在以node为根的二叉搜索树中查找key所对应的value
    private Value search(Node node,Key key) {
        if(node==null)
            return null;

        if(key==node.key)
            return node.value;
        else if(node.key.compareTo(key)>0)
            return search(node.left,key);
        else {
            return search(node.right, key);
        }
    }

4.对二叉搜索树进行前序遍历【深度优先遍历】

public void preOrder() {
        preOrder(root);
    }
    //对以node为根的二叉搜索树进行前序遍历
    private void preOrder(Node node) {
        if(node!=null) {
            System.out.print(node.key+" ");
            preOrder(node.left);
            preOrder(node.right);
        }
    }

5.对二叉搜索树进行中序遍历【深度优先遍历】

public void inOrder() {
            inOrder(root);
        }
        //对以node为根的二叉搜索树进行中序遍历
        **//中序遍历即完成从小到大排序**
        private void inOrder(Node node) {
            if(node!=null) {
                inOrder(node.left);
                System.out.print(node.key+" ");
                inOrder(node.right);
            }
        }

6.对二叉搜索树进行后序遍历【深度优先遍历】

public void postOrder() {
            postOrder(root);
            }
    //对以node为根的二叉搜索树进行后序遍历
    **//后序遍历可以释放二叉搜索树的空间**
        private void postOrder(Node node) {
           if(node!=null) {
              postOrder(node.left);
              postOrder(node.right);
              System.out.print(node.key+" ");
            }
        }

7.对二叉搜索树进行层序遍历【广度优先遍历】

 public void levelOrder() {
            levelOrder(root);
        }
        //对以node为根的二叉搜索树进行层序遍历
        public void levelOrder(Node node) {
            LinkedList<Node> queue=new LinkedList<>();
            queue.add(node);
            while(!queue.isEmpty()) {
                Node node2=queue.poll();
                System.out.print(node2.key);
                if(node2.left != null)
                    queue.add(node2.left);
                if(node2.right!=null)
                    queue.add(node2.right);
            }
        }

8.寻找二叉搜索树的最小节点

 public Node minNum() {
          return minNum(root);
    }
       //寻找以node为根的二叉搜索树的最小节点
    private Node minNum(Node node) {
        if(node.left==null)
            return node;
        return minNum(node.left);
    }

9.寻找二叉搜索树的最大值key

public Key maxNum() {
        return maxNum(root);
    }
    //寻找以node为根的二叉搜索树的最大值
    private Key maxNum(Node node) {
        while(node.right!=null)
            node=node.right;
        return node.key;
    }

10.删除二叉搜索树的最小值结点【要考虑最左子树还有右子树的情况】

public void removeMin() {
        if(root!=null)
           root=removeMin(root);
    }
    //删除以node为根的二叉搜索树的最小值,返回删除后新树的根结点【递归】
    private Node removeMin(Node node) {
        if(node.left==null) {
            //包含了右子树为空的情况
            count--;//节点数要减一
            return node.right;
        }
        node.left=removeMin(node.left);
        return node;
    }

11.删除二叉搜索树的最大值结点【要考虑最右子树还有左子树的情况】

    public void removeMax() {
            if(root!=null)
               root=removeMax(root);
        }
        //删除以node为根的二叉搜索树的最大值,返回新树的根结点
        private Node removeMax(Node node) {
            if(node.right==null) {
                count--;
                return node.left;
            }
            node.right=removeMax(node.right);
            return node;
        }

12.删除二叉搜索树中任意一个节点key

public void deleteNum(Key key) {
                root=deleteNum(root,key);
        }
        //删除以node为根的二叉搜索树中,键值为key的节点
        //返回删除后新二叉树的根
        private Node deleteNum(Node node, Key key) {
            //处理递归到底,未找到情况
            if(node==null)
               return null;
            //在左子树中找到并删除
            if(node.key.compareTo(key)>0) {
                node.left=deleteNum(node.left,key);
            }
            //在右子树中找到并删除
            else if(node.key.compareTo(key)<0) {
                node.right=deleteNum(node.right, key);
            }else {
                //若左子树为空或者左右子树均为空
                if(node.left==null) {
                    count--;
                    return node.right;
                }
                //若右子树为空
                if(node.right==null) {
                    count--;
                    return node.left;
                }
                //若node的左右子树均不为空
                //先找到右子树的最小值来作为要删除节点的后继
                Node s1=minNum(node.right);
                //新建一个节点,用来替换,以防和后面removeMin冲突
                Node s=new Node(s1.key, s1.value);
                count++;
                //s的右子树是将s本身删除后的右子树
                s.right=removeMin(node.right);
                s.left=node.left;
                count--;
                return s;
            }
            return node;
        }

测试

 public static void main(String args[]) {
    //不能用基本类型,HashMap对象的key、value值均可为null。
       BinarySearchTree<Integer,String> bTree =new BinarySearchTree<>(); 
    //插入数据      
       bTree.insert(7,"A");
       bTree.insert(3, "C");
       bTree.insert(4,"E");
       bTree.insert(11,"r");
       bTree.insert(23, "t");
       bTree.insert(41,"e");
    //包含和查找
       System.out.println(bTree.contain(44));
       System.out.println(bTree.search(11));
    //深度优先遍历
       bTree.preOrder();
       bTree.inOrder();
       bTree.postOrder();
     //广度优先遍历【层序遍历】
       bTree.levelOrder();
     //寻找最小值和最大值
       System.out.println(bTree.minNum().key);
       System.out.println(bTree.maxNum());
     //删除最大值
       bTree.removeMax();
       System.out.println(bTree.maxNum());
       System.out.println(bTree.size());
     //删除任意一个节点
       bTree.deleteNum(11);
       bTree.inOrder();
   }

}

猜你喜欢

转载自blog.csdn.net/yulutian/article/details/79491008