数据结构复习--二分搜索树遍历、删除最大最小元素和、查询

二叉树

每个元素存在一个节点中 和链表 一样 动态数据结构

和链表一样 节点结构

节点定义

class Node{
    E e;
    Node left;  // 左孩子
    Node right; // 右孩子
}

二叉树具有唯一根节点。

二叉树 每个节点 最多有两个孩子

叶子节点的定义 : 这个节点没有左右孩子。

二叉树的每个节点最多有一个父亲节点

二叉树具有天然的递归结构

每个结点的左子树 是 二叉树。

每个节点的右子树也是二叉树。

注意的是:

  • 二叉树不一定是满的
  • 一个节点也可以是一个二叉树
  • Null 空也是二叉树。

二叉树–二分搜索树

性质 (定义): 二叉搜索树 每个节点的值 大于 左子树所有节点的值

小于其 右子树所有节点的值

每一个节点都要满足这样的性质

存储的元素必须要有可比较性

二分搜索树 -------添加元素

复杂递归写法

   public void add(Integer e ){
        /*
        * 如果根节点为空 加到根节点上 size ++
        * */
        if (root == null){
            root = new Node(e);
            size ++;
        }
        else
            add(root , e);
    }
/*复杂递归写法*/
    private void add(Node root, Integer e) {
        if (Objects.equals(root.e, e)) {
            return;
        }
        else if (root.e < e && root.right == null) {
            root.right = new Node(e);
            size ++;
            return;
        }
        else if (root.e > e && root.left == null){
            root.left = new Node(e);
            size ++;
            return;
        }
        if  (e < root.e) {
            add(root.left , e);
        }
        else
            add(root.right,e);
    }

递归代码结束条件太多,可以试着不做判断 左右孩子是否为空,让递归进行到底,节点为空的是后new 一个新的节点出来 与二茶树的 左节点或者右节点进行链接 简洁代码写法如下

    public void add(Integer e ){
        /*
        * 如果根节点为空 加到根节点上 size ++
        * */
      root = add (root,e);
    }
    private Node add(Node root, Integer e) {
       if (root == null){
           size ++;
           return new Node(e);
       }
        if  (e < root.e) {
            root.left = add(root.left , e); // 左子树为空的话 会以 e为值 new 一个 新的节点。
        }
        else
           root.right =   add(root.right,e); 
        return  root;
    }

在二分搜素树中搜节点

    public boolean contains(Node root, Integer e) {
            if (root == null){
                return false;
            }
        if (root.e.equals(e)) {
            return true;
        } else if (root.e.compareTo(e) < 0) {
            // 去 遍历右子树 遍历到底没找到  节点为空 返回false  左子树相同情况
           return contains(root.right, e);
        } else
           return contains(root.left, e);
    // 递归遍历完了 让然没有找到 就返回false.
    }

二分搜索树的遍历

对于上面两个操作  搜索节点 和 添加节点  我们只要顾及一个分支的递归遍历, 对于二叉树的 遍历  则要顾及两个分支的遍历。进行两次递归调用。 不加判断条件。
// 前序遍历。  访问顺序 改变一下 就是 中 后 序的遍历
   public void preOrder(Node node){
        if (node == null){
            // 递归终止条件
            return;
        }
        System.out.println(node.e);
        preOrder(node.left);
        preOrder(node.right);
    } 

**不使用递归实现二叉树的遍历怎么实现 递归是调用系统栈来实现的 栈有一个特点 是 后入先出的数据结构 以前序遍历为例: 根 左 右 **

要实现这样的遍历顺序 像访问根节点 根入就出 但是 左 和 右 子树很大的情况下 不能 直接将其 放在 栈中 因为还要遍历 他的子树

应该逆序放入 才会 按前序遍历的顺序出来 代码如下

    public void preOrder(Node node){
        Stack<Node> stack = new Stack<>();
        stack.push(node);
        while (!stack.isEmpty()){
            Node cur = stack.pop();
            System.out.println(cur.e);
            if (cur.right != null)
            stack.push(cur.right);
            if (cur.left != null)
            stack.push(cur.left);
        }
    }

二叉树的层序遍历(广度优先遍历)

按深度 一层一层 的遍历 BFS

使用队列这种数据结构实现广度优先遍历

    public void bfs(Node node){
        Queue<Node> queue = new LinkedList<>();
        queue.add(node);
        while (!queue.isEmpty()){
            // 循环不变性 队列不为空的条件下循环进行
            Node remove = queue.remove();
            System.out.println(remove.e);
            if (null != node.left)
             bfs(node.left);
            if (null != node.right)
            bfs(node.right);
        }
    }

删除节点的操作

删除最小节点
 public Node removeMinNode(Node node){
        /*递归终止 传过来的 root 肯定在系统栈顶的最顶端  直接返回node 即可*/
        //        root = node;
        if (null == node.left) {
            // 当前节点没有左子树了 就是 最小节点
            /*
             最小节点课能有右子树 拿到最小节点的右子树*/
            Node rightNode = node.right;
            node.right = null ;  // 让当前节点与树脱离关系 此时右节点 为 改树的最小值
            size --;
            return  rightNode; // 返回一层层调用的的 rightNode
        }
        // 递归一层一层 最后结束的这层 终止条件 是 已经找到最小的节点  上一层节点 为 node 栈的第二层
        node.left = removeMinNode(node.left);
        return node;
    }
删除最大节点的操作
  /* 删除最大 结点的操作*/
    public Node removeMaxNode(){
     return removeMaxNode(root);
    }
    private Node removeMaxNode(Node node){
        if (null == node.right){
            Node scncondMax = node.left;
            node.left  = null; // 让该节点脱离树
            size -- ; // 树的节点减一操作
            return scncondMax;
        }
        node.right = removeMaxNode(node.right);
        return node;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值