码迷,mamicode.com
首页 > 其他好文 > 详细

二叉查找树

时间:2016-05-13 09:58:25      阅读:257      评论:0      收藏:0      [点我收藏+]

标签:

二叉排序树或者是一棵空树,或者是具有下列性质的二叉树:
(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(3)左、右子树也分别为二叉排序树;
(4)没有键值相等的节点。
图片表示
技术分享
 
============================================================================
======================最好理解的数字树节点=======================================
============================================================================
/**
 * 树节点
 */
public class TreeNode {

     int key;//节点的数值
     TreeNode leftChild;//左子节点
     TreeNode rightChild;//右子节点
     TreeNode parent;//父节点
    
    public TreeNode(int key,TreeNode leftChild,TreeNode rightChild,TreeNode parent){
        this.key=key;
        this.leftChild=leftChild;
        this.rightChild=rightChild;
        this.parent=parent;
    }

    public int getKey() {  
        return key;  
    }
    public String toString(){
        String leftkey = (leftChild==null?"":String.valueOf(leftChild.key));
        String rightkey = (rightChild==null?"":String.valueOf(rightChild.key));
        return "("+leftkey+","+key+","+rightkey+")";
    }
}
package test4;

import java.util.ArrayList;
import java.util.List;

public class BinarySearchTree {

    //根节点
    TreeNode root = null;
    //遍历节点列表
    List<TreeNode> list = new ArrayList<TreeNode>();
    
    /**
     * 判断二叉树是否为空
     * @return
     */
    public boolean isEmpty(){
        if(null==root){
            return true;
        }
        return false;
    }
     /** 
     * search: 在二叉查找树中查询给定关键字 
     * @param key 
     */
    public TreeNode search(int key){
        TreeNode pNode = root;
        while(pNode!=null&&pNode.key!=key){
            if(key<pNode.key){
                pNode=pNode.leftChild;
            }else{
                pNode=pNode.rightChild;
            }
        }
        return pNode;
    }
    /**
     * 获取二叉查找树中的最小关键字结点 
     * @return
     * @throws Exception 
     */
    public TreeNode minNode(TreeNode node) throws Exception{
        if(node==null){
            throw new Exception("null tree");
        }
        TreeNode pNode = node;
        while(pNode.leftChild!=null){
            pNode=pNode.leftChild;
        }
        return pNode;
    }
    
    /**
     * 获取二叉查找树中的最大关键字结点 
     * @return
     * @throws Exception 
     */
    public TreeNode maxNode(TreeNode node) throws Exception{
        if(null==node){
            throw new Exception("null tree");
        }
        TreeNode pNode = node;
        while(pNode.rightChild!=null){
            pNode = pNode.rightChild;
        }
        return pNode;
    }
    
    /**
     * 将给定关键字插入到二叉查找树中
     * @param key
     */
    public void insert(int key){
        TreeNode parentNode = null;
        TreeNode newNode = new TreeNode(key, null, null, null);
        TreeNode pNode = root;
        if(root==null){
            root = newNode;
            return;
        }
        while(pNode!=null){
            parentNode = pNode;
            if(key>pNode.key){
                pNode = pNode.rightChild;
            }else if(key<pNode.key){
                pNode = pNode.leftChild;
            }else{
                return;//设定不能插入相同的数字
            }
        }
        if(key<parentNode.key){
            parentNode.leftChild = newNode;
            newNode.parent = parentNode;
        }else{
            parentNode.rightChild = newNode;
            newNode.parent = parentNode;
        }
    }
     /** 
     * successor: 获取给定结点在中序遍历顺序下的后继结点 
     *  
     * @param node 
     *            给定树中的结点 
     * @return 若该结点存在中序遍历顺序下的后继结点,则返回其后继结点;否则返回 null 
     *  分为三种情况:
        1.一个节点有右孩子,则在中序遍历中,该节点的后继是它的右子树的最左节点。
        2. 这个节点是它父亲的左孩子,则该节点的后继节点是它的父亲
        3. 这个节点是它父亲的右孩子,则需要一直向上搜索,直到它们n-1代祖先是它第n代祖先的左孩子,
                           则它的后继就是第n个祖先。如果一直搜索到根节点,也没有找到n-1代祖先是它第n代祖先的左孩子,
                           则该节点是整个树的中序遍历中的最后一个节点,即它没有后继。
     * @throws Exception 
     */  
    public TreeNode successor(TreeNode node) throws Exception {  
        if (node == null) {  
            return null;  
        }  
  
        // 若该结点的右子树不为空,则其后继结点就是右子树中的最小关键字结点  
        if (node.rightChild != null) {  
            return minNode(node.rightChild);  
        }  
        // 若该结点右子树为空  
        TreeNode parentNode = node.parent;  
        while (parentNode != null && node == parentNode.rightChild) {  
            node = parentNode;  
            parentNode = parentNode.parent;  
        }  
        return parentNode;  
    } 
    
    /** 
     * precessor: 获取给定结点在中序遍历顺序下的前趋结点 
     *  
     * @param node 
     *            给定树中的结点 
     * @return 若该结点存在中序遍历顺序下的前趋结点,则返回其前趋结点;否则返回 null 
     * @throws Exception 
     */  
    public TreeNode precessor(TreeNode node) throws Exception {  
        if (node == null) {  
            return null;  
        }  
  
        // 若该结点的左子树不为空,则其前趋结点就是左子树中的最大关键字结点  
        if (node.leftChild != null) {  
            return maxNode(node.leftChild);  
        }  
        // 若该结点左子树为空  
        TreeNode parentNode = node.parent;  
        while (parentNode != null && node == parentNode.leftChild) {  
            node = parentNode;  
            parentNode = parentNode.parent;  
        }  
        return parentNode;  
    }  
    
    /**
     * 删除节点
     * @param key
     * @throws Exception
     */
    public void delete(int key) throws Exception{
        TreeNode node = search(key);
            if(node==null){
                throw new Exception("不存在");
            }
            delete(node);
    }
    private void delete(TreeNode node) throws Exception {
        if(node==null){
            return;
        }
        //既没有左侧节点,又没有右侧节点
        if(node.leftChild==null&&node.rightChild==null){
            TreeNode parentNode = node.parent;
            if(parentNode.leftChild==node){
                parentNode.leftChild=null;
            }else{
                parentNode.rightChild=null;
            }
            return;
        }
        //没有左侧节点,有右侧节点
        if(node.leftChild==null&&node.rightChild!=null){
            TreeNode parentNode = node.parent;
            if(parentNode.leftChild==node){
                parentNode.leftChild=node.rightChild;
                node.rightChild.parent=parentNode;
            }else{
                parentNode.rightChild=node.rightChild;
                node.rightChild.parent=parentNode;
            }
            return;
        }
        //有左侧节点,没有右侧节点
        if(node.leftChild!=null&&node.rightChild==null){
            TreeNode parentNode = node.parent;
            if(parentNode.leftChild==node){
                parentNode.leftChild=node.leftChild;
                node.leftChild.parent=parentNode;
            }else{
                parentNode.rightChild=node.leftChild;
                node.leftChild.parent=parentNode;
            }
            return;
        }
    
        //左右节点都有
        TreeNode successorNode = successor(node);  
        delete(successorNode);  
        node.key = successorNode.key;  
    }
    
    /**
     * 二叉查找树的中序遍历结点列表 
     * @return
     */
    public List<TreeNode> inOrderTraverseList(){
        if(list!=null){
            list.clear();
        }
        inOrderTraverse(root);
        return list;
    }
    //    二叉查找树的中序遍历结点列表 
    private void inOrderTraverse(TreeNode root) {
        if(root!=null){
            inOrderTraverse(root.leftChild);
            list.add(root);
            inOrderTraverse(root.rightChild);
        }
    }
    /** 
     * 获取二叉查找树中关键字的有序列表 
     *  
     * @return 二叉查找树中关键字的有序列表 
     */  
    public String toStringOfOrderList() {  
        StringBuilder sbBuilder = new StringBuilder(" [ ");  
        for (TreeNode p : inOrderTraverseList()) {  
            sbBuilder.append(p.key);  
            sbBuilder.append(" ");  
        }  
        sbBuilder.append("]");  
        return sbBuilder.toString();  
    }  
    /** 
     * 获取该二叉查找树的字符串表示 
     */  
    public String toString() {  
        StringBuilder sbBuilder = new StringBuilder(" [ ");  
        for (TreeNode p : inOrderTraverseList()) {  
            sbBuilder.append(p);  
            sbBuilder.append(" ");  
        }  
        sbBuilder.append("]");  
        return sbBuilder.toString();  
    }  
  
    public TreeNode getRoot() {  
        return root;  
    }    
}

上面还提到中序遍历

中序遍历(LDR)是二叉树遍历的一种,也叫做中根遍历、中序周游,可记做左根右

中序遍历首先遍历左子树,然后访问根结点,最后遍历右子树。在遍历左、右子树时,

仍然先遍历左子树,再访问根结点,最后遍历右子树

技术分享返回DBEAFC
此外还有前序后序

前序遍历:根节点->左子树->右子树

中序遍历:左子树->根节点->右子树

后序遍历:左子树->右子树->根节点

层次遍历:第一层->第二层->...eg:12345678

技术分享

package test4;

public class test {

    public static void main(String[] args) {
        try {  
            BinarySearchTree bst = new BinarySearchTree();  
            System.out.println("查找树是否为空? " + (bst.isEmpty() ? "是" : "否"));  
            int[] keys = new int[] { 15, 6, 18, 3, 7, 13, 20, 2, 9, 4 };  
            for (int key : keys) {  
                bst.insert(key);  
            }  
            System.out.println("查找树是否为空? " + (bst.isEmpty() ? "是" : "否"));  
            TreeNode minkeyNode = bst.minNode(bst.getRoot());  
            System.out.println("最小关键字: " + minkeyNode.getKey());  
            testNode(bst, minkeyNode);  
            TreeNode maxKeyNode = bst.maxNode(bst.getRoot());  
            System.out.println("最大关键字: " + maxKeyNode.getKey());  
            testNode(bst, maxKeyNode);  
            System.out.println("根结点关键字: " + bst.getRoot().getKey());  
            testNode(bst, bst.getRoot());  
            testTraverse(bst);  
            System.out.println("****************************** ");  
            testTraverse(bst);  
        } catch (Exception e) {  
            System.out.println(e.getMessage());  
            e.printStackTrace();  
        }  

    }
     public static void testNode(BinarySearchTree bst, TreeNode pNode)  
                throws Exception {  
            System.out.println("本结点: " + pNode);  
            System.out.println("前趋结点: " + bst.precessor(pNode));  
            System.out.println("后继结点: " + bst.successor(pNode));  
        }  
      
    public static void testTraverse(BinarySearchTree bst) {  
        System.out.println("二叉树遍历:" + bst);  
        System.out.println("二叉查找树转换为有序列表: " + bst.toStringOfOrderList());  
    } 

}

 

==============================================================================
=================================Object的二叉树====================================
==============================================================================
package test5;

/**
 * 树节点
 */
public class TreeNode {

    Object key;
    Object value;
    TreeNode left;
    TreeNode right;
    TreeNode(Object key, Object value, TreeNode left, TreeNode right) {
        this.key = key;
        this.value = value;
        this.left = left;
        this.right = right;
    }
    TreeNode(Object key, Object value) {
        this(key, value, null, null);
    }
    public String toString() {
        return "[" + key + ":" + value + "]";
    }
}
package test5;

import java.util.Comparator;
import java.util.LinkedList;
import java.util.Queue;


public class BinarySearchTree {
     TreeNode root;
     private Comparator<Object> cmp;
     public BinarySearchTree(Comparator<Object> cmp) {
         this.cmp = cmp;
     }
     public String toString() {
         return inOrderString();
     }
     public String inOrderString() {
         StringBuilder sb = new StringBuilder();
         _inOrder(sb, root);
         return sb.toString();
     }
     /**
      * 中序遍历
      */
     private void _inOrder(StringBuilder sb, TreeNode n) {
         if (n.left != null) _inOrder(sb, n.left);
         sb.append(n + " ");
         if (n.right != null) _inOrder(sb, n.right);
     }
     
     /**
      * 层次遍历
      * @return
      */
     public String levelOrderString() {
        if (root == null) return "";
        StringBuilder sb = new StringBuilder();
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.add(root);
        TreeNode node;
        while ((node = (TreeNode)queue.poll()) != null) {
            sb.append(node + " ");
            if (node.left != null) queue.add(node.left);
            if (node.right != null) queue.add(node.right);
            }
            return sb.toString();
        }
     
     public TreeNode max() {
         if (root == null) return null;
         TreeNode n = root;
         while (n.right != null) n = n.right;
         return n;
     }
     public TreeNode min() {
         if (root == null) return null;
         TreeNode n = root;
         while (n.left != null) n = n.left;
         return n;
     }
     
     public boolean insert(TreeNode node) {
         if (root == null) {
             root = node;
             return true;
         }
         TreeNode n = root;
         TreeNode parent = n;
         boolean isLeft = false;
         while (n != null) {
             int result = cmp.compare(node.key, n.key);
             if (result == 0) return false;
             else if (result > 0) {
                 parent = n;
                 n = n.right;
                 isLeft = false;
             } else {
                 parent = n;
                 n = n.left;
                 isLeft = true;
             }
         }
         if (isLeft) parent.left = node;
         else parent.right = node;
         return true;
     }
     
     public TreeNode find(Object key) {
         TreeNode n = root;
         while (n != null) {
             int result = cmp.compare(key, n.key);
             if (result == 0) return n;
             else if (result > 0) n = n.right;
             else n = n.left;
         }
         return n;
     }
         
     public boolean remove(Object key) {
         if (root == null) return false;
         TreeNode n = root;
         TreeNode parent = n;
         boolean isLeft = false;
         while (n != null) {
             int result = cmp.compare(key, n.key);
             if (result == 0) {
                 _delete(parent, n, isLeft);
                 return true;
             } else if (result > 0) {
                 isLeft = false;
                 parent = n;
                 n = n.right;
             } else {
                 isLeft = true;
                 parent = n;
                 n = n.left;
             }
         }
         return false;
     }
     private void _delete(TreeNode parent, TreeNode node, boolean isLeft) {
         if (node.left == null && node.right == null) {  //叶子节点
             if (node == root) root = null;
             else if (isLeft) parent.left = null;
             else parent.right = null;
         } else if (node.left == null) { //仅有右子树
             if (node == root) root = node.right;
             else if (isLeft) parent.left = node.right;
             else parent.right = node.right;
         } else if (node.right == null) {    //仅有左子树
             if (node == root) root = node.left;
             else if (isLeft) parent.left = node.left;
             else parent.right = node.left;
         } else {    //左右子树均存在
             //找到右子树最小节点n
             TreeNode n = node.right;
             TreeNode np = node;
             while (n.left != null) {
                 np = n;
                 n = n.left;
             }
        //将n的key和value赋给node
        node.key = n.key;
        node.value = n.value;
        //删除n
        _delete(np, n, true);
         }
     }
}
package test5;

import java.util.Comparator;
import java.util.Random;

public class test {

    public static void main(String[] args) {
        Random rand = new Random();
        BinarySearchTree bst = new BinarySearchTree(new Comparator<Object>() {
            @Override
            public int compare(Object o1, Object o2) {
                if (!(o1 instanceof Integer) || ! (o2 instanceof Integer))
                    throw new RuntimeException("compare()参数非整型");
                return ((Integer)o1).compareTo((Integer)o2);
            }
        });
        bst.insert(new TreeNode(0, 0));
        bst.insert(new TreeNode(50, 50));
        bst.insert(new TreeNode(100, 100));
        for (int i = 0; i < 10; i++) {
            bst.insert(new TreeNode(rand.nextInt(100), rand.nextInt(100)));
        }
        System.out.println(bst);
        System.out.println(bst.levelOrderString());
        System.out.println(bst.min() + " <<< " + bst.max());
        System.out.println(bst.find(0) + " " + bst.find(50) + " " + bst.find(100));
        bst.remove(0);
        bst.remove(50);
        bst.remove(100);
        System.out.println(bst);
    }
    
}

 

 

二叉查找树

标签:

原文地址:http://www.cnblogs.com/itliucheng/p/5485854.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!