二叉搜索树

二叉搜索树的特点:

二叉搜索树的左节点小于它的父节点,右节点大于父节点

二叉搜索树中的结点:

 1     private static class Node<E>{
 2 
 3         private E element;
 4         private Node<E> parent;
 5         private Node<E> left;
 6         private Node<E> right;
 7 
 8         public Node(E element, Node<E> parent){
 9             this.element = element;
10             this.parent = parent;
11         }
12 
13     }

二叉搜索树的添加方法:

 public void add(E element){
        if(size == 0){
            root = new Node<E>(element,null);//创建一个头节点
        }

        Node<E> parent = root;
        Node<E> node = root;
        int cmp = 0;

        while(node != null){
            cmp = compare(element,node.element);//比较两个节点的大小
            parent = node;
            if(cmp > 0){
                node = node.right;
            }else if(cmp < 0){
                node = node.left;
            }else{
                return;
            }
        }

        if(cmp > 0 ){
            parent.right = new Node<E>(element,parent);
        }else if(cmp < 0 ){
            parent.left = new Node<E>(element,parent);
        }else{
            parent.element = element;
        }
        
        size++;
    }

二叉搜索树中的元素的比较

1.插入的元素中实现Comparable接口,重写compare方法.

2.如果插入的元素不想实现接口,

 

 在创建二叉搜索树的时候new 一个Comparator的匿名内部类,重写compare方法.

二叉树的遍历(所有二叉树)

前序遍历:

先访问该节点,在访问该节点的左子树,然后访问该节点的右子树.

public void preOrderTree(){
    preOrderTree(root);
}

private void preOrderTree(Node<E> node){
    if(node == null) return;

     System.out.println(node.element);
     preOrderTree(node.left);
     preOrderTree(node.right);
}    

中序遍历:

中序遍历根节点的左子树,访问根节点,中序遍历根节点的右子树

public void inOrderTree(){
        inOrderTree(root);
    }

    private void inOrderTree(Node<E> node){
        if(node == null) return;
        inOrderTree(node.left);
        System.out.println(node.element);
        inOrderTree(node.right);
    }

后序遍历

后序遍历根节点的左子树,后序遍历根节点的右子树,访问根节点.

public void  lastOrderTree(){
        inOrderTree(root);
    }

private void lastOrderTree(Node<E> node){
    if(node == null) return;
    System.out.println(node.element);
    inOrderTree(node.left);
    inOrderTree(node.right);
 }

层序遍历

从根节点开始一层一层的访问节点

   public void levelOrderTree(Node<E> root){
        Queue<Node<E>> queue = (Queue<Node<E>>) new LinkedList<E>();
        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);
            }
        }
    }

利用队列先进先出的特点,每次弹出一个,就把他的左右节点添加进来.

前驱结点:对一棵二叉树进行中序遍历,遍历后的顺序,当前节点的前一个节点为该节点的前驱节点;

后继节点:对一棵二叉树进行中序遍历,遍历后的顺序,当前节点的后一个节点为该节点的后继节点;

前驱结点的实现:

 public Node<E> predecessor(Node<E> node){
        if(node == null) return null;
     
      
      //如果该结点有左子节点,那么该节点的前驱结点就是左子节点的最后一个右子节点
if(node.left != null){ node = node.left; while(node.right != null){ node = node.right; } return node; }      
    
     //如果该节点没有左子节点,那么分两种情况,如果这个节点在父节点的右边,那么这个父节点就是前驱结点
     //吐过这个节点在父节点的左边,那么就要找父节点的父节点,知道父节点在前一个父节点的右边.
while(node.parent != null && node.parent.right != node){ node = node.parent; } return node.parent; }

二叉搜索树的删除方法:

 public void remove(Node<E> node){
        if(node == null) return;

        //当删除的节点有两个子节点时
        if(node.left != null && node.right != null){
            Node<E> s = predecessor(node);//前序节点只可能有一个左子点或者没有子节点
            node.element = s.element;
            s = node; //把前序节点的值赋给要删除的节点,然后把node指向这个前序节点,那么就只需要删除前序节点就可.
        }
        
        //我觉得replacement只可能是node.left或者为null;不用加node.right
        Node<E> replacement = node.left != null ? node.left : node.right;
        
        if(replacement != null){
            replacement.parent = node.parent;//如果node有一个子节点的话,把node的父节点赋给子节点
            if(node.parent == null){
                root = replacement;//如果node没有父节点的话,那么他就是根节点
            }else if(node.parent.left == node){
                node.parent.left = replacement;
            }else if(node.parent.right == node){
                node.parent.right = replacement;
            }
            //根据node节点在父节点的左边还是右边赋给node的子节点.这样,node就被删除了
        }else if(node.parent == null){
            root = null;
        }else{
            if(node == node.parent.left){
                node.parent.left = null;
            }else if(node == node.parent.right){ //如果node没有子节点的话,那么就直接删除
                node.parent.right = null;
            }
        }


    }
原文地址:https://www.cnblogs.com/lzh66/p/12944631.html