数据结构与算法(java版)第一季 - 08 二叉搜索树(未完待续)

本篇笔记还没写完,不想写了,后面再写

目录

01 需求分析

02 接口设计

03 根节点

04 add思路

05 add实现

06 comparable

07 comparator

08 完美结合

09 匿名类

10 打印器使用

11 打印器Person

12 打印器更多用法

13 打印器文件建议

14 网站推荐

15 值相等处理

16 前序遍历

17 中序遍历

18 后序遍历

19 层序遍历

20 设计遍历接口

21 增强型遍历接口01

22 增强型遍历接口02

23 树状打印二叉树

24 计算二叉树的高度

25 完全二叉树的判断01

26 完全二叉树的判断02

27 翻转二叉树

28 重构二叉树

29 前驱节点

30 后继节点

31 remove01

32 remove02

33 remove03实现

34 


01 需求分析

  • 在n个动态的整数中搜索某个整数(查看其是否存在),如果要是使用动态数组存放元素,从第0个位置开始遍历搜索,平均时间复杂度:O(n);
  • 在一个有序的动态数组,使用二分搜索,最坏的时间复杂度是:O(logn),但是添加、删除的平均时间复杂度是O(n).针对上述的这个需求,更好的设计方案是使用相应的二叉搜索树,添加 删除 搜索的最坏时间复杂度可优化到:O(logn).

02 接口设计

  • 二叉搜索树是二叉树的一种,是一种应用非常广泛的二叉树,英文简称是BST.(别称是二叉查找树 二叉排序树)
  • 特点:(1)任意一个节点的值都大于左子树所有节点的值;  (2)任意一个节点的值都大于右子树所有节点的值; (3)左右子树也是二叉搜索树; (4)可以大大提高搜索效率.

  • 接口如下所示:对比于动态数组的元素是没有索引的概念.

03 add-根节点

  • 代码段如下所示:
    import java.util.Comparator;
    
    public class BinarySearchTree<E> {
        private int size;
        private Node<E> root;
        
        public int size() {
            return size;
        }
    
        public boolean isEmpty() {
            return size == 0;
        }
    
        public void clear() {
          
        }
    
        public void add(E element) {
            elementNOtNullCheck(element);
            
            //添加第一个节点
            if(root == null)
            {
                root = new Node<E>(element,null);
                size++;
                return ;
            }
            
            //添加的不是第一个节点
            
        }
    
        public void remove(E element) {
            
        }
    
        public boolean contains(E element) {
            return true;
        }
        
        //检查节点是否为空
        private void elementNOtNullCheck(E element)
        {
         if(element == null)
         {
         throw new IllegalArgumentException("element must not be null");
        }
         
         
        }
    
        private static class Node<E>
        {
            E element;
            Node<E> left;
            Node<E> right;
            Node<E> parent;
            public Node(E element,Node<E> parent)
            {
                this.element = element;
                this.parent = parent;
            }
        }
    }
    

04 add-思路

  • 比如说我们添加1和12,如下图所示:
  • 添加的步骤是如下所示:(1)找到父节点 parent(2)创建新节点 node; (3)parent.left = node 或者 parent.right = node
  • 如果要是遇到相同的节点,建议进行相应的一个覆盖节点的使用过程.

05 add实现

  • 完善了compare函数和add()函数,完整的代码如下所示:
    import java.util.Comparator;
    
    public class BinarySearchTree<E> {
        private int size;
        private Node<E> root;
    
        public int size() {
            return size;
        }
    
        public boolean isEmpty() {
            return size == 0;
        }
    
        public void clear() {
    
        }
    
        public void add(E element) {
            elementNOtNullCheck(element);
    
            //添加第一个节点
            if(root == null)
            {
                root = new Node<E>(element,null);
                size++;
                return ;
            }
    
            //添加的不是第一个节点
            //找到父节点
            Node<E> parent = null;//看下面的一句代码
            Node<E> node = root;
            int cmp = 0;
            while(node != null)
            {
                int cmp = compare(element, node.element);
                parent = node;//这句话的含义是在进行比较之前进行一个节点的赋值,因为要是跳出循环之后,node=null,需要进行一个提前保存的过程.
                if (cmp > 0) {
                    node = node.right;
                } else if (cmp < 0) {
                    node = node.left;
                } else {
                    return;//什么也不干
                }
            }
    
            //插入到父节点的位置
            Node<E> newNode = new Node<E>(element,parent);
            if(cmp > 0)
            {
                parent.right = newNode;
            }
            else {
                parent.left = newNode;
            }
    
        }
    
        public void remove(E element) {
    
        }
    
        public boolean contains(E element) {
            return true;
        }
    
        //检查节点是否为空
        private void elementNOtNullCheck(E element)
        {
         if(element == null)
         {
         throw new IllegalArgumentException("element must not be null");
        }
        }
    
        /**
         * @return 返回值=0,e1=e2;返回值=1,e1>e2;返回值<0,e1<e2;
         * @param
         */
        private int compare(E e1,E e2)
        {
            return 0;
        }
    
        private static class Node<E>
        {
            E element;
            Node<E> left;
            Node<E> right;
            Node<E> parent;
            public Node(E element,Node<E> parent)
            {
                this.element = element;
                this.parent = parent;
            }
        }
    }
    

