• 二叉查找树


    原帖地址 http://www.iteye.com/topic/561590

      1 import java.util.Collection;
      2 import java.util.Iterator;
      3 import java.util.NoSuchElementException;
      4 
      5 public class BinarySearchTree<E extends Comparable<E>> 
      6 {
      7     
      8     public static void main(String[] args)
      9     {
     10         BinarySearchTree<Integer> bst = new BinarySearchTree<Integer>();
     11         bst.add(50);  
     12         bst.add(37);  
     13         bst.add(75);  
     14         bst.add(25);  
     15         bst.add(61);  
     16         bst.add(15);  
     17         bst.add(30);  
     18         bst.add(55);  
     19         bst.add(68);  
     20         bst.add(28);  
     21         bst.add(32);  
     22         bst.add(59);  
     23         bst.add(36);  
     24         bst.add(36);
     25         
     26         //是否包含  
     27         System.out.println(bst.contains(36));//true  
     28         System.out.println(bst.contains(38));//false  
     29   
     30         //大小  
     31         System.out.println(bst.size());//13  
     32   
     33         //遍历  
     34         Iterator<Integer> itr = bst.iterator();  
     35         while (itr.hasNext()) {  
     36             //15 25 28 30 32 36 37 50 55 59 61 68 75  
     37             System.out.print(itr.next() + " ");  
     38         }  
     39         System.out.println();  
     40   
     41   
     42         //删除根叶子节点36  
     43         bst.remove(36);  
     44         System.out.println(bst.size());//12  
     45         itr = bst.iterator();  
     46         while (itr.hasNext()) {  
     47             //15 25 28 30 32 37 50 55 59 61 68 75  
     48             System.out.print(itr.next() + " ");  
     49         }  
     50         System.out.println();  
     51   
     52         //删除只有一个左子节点的节点37  
     53         bst.remove(37);  
     54         System.out.println(bst.size());//11  
     55         itr = bst.iterator();  
     56         while (itr.hasNext()) {  
     57             //15 25 28 30 32 50 55 59 61 68 75   
     58             System.out.print(itr.next() + " ");  
     59         }  
     60         System.out.println();  
     61   
     62         //删除只有一个右子节点的节点55  
     63         bst.remove(55);  
     64         System.out.println(bst.size());//10  
     65         itr = bst.iterator();  
     66         while (itr.hasNext()) {  
     67             //15 25 28 30 32 50 59 61 68 75   
     68             System.out.print(itr.next() + " ");  
     69         }  
     70         System.out.println();  
     71   
     72         //删除有左右子节点的根节点50  
     73         bst.remove(50);  
     74         System.out.println(bst.size());//9  
     75         itr = bst.iterator();  
     76         while (itr.hasNext()) {  
     77             //15 25 28 30 32 59 61 68 75   
     78             System.out.print(itr.next() + " ");  
     79         }  
     80         System.out.println();  
     81   
     82         //下面通过迭代器删除节点根节点59  
     83         itr = bst.iterator();  
     84         while (itr.hasNext()) {  
     85             if (itr.next() == 59) {  
     86                 itr.remove();//删除最近一次next返回的节点  
     87                 break;  
     88             }  
     89         }  
     90   
     91         while (itr.hasNext()) {  
     92             //61 68 75  
     93             System.out.print(itr.next() + " ");  
     94             itr.remove();  
     95         }  
     96   
     97         System.out.println();  
     98         System.out.println(bst.size());//5 
     99     }
    100     
    101     
    102     private Node root;
    103     
    104     private int size;
    105     
    106     
    107     public BinarySearchTree()
    108     {
    109         root = null;
    110     }
    111     
    112     
    113     /*
    114      * 二叉树插入操作,如果插入节点大于
    115      */
    116     public boolean add(E e)
    117     {
    118         Node<E> x = root, y = null;
    119         int compare = 0;
    120         
    121         while (x != null) {
    122             // y为每次循环x的父节点
    123             y = x;
    124             compare = e.compareTo(x.value);
    125 
    126             /*
    127              * 插入节点于当前结点相同则直接返回False
    128              * 如果插入节点e如比当前节点x小则将当前节点e指向当前节点的左节点e.left
    129              * 否则则将当前节点e指向当前结点右节点e.right
    130              */
    131             if (compare == 0) return false;
    132             
    133             if (compare == 1)
    134                 x = x.right;
    135             else
    136                 x = x.left;
    137         }
    138         
    139         if (y == null) {
    140             // y为空则表示root为空
    141             root = new Node(e, null);
    142         }
    143         else {
    144             // 根据之前判断创建新节点并指定为父节点y的左子节点或右子节点
    145             if (compare == 1)
    146                 y.right = new Node(e, y);
    147             else
    148                 y.left = new Node(e, y);
    149         }
    150         size++;
    151         return true;
    152     }
    153     
    154     
    155     public boolean contains(E e)
    156     {
    157         return getNode(e) != null;
    158     }
    159     
    160     
    161     private Node<E> getNode(E e)
    162     {
    163         Node<E> node = root;
    164         int compare;
    165         
    166         while (node != null) {
    167             compare = e.compareTo(node.value);
    168             
    169             if (compare == 0) return node;
    170             if (compare == 1) 
    171                 node = node.right;
    172             else
    173                 node = node.left;
    174         }
    175         
    176         return null;
    177     }
    178     
    179     
    180     public boolean remove(E e)
    181     {
    182         // 如果为空则直接返回
    183         Node<E> node = getNode(e);
    184         if (node == null) return false;
    185         removeNode(node);
    186         return true;
    187     }
    188     
    189     
    190     /*
    191      * 如果删除节点n是叶子节点,则直接删除该节点
    192      * 如果删除节点只有一个子节点,则将n的子节点与n的父节点直接连接,然后删除节点n
    193      * 如果删除节点n有两个子节点,则使用中序立遍历方式得到直接前置节点c或直接后继节点c得知代替节点n的值,然后删除c 
    194      */
    195     private void removeNode(Node<E> node)
    196     {
    197         // 有两个子节点
    198         if (node.left != null && node.right != null) {
    199             Node<E> child = intervalNode(node);
    200             node.value = child.value;
    201             node = child;
    202         }
    203         
    204         // 没有子节点,自身为叶子节点
    205         if (node.left == null && node.right == null) {
    206             // 
    207             if (node.parent == null) {
    208                 root = null;
    209             }
    210             else {
    211                 if (node == node.parent.left)
    212                     node.parent.left = null;
    213                 else
    214                     node.parent.right = null;
    215             }
    216         }
    217         else {
    218             // 只有一个节点的情况
    219             Node<E> replace;
    220             
    221             replace = node.left != null ? node.left : node.right;
    222             
    223             replace.parent = node.parent;
    224             
    225             if (node.parent == null) {
    226                 root = replace;
    227             }
    228             else if (node == node.parent.left) {
    229                 node.parent.left = replace;
    230             }
    231             else {
    232                 node.parent.right = replace;
    233             }
    234         }
    235         node.parent = null;
    236         node.left = node.right = null;
    237         size--;
    238     }
    239     
    240     
    241     /*
    242      * 查找中序遍历的直接后继节点
    243      * 
    244      * 如果待查找的节点有右子树,则后继节点一定在右子树上,此时右子树上的某个节点可能成为后 
    245      * 继节点:一是如果待查节点的右子树没有左子树(有没有右子树无所谓)时,直接就返回该待查节点 
    246      * 的右子节点;二是如果待点节点的右子节点有左子树,则查找右子节点的最左边的左子树节点(注, 
    247      * 该节点一点是左叶子节点或只有一个右子节点的左节点,查找过程要一直向左,即遍历时只向左拐, 
    248      * 不可向右)
    249      * 
    250      * 如果待查找的节点没有右子树,则需要从该节点向根的方向遍历(不可向左或右拐),后继节点只 
    251      * 可能在祖宗节点中产生(包括父节点与根节点在内),此情况分两种:一种就是待查节点为某节点的左 
    252      * 子树,则此时的后继为父节点;第二种就是当待查节点为某个节点的右子树时,则需沿根的方向向上找, 
    253      * 一直找到第一个有左子树的祖宗节点即为后继节点,或到根为止还没有找到(则该节点只可能为中序遍 
    254      * 历的最后节点
    255      */
    256     private Node intervalNode(Node node)
    257     {
    258         if (node == null) {
    259             return null;
    260         }
    261         else if (node.right != null) {
    262             /* 
    263              * 查找50节点的直接后继,查找结果为55 
    264              *            50 
    265              *             \ 
    266              *             75 
    267              *             / 
    268              *            61 
    269              *            /\ 
    270              *           55 68 
    271              *            \ 
    272              *            59               
    273              */ 
    274             
    275             Node<E> child = node.right;
    276             while (child.left != null) {
    277                 child = child.left;
    278             }
    279             return child;
    280         }
    281         else {
    282             /* 
    283              * 没有右子树的节点且为父节点的右子节点36的直接后继为37,同样节点68的直接后继为75 
    284              * 没有右子树的节点且为父节点的左子节点37的直接后继为50,同样节点28的直接后继为30 
    285              * 75为最后节点,所以直接后继为null 
    286              *  
    287              *                 50 
    288              *                 /\ 
    289              *                37 75 
    290              *                /   / 
    291              *               25   61  
    292              *               /\   /\ 
    293              *             15 30 55 68  
    294              *                /\  \ 
    295              *              28 32 59 
    296              *                  \ 
    297              *                  36 
    298              *                   / 
    299              *                  35 
    300              */ 
    301             
    302             Node<E> parent = node.parent;
    303             Node<E> current = node;
    304             
    305             while (parent != null && current == parent.right) {
    306                 current = parent;
    307                 parent = parent.parent;
    308             }
    309             return parent;
    310         }
    311     }
    312     
    313     
    314     public int size()
    315     {
    316         return size;
    317     }
    318     
    319     
    320     public Iterator<E> iterator()
    321     {
    322         return new TreeIterator();
    323     }
    324     
    325     
    326     public class TreeIterator implements Iterator<E>
    327     {
    328         private Node<E> lastReturned;
    329         
    330         private Node<E> next;
    331         
    332         private Node<E> endNode;
    333 
    334         
    335         public TreeIterator()
    336         {
    337             next = root;
    338             if (next != null) {
    339                 while (next.left != null) {
    340                     next = next.left;
    341                 }
    342             }
    343         }
    344         
    345         public boolean hasPreVious()
    346         {
    347             return (next != null && intervalNode(next) != null) || endNode != null;
    348         }
    349         
    350         
    351         public E previous()
    352         {
    353             if (next != null && intervalNode(next) == null) {
    354                 throw new NoSuchElementException();
    355             }
    356             
    357             if (endNode != null) {
    358                 lastReturned = next = endNode;
    359                 endNode = null;
    360             }
    361             else {
    362                 lastReturned = next = intervalNode(next);
    363             }
    364             return lastReturned.value;
    365         }
    366         
    367         public boolean hasNext() 
    368         {
    369             return next != null;
    370         }
    371 
    372         public E next() 
    373         {
    374             if (next == null)
    375                 throw new NoSuchElementException();
    376             
    377             lastReturned = next;
    378             next = intervalNode(next);
    379             
    380             if (next == null) {
    381                 endNode = lastReturned;
    382             }
    383             return lastReturned.value;
    384         }
    385 
    386         
    387         public void remove() 
    388         {
    389             if (lastReturned == null) {
    390                 throw new IllegalStateException();
    391             }
    392             
    393             if (lastReturned.left != null && lastReturned.right != null) {
    394                 next = lastReturned;
    395             }
    396             removeNode(lastReturned);
    397             lastReturned = null;
    398         }
    399 
    400     }
    401 
    402     
    403     public void preOrder(Collection<E> collect)
    404     {
    405         preOrder(root, collect);
    406     }
    407     
    408     
    409     private final void preOrder(Node<E> n, Collection<E> collect)
    410     {
    411         if (n != null) {
    412             collect.add(n.value);
    413             preOrder(n.left, collect);
    414             preOrder(n.right, collect);
    415         }
    416     }
    417     
    418     
    419     public void inOrder(Collection<E> collect)
    420     {
    421         inOrder(root, collect);
    422     }
    423     
    424     
    425     private void inOrder(Node<E> n, Collection<E> collect)
    426     {
    427         if (n == null) return;
    428         inOrder(n.left, collect);
    429         collect.add(n.value);
    430         inOrder(n.right, collect);
    431     }
    432     
    433     
    434     public void postOrder(Collection<E> collect)
    435     {
    436         postOrder(root, collect);
    437     }
    438     
    439     
    440     private final void postOrder(Node<E> n, Collection<E> collect)
    441     {
    442         if (n == null) return;
    443         postOrder(n.left, collect);
    444         postOrder(n.right, collect);
    445         collect.add(n.value);
    446     }
    447     
    448     
    449     private class Node<E>
    450     {
    451         private E value;
    452         
    453         private Node parent;
    454         
    455         private Node left;
    456         
    457         private Node right;
    458         
    459         public Node(E value, Node parent)
    460         {
    461             this.value = value;
    462             this.parent = parent;
    463         }
    464     }
    465 }
  • 相关阅读:
    20145总结
    2014515 总结
    2014514 总结
    20148总结
    20147总结
    20146总结
    20149总结
    2014512 总结
    2014513 总结
    【Visual Lisp】驱动器、目录、文件和注册表
  • 原文地址:https://www.cnblogs.com/rilley/p/2586388.html
Copyright © 2020-2023  润新知