Java--数据结构之BST二叉搜索树

一、二叉搜索树Binary Search Tree
1、若左子树不为空,则左子树上所有节点的值均小于或等于它的根节点的值。
2、若右子树不为空,则右子树上所有节点的值均大于或等于它的根节点的值。
3、左、右子树也分别为二叉搜索树。
二、节点域设置

    //根节点
    private Entry<T> root;

    //初始化
    public BSTDemo(){
        this.root=null;
    }

    //节点域
    public class Entry<T extends Comparable<T>> {
        private T data;//数据域
        private Entry<T> left;//左孩子域
        private Entry<T> right;//右孩子域

        public Entry() {
            this(null, null, null);
        }
        public Entry(T data,Entry<T> left,Entry<T> right){
            this.data=data;
            this.left=left;
            this.right=right;
        }
    }

三、递归和非递归操作BST
1、插入
(1)递归插入

   //插入
    public void insert(T val){
        this.root = insert(this.root, val);
    }
    private Entry<T> insert(Entry<T> root, T val) {
        if(root == null){
            return new Entry<T>(val, null, null);
        }
        if(root.data.compareTo(val) > 0){
            root.left=insert(root.left, val);
        } else if(root.data.compareTo(val) < 0){
            root.right=insert(root.right, val);
        }
        return root;
    }

(2)非递归插入

//插入
public void non_insert(T val){
        if(this.root == null){
            //直接生成根节点
            this.root = new Entry<T>(val, null, null);
            return;
        }
        Entry<T> parent = null;
        Entry<T>  cur = this.root;
        while(cur != null){
            parent = cur;
            if(cur.data.compareTo(val) < 0){
                cur = cur.right;
            } else if(cur.data.compareTo(val) > 0){
                cur = cur.left;
            } else {
                return;
            }
        }
        if(parent.data.compareTo(val)  < 0){
            parent.right=new Entry<T>(val, null, null);
        } else {
            parent.left=new  Entry<T>(val, null, null);
        }
    }

2、删除
(1)递归删除

public void delete(T data){
        this.root = delete(this.root, data);
    }

    private Entry<T> delete(Entry<T> root, T val) {
        if(root == null){
            return null;
        }

        if(root.data.compareTo(val) > 0){
            root.left=delete(root.left, val);
        } else if(root.data.compareTo(val) < 0){
            root.right=delete(root.right, val);
        } else {
            if(root.left!= null && root.right != null){
                Entry<T> pre = root.left;
                while(pre.right != null){
                    pre = pre.right;
                }
                root.data=pre.data;
                // 递归继续删除前驱节点
                root.left=delete(root.left, pre.data);
            } else {
                if(root.left != null){
                    return root.left;
                } else if(root.right != null){
                    return root.right;
                } else {
                    return null;
                }
            }
        }
        return root;
    }

(2)非递归删除

//删除
    public void non_delete(T val){
        if(this.root==null){
            System.out.println("该树不存在,无法进行删除。");
            return;
        }

        Entry<T> parent = null; //记录根和跟的父节点
        Entry<T> cur = this.root;

        while(cur != null){
            if(cur.data.compareTo(val) > 0){
                parent = cur;
                cur = cur.left;
            } else if(cur.data.compareTo(val) < 0){
                parent = cur;
                cur = cur.right;
            } else {
                break;
            }
        }
        if(cur == null){//没找到
            System.out.println("树中不存在"+val+",删除失败。");
            return;
        }
        //待删除节点有两个孩子
        if(cur.left!= null && cur.right != null){
            Entry<T> old = cur;//记录当前cur的位置
            parent = cur;
            cur = cur.left;//找前驱

            while(cur.right != null){//找左子树中最大的,往右走
                parent = cur;
                cur = cur.right;
            }
            old.data=cur.data;
        }

        //待删节点有一个孩子或者没有孩子
        Entry<T> child = cur.left;
        if(child == null){
            child = cur.right;//记录孩子位置,非左即右
        }

        if(parent == null){ //删除的是根节点
            this.root = child;
        } else {
            if(cur == parent.left){ //把cur的child写入父节点的左孩子域
                parent.left=child;
            } else {
                parent.right=child;
            }
        }

    }

3、查询
(1)递归查询

//查询
    public void search(T val){
       search(this.root, val);
    }
    private Entry<T> search(Entry<T> root,T val) {
        if (this.root == null) {
            return null;
        }
        while (root != null) {
            if (root.data.compareTo(val) < 0) {
                return search(root.right, val);
            } else if (root.data.compareTo(val) > 0) {
                return search(root.left, val);
            } else{
                System.out.println("树中存在"+val+",查询成功。");
                return root;
            }
        }
        //没找到
        System.out.println("树中不存在"+val+",查询失败。");
        return null;
    }