06 comparable

  • 第一种设计方式是通过相应的comparable的方式实现的.
  • 设定一个相应的comparable的接口,接口的代码是如下所示:
public interface Comparable<E> {
    int compareTo(E e);
}
  • 声明一个Person类去继承相应的Comparable接口,代码是如下所示:
public class Person implements Comparable<Person>{//这里是需要进行继承一个官方的Comparable的
    private int age;

    public Person(int age)
    {
        this.age = age;
    }

    public int compareTo(Person e) {//对比年龄的大小
        return (this.age - e.age);
    }

}
  • 二叉树之中的代码是如下所示:
import java.util.Comparator;

public class BinarySearchTree<E extends Comparable> {
    private int size;
    private Node<E> root;

    public int size() {
        return size;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    public void clear() {

    }

    public void add(E element) {
        elementNOtNullCheck(element);

        //添加第一个节点
        if(root == null)
        {
            root = new Node<E>(element,null);
            size++;
            return ;
        }

        //添加的不是第一个节点
        //找到父节点
        Node<E> parent = null;//看下面的一句代码
        Node<E> node = root;
        int cmp = 0;
        while(node != null)
        {
            cmp = compare(element, node.element);
            parent = node;//这句话的含义是在进行比较之前进行一个节点的赋值,因为要是跳出循环之后,node=null,需要进行一个提前保存的过程.
            if (cmp > 0) {
                node = node.right;
            } else if (cmp < 0) {
                node = node.left;
            } else {
                return;//什么也不干
            }
        }

        //插入到父节点的位置
        Node<E> newNode = new Node<E>(element,parent);
        if(cmp > 0)
        {
            parent.right = newNode;
        }
        else {
            parent.left = newNode;
        }

    }

    public void remove(E element) {

    }

    public boolean contains(E element) {
        return true;
    }

    //检查节点是否为空
    private void elementNOtNullCheck(E element)
    {
     if(element == null)
     {
     throw new IllegalArgumentException("element must not be null");
    }
    }

    /**
     * @return 返回值=0,e1=e2;返回值=1,e1>e2;返回值<0,e1<e2;
     * @param
     */
    private int compare(E e1,E e2)
    {
        return e1.compareTo(e2);
    }

    private static class Node<E>
    {
        E element;
        Node<E> left;
        Node<E> right;
        Node<E> parent;
        public Node(E element,Node<E> parent)
        {
            this.element = element;
            this.parent = parent;
        }
    }
}
  • 我们的主函数是这样进行编写测试.(应当注意函数之中对于Comparable接口的继承)

import java.util.Comparator;

public class BinarySearchTree<E extends Comparable> {
    private int size;
    private Node<E> root;

