zoukankan      html  css  js  c++  java
  • 二叉搜索树

    二叉搜索树的特点:

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

    二叉搜索树中的结点:

     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;
                }
            }
    
    
        }
  • 相关阅读:
    删除sql注入
    查询所有数据库,数据集
    删除SQL注入的一些方法总结
    需求变更
    ASP/SQL 注入天书
    js元素闪动效果
    JS 运行、复制、另存为 代码。
    判断是否是手机访问及大致手机网页格式
    过滤资源地址
    Tomcat目录介绍以及运行时寻找class的顺序
  • 原文地址:https://www.cnblogs.com/lzh66/p/12944631.html
Copyright © 2011-2022 走看看