(2)非递归查询

//查询
    public boolean non_search(T val){
        if(this.root==null){
            System.out.println("该树不存在,无法进行查询。");
            return false;
        }
        Entry<T> cur=this.root;
        while(cur!=null){
            if(cur.data.compareTo(val)>0){
                //插入元素比当前节点小,往左
                cur=cur.left;
            }else if(cur.data.compareTo(val)<0){
                cur=cur.right;
            }else {
                System.out.println("树中存在"+ val +",查询成功。");
                return true;
            }
        }
        System.out.println("树中不存在"+ val +",查询失败。");
        return false;
    }

4、遍历
(1)递归遍历
①前序遍历

//前序遍历:中 左 右
    public void prePrint() {
        System.out.println("前序遍历:");
        preOrder(this.root);
        System.out.println();
    }
    private void preOrder(Entry<T> root) {
        if (root == null) {
            return;
        }
        System.out.print(root.data + " ");
        preOrder(root.left);
        preOrder(root.right);
    }

②中序遍历

    //中序遍历:左 中 右
    public void inOrder() {
        System.out.println("中序遍历:");
        inOrder(this.root);
        System.out.println();
    }
    private void inOrder(Entry<T> root) {
        if (root == null) {
            return;
        }
        inOrder(root.left);
        System.out.print(root.data + " ");
        inOrder(root.right);
    }

③后序遍历

    //后序遍历:左 右 中
    public void postOrder(){
        System.out.println("后序遍历:");
        postOrder(this.root);
        System.out.println();
    }
    private void postOrder(Entry<T> root) {
        if (root == null) {
            return;
        }
        postOrder(root.left);
        postOrder(root.right);
        System.out.print(root.data + " ");

    }

④层序遍历

    //层序遍历
    //统计层数
    public int level(){
        return level(this.root);
    }
    private int level(Entry<T> root){
        if(root==null){
            return 0;
        }else{
            int left=level(root.left);
            int right=level(root.right);
            return right>left?(right+1):(left+1);
        }
    }
    //开始遍历
    public void levelOrder(){
        System.out.println("层序遍历");
        int level=level();
        for(int i=0;i<level;i++){
            levelOrder(this.root,i);
        }
    }
    private void levelOrder(Entry<T> root,int i){
        if(root==null){
            return;
        }
        if(i==0){
            System.out.print(root.data+" ");
            return;
        }
        levelOrder(root.left,i-1);
        levelOrder(root.right,i-1);
    }

(2)非递归遍历
①前序遍历

 //前序遍历:中 左 右
    public void non_preOrder() {
        System.out.println();
        System.out.println("前序遍历:");
        Stack<Entry> stack = new Stack<>();
        stack.push(root);

        while (!stack.isEmpty()) {
            Entry<T> cur = stack.pop();
            System.out.print(cur.data+" ");
            if (cur.right != null) {//后进先出,因此先放右
                stack.push(cur.right);
            }
            if (cur.left != null) {
                stack.push(cur.left);
            }
        }
    }

②中序遍历

    //中序遍历:左 中 右
    public void non_inOrder(){
        System.out.println();
        System.out.println("中序遍历:");
        Entry<T> cur=this.root;
        Stack<Entry> stack = new Stack<>();
        if (cur != null) {
            while (!stack.isEmpty()|| cur!=null) {
                if (cur != null) {
                    stack.push(cur);
                    cur = cur.left;//一直向左走,走到左边全完了然后出栈
                } else {
                    cur = stack.pop();
                    System.out.print(cur.data + " ");
                    cur = cur.right;
                }
            }
        }
    }

③后序遍历

    //后序遍历:左 右 中
    public void non_postOrder(){
        System.out.println();
        System.out.println("后序遍历:");
        Entry<T> cur=this.root;
        Stack<Entry> s1 = new Stack<>();
        Stack<Entry> s2 = new Stack<>();
        if (cur != null) {
            s1.push(cur);
            while (!s1.isEmpty()) {
                cur = s1.pop();
                s2.push(cur);
                if (cur.left != null) {
                    s1.push(cur.left);
                }
                if (cur.right != null) {
                    s1.push(cur.right);
                }
            }
            while (!s2.isEmpty()) {
                System.out.print(s2.pop().data + " ");
            }
        }
    }

④层序遍历

public void non_levelOrder(){
        System.out.println();
        System.out.println("层序遍历:");
        LinkedList<Entry> linkedList=new LinkedList<>();
        linkedList.add(this.root);
        while(!linkedList.isEmpty()){
            Entry<T> cur=linkedList.remove();
            System.out.print(cur.data+" ");
            if(cur.left!=null){
                linkedList.add(cur.left);
            }
            if(cur.right!=null){
                linkedList.add(cur.right);
            }
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值