    public int size() {
        return size;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    public void clear() {

    }

    public void add(E element) {
        elementNOtNullCheck(element);

        //添加第一个节点
        if(root == null)
        {
            root = new Node<E>(element,null);
            size++;
            return ;
        }

        //添加的不是第一个节点
        //找到父节点
        Node<E> parent = null;//看下面的一句代码
        Node<E> node = root;
        int cmp = 0;
        while(node != null)
        {
            cmp = compare(element, node.element);
            parent = node;//这句话的含义是在进行比较之前进行一个节点的赋值,因为要是跳出循环之后,node=null,需要进行一个提前保存的过程.
            if (cmp > 0) {
                node = node.right;
            } else if (cmp < 0) {
                node = node.left;
            } else {
                return;//什么也不干
            }
        }

        //插入到父节点的位置
        Node<E> newNode = new Node<E>(element,parent);
        if(cmp > 0)
        {
            parent.right = newNode;
        }
        else {
            parent.left = newNode;
        }

    }

    public void remove(E element) {

    }

    public boolean contains(E element) {
        return true;
    }

    //检查节点是否为空
    private void elementNOtNullCheck(E element)
    {
     if(element == null)
     {
     throw new IllegalArgumentException("element must not be null");
    }
    }

    /**
     * @return 返回值=0,e1=e2;返回值=1,e1>e2;返回值<0,e1<e2;
     * @param
     */
    private int compare(E e1,E e2)
    {
        return e1.compareTo(e2);
    }

    private static class Node<E>
    {
        E element;
        Node<E> left;
        Node<E> right;
        Node<E> parent;
        public Node(E element,Node<E> parent)
        {
            this.element = element;
            this.parent = parent;
        }
    }
}

07 comparator

  • 上面的设计模式并不是很好的,为什么呢?因为如果要是使用两个相应的二叉搜索树,二叉搜索树的分配方式都是一样的,也就是所谓的比较规则是一样的,不可以进行改变,为了解决这个问题,我们采用一个新的接口comparator.
  • 创建一个新的比较器接口,代码是如下所示:
    public interface Comparator<E> {
        int compare(E e1,E e2);
    }
    

    在二叉搜索树之中进行相应的一个构造函数的引用,并且不再继承原来的接口.

    
    public class BinarySearchTree<E>{
        private int size;
        private Node<E> root;
        private Comparator<E> comparator;
    
        public BinarySearchTree(Comparator<E> comparator)
        {
            this.comparator = comparator;
        }
    
        public int size() {
            return size;
        }
    
        public boolean isEmpty() {
            return size == 0;
        }
    
        public void clear() {
    
        }
    
        public void add(E element) {
            elementNOtNullCheck(element);
    
            //添加第一个节点
            if(root == null)
            {
                root = new Node<E>(element,null);
                size++;
                return ;
            }
    
            //添加的不是第一个节点
            //找到父节点
            Node<E> parent = null;//看下面的一句代码
            Node<E> node = root;
            int cmp = 0;
            while(node != null)
            {
                cmp = compare(element, node.element);
                parent = node;//这句话的含义是在进行比较之前进行一个节点的赋值,因为要是跳出循环之后,node=null,需要进行一个提前保存的过程.
                if (cmp > 0) {
                    node = node.right;
                } else if (cmp < 0) {
                    node = node.left;
                } else {
                    return;//什么也不干
                }
            }
    
            //插入到父节点的位置
            Node<E> newNode = new Node<E>(element,parent);
            if(cmp > 0)
            {
                parent.right = newNode;
            }
            else {
                parent.left = newNode;
            }
    
        }
    
        public void remove(E element) {
    
        }
    
        public boolean contains(E element) {
            return true;
        }
    
        //检查节点是否为空
        private void elementNOtNullCheck(E element)
        {
         if(element == null)
         {
         throw new IllegalArgumentException("element must not be null");
        }
        }
    
        /**
         * @return 返回值=0,e1=e2;返回值=1,e1>e2;返回值<0,e1<e2;
         * @param
         */
        private int compare(E e1,E e2)
        {
            return comparator.compare(e1,e2);
        }
    
        private static class Node<E>
        {
            E element;
            Node<E> left;
            Node<E> right;
            Node<E> parent;
            public Node(E element,Node<E> parent)
            {
                this.element = element;
                this.parent = parent;
            }
        }
    }
    

    Person类直接调用相应的构造器,为主函数测试使用做准备.

    public class Person implements Comparable<Person>{//这里是需要进行继承一个官方的Comparable的
        private int age;
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public Person(int age)
        {
            this.age = age;
        }
    
        public int compareTo(Person e) {//对比年龄的大小
            return (this.age - e.age);
        }
    
    }
    

    主函数是如下所示:

    public class Main {
        private static class personComparator implements Comparator<Person>
        {
            public int compare(Person e1, Person e2) {
                return e1.getAge() - e2.getAge();
            }
        }
    
        private static class personComparator2 implements Comparator<Person>
        {
    
            public int compare(Person e1, Person e2) {
                return e2.getAge() - e1.getAge();
            }
        }
        public static void main(String[] args) {
            Integer data[]  = new Integer[] {
                    7,4,9,2,5,8,11,3
            } ;
    
          /*  BinarySearchTree<Integer> bst = new BinarySearchTree<Integer>();
            for(int i = 0;i < data.length;i++)
            {   bst.add(data[i]);
            }
    */
    
            BinarySearchTree<Person> bst2 = new BinarySearchTree<Person>(new personComparator());
    
            bst2.add(new Person(12));
            bst2.add(new Person(15));
    
            BinarySearchTree<Person> bst3 = new BinarySearchTree<Person>(new personComparator2());
            bst2.add(new Person(12));
            bst2.add(new Person(15));
    
        }
    }
    

08 完美结合

  • 通过对于二叉搜索树的改写,可以进行相应的一个二者的结合,在compare函数之中进行定义相应的比较规则,代码是如下所示:
    
    public class BinarySearchTree<E>{
        private int size;
        private Node<E> root;
        private Comparator<E> comparator;
        public BinarySearchTree()
        {
            this(null);
        }
    
        public BinarySearchTree(Comparator<E> comparator)
        {
            this.comparator = comparator;
        }
    
        public int size() {
            return size;
        }
    
        public boolean isEmpty() {
            return size == 0;
        }
    
        public void clear() {
    
        }
    
        public void add(E element) {
            elementNOtNullCheck(element);
    
            //添加第一个节点
            if(root == null)
            {
                root = new Node<E>(element,null);
                size++;
                return ;
            }
    
            //添加的不是第一个节点
            //找到父节点
            Node<E> parent = null;//看下面的一句代码
            Node<E> node = root;
            int cmp = 0;
            while(node != null)
            {
                cmp = compare(element, node.element);
                parent = node;//这句话的含义是在进行比较之前进行一个节点的赋值,因为要是跳出循环之后,node=null,需要进行一个提前保存的过程.
                if (cmp > 0) {
                    node = node.right;
                } else if (cmp < 0) {
                    node = node.left;
                } else {
                    return;//什么也不干
                }
            }
    
            //插入到父节点的位置
            Node<E> newNode = new Node<E>(element,parent);
            if(cmp > 0)
            {
                parent.right = newNode;
            }
            else {
                parent.left = newNode;
            }
    
        }
    
        public void remove(E element) {
    
        }
    
        public boolean contains(E element) {
            return true;
        }
    
        //检查节点是否为空
        private void elementNOtNullCheck(E element)
        {
         if(element == null)
         {
         throw new IllegalArgumentException("element must not be null");
        }
        }
    
        /**
         * @return 返回值=0,e1=e2;返回值=1,e1>e2;返回值<0,e1<e2;
         * @param
         */
        private int compare(E e1,E e2)
        {
            if(comparator != null)
            {
                return comparator.compare(e1,e2);
            }
            return ((Comparable<E>)e1).compareTo(e2);
        }
    
        private static class Node<E>
        {
            E element;
            Node<E> left;
            Node<E> right;
            Node<E> parent;
            public Node(E element,Node<E> parent)
            {
                this.element = element;
                this.parent = parent;
            }
        }
    }
    

09 匿名类

  • 在main函数实现代码:
            /*
            Java的匿名类,类似于IOS之中的Block,JS之中的闭包(function)
             */
            BinarySearchTree<Person> bst4 = new BinarySearchTree<Person>(new Comparator<Person>() {
                public int compare(Person o1, Person o2) {
                    return 0;
                }
            });
    

10 打印器使用

  • 一个小小的网上,直接输入就是可以生成二叉树的网站.BinaryTreeGraph
  • 查看工具是小马哥已经编辑好的,引入BinarySearchTree,直接实现相应的接口.
  • BinarySearchTree之中的代码是如下所示:
    import printer.BinaryTreeInfo;
    
    import java.util.Comparator;
    
    public class BinarySearchTree<E extends Comparable> implements BinaryTreeInfo {
        private int size;
        private Node<E> root;
        private Comparator<E> comparator;
        public BinarySearchTree()
        {
            this(null);
        }
    
        public BinarySearchTree(Comparator<E> comparator)
        {
            this.comparator = comparator;
        }
    
        public int size() {
            return size;
        }
    
        public boolean isEmpty() {
            return size == 0;
        }
    
        public void clear() {
    
        }
    
        public void add(E element) {
            elementNOtNullCheck(element);
    
            //添加第一个节点
            if(root == null)
            {
                root = new Node<E>(element,null);
                size++;
                return ;
            }
    
            //添加的不是第一个节点
            //找到父节点
            Node<E> parent = null;//看下面的一句代码
            Node<E> node = root;
            int cmp = 0;
            while(node != null)
            {
                cmp = compare(element, node.element);
                parent = node;//这句话的含义是在进行比较之前进行一个节点的赋值,因为要是跳出循环之后,node=null,需要进行一个提前保存的过程.
                if (cmp > 0) {
                    node = node.right;
                } else if (cmp < 0) {
                    node = node.left;
                } else {
                    return;//什么也不干
                }
            }
    
            //插入到父节点的位置
            Node<E> newNode = new Node<E>(element,parent);
            if(cmp > 0)
            {
                parent.right = newNode;
            }
            else {
                parent.left = newNode;
            }
    
        }
    
        public void remove(E element) {
    
        }
    
        public boolean contains(E element) {
            return true;
        }
    
        //检查节点是否为空
        private void elementNOtNullCheck(E element)
        {
         if(element == null)
         {
         throw new IllegalArgumentException("element must not be null");
        }
        }
    
        /**
         * @return 返回值=0,e1=e2;返回值=1,e1>e2;返回值<0,e1<e2;
         * @param
         */
        private int compare(E e1,E e2)
        {
            if(comparator != null)
            {
                return comparator.compare(e1,e2);
            }
            return ((Comparable<E>)e1).compareTo(e2);
        }
    
        public Object root() {
            return root;
        }
    
        public Object left(Object node) {
            return ((Node<E>)node).left;
        }
    
        public Object right(Object node) {
            return ((Node<E>)node).right;
        }
    
        public Object string(Object node) {
            return ((Node<E>)node).element;
        }
    
        private static class Node<E>
        {
            E element;
            Node<E> left;
            Node<E> right;
            Node<E> parent;
            public Node(E element,Node<E> parent)
            {
                this.element = element;
                this.parent = parent;
            }
        }
    }
    

    主函数之中的打印流程是如下所示:

     public static void main(String[] args) {
            Integer data[]  = new Integer[] {
                    7,4,9,2,5,8,11,3
            } ;
    
           BinarySearchTree<Integer> bst = new BinarySearchTree<Integer>();
            for(int i = 0;i < data.length;i++)
            {   bst.add(data[i]);
            }
    
            BinaryTrees.println(bst);

    测试结果是如下所示:

 11 打印器Person

  •  加入Person打印的过程.
 static void test2()
    {
        BinarySearchTree<Person> bst2 = new BinarySearchTree<Person>(new personComparator());
        Integer data[]  = new Integer[] {
                7,4,9,2,5,8,11,3
        };

        for(int i = 0;i < data.length;i++)
        {   bst2.add(new Person(data[i]));
        }

        BinaryTrees.println(bst2);

    }
  • 打印结果是如下所示:

  • 如果要是想要打印年龄,就是需要进行一个重写toString的过程即可.在相应的Person类后面进行添加如下代码,需要进行注意的toString返回的必须是一个String类型的数值,因此,+""转换.
@Override
    public String toString() {
        return age + "";
    }
  • 打印结果如下所示:

12 打印器更多用法

  • 通过Math.random()函数进行一个随机数,进行测试即可.

13 打印器文件建议

 static void test3()
        {
            BinarySearchTree<Integer> bst = new BinarySearchTree<Integer>();
            for(int i = 0;i < 40;i++)
            {
                bst.add((int)(Math.random() * 100));
            }
            String str = BinaryTrees.printString(bst);
            Files.writeToFile("F:/1.txt",str);
        }

14 网站推荐

15 值相等处理

  • 直接进行一个覆盖,原因是因为比如说,在比较的过程之中只是进行比较相应的年龄,要是名字不一样就是需要进行一个覆盖操作.

16 前序遍历(Preorder Traversal)

  • 访问顺序
  • 前序遍历代码:
    /**
    	 * 前序遍历
    	 */
    	public void preorderTraversal() {
    		preorderTraversal(root);
    	}
    
    	private void preorderTraversal(Node<E> node) {
    		if (node == null) return;
    
    		System.out.println(node.element);
    		preorderTraversal(node.left);
    		preorderTraversal(node.right);
    	}
    

17 中序遍历

  • 遍历顺序:
  • 遍历代码:
    	/**
    	 * 中序遍历
    	 */
    	public void inorderTraversal() {
    		inorderTraversal(root);
    	}
    
    	private void inorderTraversal(Node<E> node) {
    		if (node == null) return;
    
    		inorderTraversal(node.left);
    		System.out.println(node.element);
    		inorderTraversal(node.right);
    	}

上述的代码进行一个位置的调换,将node.left与node.right的位置进行调换之后,打印输出是逆序的。

18 后序遍历

  • 遍历顺序
  • 遍历代码
    
    	/**
    	 * 后序遍历
    	 */
    	public void postorderTraversal() {
    		postorderTraversal(root);
    	}
    
    	private void postorderTraversal(Node<E> node) {
    		if (node == null) return;
    
    		postorderTraversal(node.left);
    		postorderTraversal(node.right);
    		System.out.println(node.element);
    	}

19 层序遍历

  • 遍历顺序
  • 遍历代码
    	/**
    	 * 层序遍历
    	 */
    	public void levelOrderTraversal() {
    		if (root == null) return;
    
    		Queue<Node<E>> queue = new LinkedList<>();
    		queue.offer(root);
    
    		while (!queue.isEmpty()) {
    			Node<E> node = queue.poll();
    			System.out.println(node.element);
    
    			if (node.left != null) {
    				queue.offer(node.left);
    			}
    
    			if (node.right != null) {
    				queue.offer(node.right);
    			}
    		}
    	}

20 设计遍历接口

  • 内部代码
	public static interface Vistor<E>
	{
		void visit(E element);
	}
	public void levelOrder(Vistor<E> vistor)
	{
		if (root == null) return;

		Queue<Node<E>> queue = new LinkedList<>();
		queue.offer(root);

		while (!queue.isEmpty()) {
			Node<E> node = queue.poll();
			vistor.visit(node.element);

			if (node.left != null) {
				queue.offer(node.left);
			}

			if (node.right != null) {
				queue.offer(node.right);
			}
		}
	}
  • 外部实现
bst.levelOrder(new Vistor<Integer>)
{
//方法重写即可,自定义进行一个输出的方式
}
  • 代码升级

	public void preorder(Visitor<E> visitor) {
		if (visitor == null) return;
		preorder(root, visitor);
	}
	
	private void preorder(Node<E> node, Visitor<E> visitor) {
		if (node == null || visitor.stop) return;
		
		visitor.stop = visitor.visit(node.element);
		preorder(node.left, visitor);
		preorder(node.right, visitor);
	}
	
	public void inorder(Visitor<E> visitor) {
		if (visitor == null) return;
		inorder(root, visitor);
	}
	
	private void inorder(Node<E> node, Visitor<E> visitor) {
		if (node == null || visitor.stop) return;
		
		inorder(node.left, visitor);
		if (visitor.stop) return;
		visitor.stop = visitor.visit(node.element);
		inorder(node.right, visitor);
	}
	
	public void postorder(Visitor<E> visitor) {
		if (visitor == null) return;
		postorder(root, visitor);
	}
	
	private void postorder(Node<E> node, Visitor<E> visitor) {
		if (node == null || visitor.stop) return;
		
		postorder(node.left, visitor);
		postorder(node.right, visitor);
		if (visitor.stop) return;
		visitor.stop = visitor.visit(node.element);
	}
	
	public void levelOrder(Visitor<E> visitor) {
		if (root == null || visitor == null) return;
		
		Queue<Node<E>> queue = new LinkedList<>();
		queue.offer(root);
		
		while (!queue.isEmpty()) {
			Node<E> node = queue.poll();
			if (visitor.visit(node.element)) return;
			
			if (node.left != null) {
				queue.offer(node.left);
			}
			
			if (node.right != null) {
				queue.offer(node.right);
			}
		}
	}

21 增强型遍历接口01

22 增强型遍历接口02

23 树状打印二叉树

24 计算二叉树的高度

25 完全二叉树的判断01

26 完全二叉树的判断02

27 翻转二叉树

28 重构二叉树

29 前驱节点

30 后继节点

31 remove01

32 remove02

33 remove03实现

34 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值