zoukankan      html  css  js  c++  java
  • 第12章 高级数据结构及其实现

    自顶向下伸展树

      1 // SplayTree class
      2 //
      3 // CONSTRUCTION: with no initializer
      4 //
      5 // ******************PUBLIC OPERATIONS*********************
      6 // void insert( x )       --> Insert x
      7 // void remove( x )       --> Remove x
      8 // boolean contains( x )  --> Return true if x is found
      9 // Comparable findMin( )  --> Return smallest item
     10 // Comparable findMax( )  --> Return largest item
     11 // boolean isEmpty( )     --> Return true if empty; else false
     12 // void makeEmpty( )      --> Remove all items
     13 // ******************ERRORS********************************
     14 // Throws UnderflowException as appropriate
     15 
     16 /**
     17  * Implements a top-down splay tree.
     18  * Note that all "matching" is based on the compareTo method.
     19  * @author Mark Allen Weiss
     20  */
     21 public class SplayTree<AnyType extends Comparable<? super AnyType>>
     22 {
     23     /**
     24      * Construct the tree.
     25      */
     26     public SplayTree( )
     27     {
     28         nullNode = new BinaryNode<AnyType>( null );
     29         nullNode.left = nullNode.right = nullNode;
     30         root = nullNode;
     31     }
     32 
     33     private BinaryNode<AnyType> newNode = null;  // Used between different inserts
     34     
     35     /**
     36      * Insert into the tree.
     37      * @param x the item to insert.
     38      */
     39     public void insert( AnyType x )
     40     {
     41         if( newNode == null )
     42             newNode = new BinaryNode<AnyType>( null );
     43         newNode.element = x;
     44 
     45         if( root == nullNode )
     46         {
     47             newNode.left = newNode.right = nullNode;
     48             root = newNode;
     49         }
     50         else
     51         {
     52             root = splay( x, root );
     53             
     54             int compareResult = x.compareTo( root.element );
     55             
     56             if( compareResult < 0 )
     57             {
     58                 newNode.left = root.left;
     59                 newNode.right = root;
     60                 root.left = nullNode;
     61                 root = newNode;
     62             }
     63             else
     64             if( compareResult > 0 )
     65             {
     66                 newNode.right = root.right;
     67                 newNode.left = root;
     68                 root.right = nullNode;
     69                 root = newNode;
     70             }
     71             else
     72                 return;   // No duplicates
     73         }
     74         newNode = null;   // So next insert will call new
     75     }
     76 
     77     /**
     78      * Remove from the tree.
     79      * @param x the item to remove.
     80      */
     81     public void remove( AnyType x )
     82     {
     83         if( !contains( x ) )
     84             return;
     85 
     86         BinaryNode<AnyType> newTree;
     87 
     88             // If x is found, it will be splayed to the root by contains
     89         if( root.left == nullNode )
     90             newTree = root.right;
     91         else
     92         {
     93             // Find the maximum in the left subtree
     94             // Splay it to the root; and then attach right child
     95             newTree = root.left;
     96             newTree = splay( x, newTree );
     97             newTree.right = root.right;
     98         }
     99         root = newTree;
    100     }
    101 
    102     /**
    103      * Find the smallest item in the tree.
    104      * Not the most efficient implementation (uses two passes), but has correct
    105      *     amortized behavior.
    106      * A good alternative is to first call find with parameter
    107      *     smaller than any item in the tree, then call findMin.
    108      * @return the smallest item or throw UnderflowException if empty.
    109      */
    110     public AnyType findMin( )
    111     {
    112         if( isEmpty( ) )
    113             throw new UnderflowException( );
    114 
    115         BinaryNode<AnyType> ptr = root;
    116 
    117         while( ptr.left != nullNode )
    118             ptr = ptr.left;
    119 
    120         root = splay( ptr.element, root );
    121         return ptr.element;
    122     }
    123 
    124     /**
    125      * Find the largest item in the tree.
    126      * Not the most efficient implementation (uses two passes), but has correct
    127      *     amortized behavior.
    128      * A good alternative is to first call find with parameter
    129      *     larger than any item in the tree, then call findMax.
    130      * @return the largest item or throw UnderflowException if empty.
    131      */
    132     public AnyType findMax( )
    133     {
    134         if( isEmpty( ) )
    135             throw new UnderflowException( );
    136 
    137         BinaryNode<AnyType> ptr = root;
    138 
    139         while( ptr.right != nullNode )
    140             ptr = ptr.right;
    141 
    142         root = splay( ptr.element, root );
    143         return ptr.element;
    144     }
    145 
    146     /**
    147      * Find an item in the tree.
    148      * @param x the item to search for.
    149      * @return true if x is found; otherwise false.
    150      */
    151     public boolean contains( AnyType x )
    152     {
    153         if( isEmpty( ) )
    154             return false;
    155             
    156         root = splay( x, root );
    157 
    158         return root.element.compareTo( x ) == 0;
    159     }
    160 
    161     /**
    162      * Make the tree logically empty.
    163      */
    164     public void makeEmpty( )
    165     {
    166         root = nullNode;
    167     }
    168 
    169     /**
    170      * Test if the tree is logically empty.
    171      * @return true if empty, false otherwise.
    172      */
    173     public boolean isEmpty( )
    174     {
    175         return root == nullNode;
    176     }
    177 
    178     private BinaryNode<AnyType> header = new BinaryNode<AnyType>( null ); // For splay
    179     
    180     /**
    181      * Internal method to perform a top-down splay.
    182      * The last accessed node becomes the new root.
    183      * @param x the target item to splay around.
    184      * @param t the root of the subtree to splay.
    185      * @return the subtree after the splay.
    186      */
    187     private BinaryNode<AnyType> splay( AnyType x, BinaryNode<AnyType> t )
    188     {
    189         BinaryNode<AnyType> leftTreeMax, rightTreeMin;
    190 
    191         header.left = header.right = nullNode;
    192         leftTreeMax = rightTreeMin = header;
    193 
    194         nullNode.element = x;   // Guarantee a match
    195 
    196         for( ; ; )
    197         {
    198             int compareResult = x.compareTo( t.element );
    199             
    200             if( compareResult < 0 )
    201             {
    202                 if( x.compareTo( t.left.element ) < 0 )
    203                     t = rotateWithLeftChild( t );
    204                 if( t.left == nullNode )
    205                     break;
    206                 // Link Right
    207                 rightTreeMin.left = t;
    208                 rightTreeMin = t;
    209                 t = t.left;
    210             }
    211             else if( compareResult > 0 )
    212             {
    213                 if( x.compareTo( t.right.element ) > 0 )
    214                     t = rotateWithRightChild( t );
    215                 if( t.right == nullNode )
    216                     break;
    217                 // Link Left
    218                 leftTreeMax.right = t;
    219                 leftTreeMax = t;
    220                 t = t.right;
    221             }
    222             else
    223                 break;
    224         }    
    225 
    226         leftTreeMax.right = t.left;
    227         rightTreeMin.left = t.right;
    228         t.left = header.right;
    229         t.right = header.left;
    230         return t;
    231     }
    232 
    233     /**
    234      * Rotate binary tree node with left child.
    235      * For AVL trees, this is a single rotation for case 1.
    236      */
    237     private static <AnyType> BinaryNode<AnyType> rotateWithLeftChild( BinaryNode<AnyType> k2 )
    238     {
    239         BinaryNode<AnyType> k1 = k2.left;
    240         k2.left = k1.right;
    241         k1.right = k2;
    242         return k1;
    243     }
    244 
    245     /**
    246      * Rotate binary tree node with right child.
    247      * For AVL trees, this is a single rotation for case 4.
    248      */
    249     private static <AnyType> BinaryNode<AnyType> rotateWithRightChild( BinaryNode<AnyType> k1 )
    250     {
    251         BinaryNode<AnyType> k2 = k1.right;
    252         k1.right = k2.left;
    253         k2.left = k1;
    254         return k2;
    255     }
    256 
    257     // Basic node stored in unbalanced binary search trees
    258     private static class BinaryNode<AnyType>
    259     {
    260             // Constructors
    261         BinaryNode( AnyType theElement )
    262         {
    263             this( theElement, null, null );
    264         }
    265 
    266         BinaryNode( AnyType theElement, BinaryNode<AnyType> lt, BinaryNode<AnyType> rt )
    267         {
    268             element  = theElement;
    269             left     = lt;
    270             right    = rt;
    271         }
    272 
    273         AnyType element;            // The data in the node
    274         BinaryNode<AnyType> left;   // Left child
    275         BinaryNode<AnyType> right;  // Right child
    276     }
    277 
    278     private BinaryNode<AnyType> root;
    279     private BinaryNode<AnyType> nullNode;
    280     
    281 
    282         // Test program; should print min and max and nothing else
    283     public static void main( String [ ] args )
    284     {
    285         SplayTree<Integer> t = new SplayTree<Integer>( );
    286         final int NUMS = 40000;
    287         final int GAP  =   307;
    288 
    289         System.out.println( "Checking... (no bad output means success)" );
    290 
    291         for( int i = GAP; i != 0; i = ( i + GAP ) % NUMS )
    292             t.insert( i );
    293         System.out.println( "Inserts complete" );
    294 
    295         for( int i = 1; i < NUMS; i += 2 )
    296             t.remove( i );
    297         System.out.println( "Removes complete" );
    298 
    299         if( t.findMin( ) != 2 || t.findMax( ) != NUMS - 2 )
    300             System.out.println( "FindMin or FindMax error!" );
    301 
    302         for( int i = 2; i < NUMS; i += 2 )
    303             if( !t.contains( i ) )
    304                 System.out.println( "Error: find fails for " + i );
    305 
    306         for( int i = 1; i < NUMS; i += 2 )
    307             if( t.contains( i ) )
    308                 System.out.println( "Error: Found deleted item " + i );
    309     }
    310 }

    红黑树

      1 // RedBlackTree class
      2 //
      3 // CONSTRUCTION: with no parameters
      4 //
      5 // ******************PUBLIC OPERATIONS*********************
      6 // void insert( x )       --> Insert x
      7 // void remove( x )       --> Remove x (unimplemented)
      8 // boolean contains( x )  --> Return true if x is found
      9 // Comparable findMin( )  --> Return smallest item
     10 // Comparable findMax( )  --> Return largest item
     11 // boolean isEmpty( )     --> Return true if empty; else false
     12 // void makeEmpty( )      --> Remove all items
     13 // void printTree( )      --> Print all items
     14 // ******************ERRORS********************************
     15 // Throws UnderflowException as appropriate
     16 
     17 /**
     18  * Implements a red-black tree.
     19  * Note that all "matching" is based on the compareTo method.
     20  * @author Mark Allen Weiss
     21  */
     22 public class RedBlackTree<AnyType extends Comparable<? super AnyType>>
     23 {
     24     /**
     25      * Construct the tree.
     26      */
     27     public RedBlackTree( )
     28     {
     29         nullNode = new RedBlackNode<>( null );
     30         nullNode.left = nullNode.right = nullNode;
     31         header      = new RedBlackNode<>( null );
     32         header.left = header.right = nullNode;
     33     }
     34 
     35     /**
     36      * Compare item and t.element, using compareTo, with
     37      * caveat that if t is header, then item is always larger.
     38      * This routine is called if is possible that t is header.
     39      * If it is not possible for t to be header, use compareTo directly.
     40      */
     41     private int compare( AnyType item, RedBlackNode<AnyType> t )
     42     {
     43         if( t == header )
     44             return 1;
     45         else
     46             return item.compareTo( t.element );    
     47     }
     48     
     49     /**
     50      * Insert into the tree.
     51      * @param item the item to insert.
     52      */
     53     public void insert( AnyType item )
     54     {
     55         current = parent = grand = header;
     56         nullNode.element = item;
     57 
     58         while( compare( item, current ) != 0 )
     59         {
     60             great = grand; grand = parent; parent = current;
     61             current = compare( item, current ) < 0 ?
     62                          current.left : current.right;
     63 
     64                 // Check if two red children; fix if so
     65             if( current.left.color == RED && current.right.color == RED )
     66                  handleReorient( item );
     67         }
     68 
     69             // Insertion fails if already present
     70         if( current != nullNode )
     71             return;
     72         current = new RedBlackNode<>( item, nullNode, nullNode );
     73 
     74             // Attach to parent
     75         if( compare( item, parent ) < 0 )
     76             parent.left = current;
     77         else
     78             parent.right = current;
     79         handleReorient( item );
     80     }
     81 
     82     /**
     83      * Remove from the tree.
     84      * @param x the item to remove.
     85      * @throws UnsupportedOperationException if called.
     86      */
     87     public void remove( AnyType x )
     88     {
     89         throw new UnsupportedOperationException( );
     90     }
     91 
     92     /**
     93      * Find the smallest item  the tree.
     94      * @return the smallest item or throw UnderflowExcepton if empty.
     95      */
     96     public AnyType findMin( )
     97     {
     98         if( isEmpty( ) )
     99             throw new UnderflowException( );
    100 
    101         RedBlackNode<AnyType> itr = header.right;
    102 
    103         while( itr.left != nullNode )
    104             itr = itr.left;
    105 
    106         return itr.element;
    107     }
    108 
    109     /**
    110      * Find the largest item in the tree.
    111      * @return the largest item or throw UnderflowExcepton if empty.
    112      */
    113     public AnyType findMax( )
    114     {
    115         if( isEmpty( ) )
    116             throw new UnderflowException( );
    117 
    118         RedBlackNode<AnyType> itr = header.right;
    119 
    120         while( itr.right != nullNode )
    121             itr = itr.right;
    122 
    123         return itr.element;
    124     }
    125 
    126     /**
    127      * Find an item in the tree.
    128      * @param x the item to search for.
    129      * @return true if x is found; otherwise false.
    130      */
    131     public boolean contains( AnyType x )
    132     {
    133         nullNode.element = x;
    134         current = header.right;
    135 
    136         for( ; ; )
    137         {
    138             if( x.compareTo( current.element ) < 0 )
    139                 current = current.left;
    140             else if( x.compareTo( current.element ) > 0 ) 
    141                 current = current.right;
    142             else if( current != nullNode )
    143                 return true;
    144             else
    145                 return false;
    146         }
    147     }
    148 
    149     /**
    150      * Make the tree logically empty.
    151      */
    152     public void makeEmpty( )
    153     {
    154         header.right = nullNode;
    155     }
    156 
    157     /**
    158      * Print the tree contents in sorted order.
    159      */
    160     public void printTree( )
    161     {
    162         if( isEmpty( ) )
    163             System.out.println( "Empty tree" );
    164         else
    165             printTree( header.right );
    166     }
    167     
    168     /**
    169      * Internal method to print a subtree in sorted order.
    170      * @param t the node that roots the subtree.
    171      */
    172     private void printTree( RedBlackNode<AnyType> t )
    173     {
    174         if( t != nullNode )
    175         {
    176             printTree( t.left );
    177             System.out.println( t.element );
    178             printTree( t.right );
    179         }
    180     }
    181      
    182     /**
    183      * Test if the tree is logically empty.
    184      * @return true if empty, false otherwise.
    185      */
    186     public boolean isEmpty( )
    187     {
    188         return header.right == nullNode;
    189     }
    190 
    191     /**
    192      * Internal routine that is called during an insertion
    193      * if a node has two red children. Performs flip and rotations.
    194      * @param item the item being inserted.
    195      */
    196     private void handleReorient( AnyType item )
    197     {
    198             // Do the color flip
    199         current.color = RED;
    200         current.left.color = BLACK;
    201         current.right.color = BLACK;
    202 
    203         if( parent.color == RED )   // Have to rotate
    204         {
    205             grand.color = RED;
    206             if( ( compare( item, grand ) < 0 ) !=
    207                 ( compare( item, parent ) < 0 ) )
    208                 parent = rotate( item, grand );  // Start dbl rotate
    209             current = rotate( item, great );
    210             current.color = BLACK;
    211         }
    212         header.right.color = BLACK; // Make root black
    213     }
    214 
    215     /**
    216      * Internal routine that performs a single or double rotation.
    217      * Because the result is attached to the parent, there are four cases.
    218      * Called by handleReorient.
    219      * @param item the item in handleReorient.
    220      * @param parent the parent of the root of the rotated subtree.
    221      * @return the root of the rotated subtree.
    222      */
    223     private RedBlackNode<AnyType> rotate( AnyType item, RedBlackNode<AnyType> parent )
    224     {
    225         if( compare( item, parent ) < 0 )
    226             return parent.left = compare( item, parent.left ) < 0 ?
    227                 rotateWithLeftChild( parent.left )  :  // LL
    228                 rotateWithRightChild( parent.left ) ;  // LR
    229         else
    230             return parent.right = compare( item, parent.right ) < 0 ?
    231                 rotateWithLeftChild( parent.right ) :  // RL
    232                 rotateWithRightChild( parent.right );  // RR
    233     }
    234 
    235     /**
    236      * Rotate binary tree node with left child.
    237      */
    238     private RedBlackNode<AnyType> rotateWithLeftChild( RedBlackNode<AnyType> k2 )
    239     {
    240         RedBlackNode<AnyType> k1 = k2.left;
    241         k2.left = k1.right;
    242         k1.right = k2;
    243         return k1;
    244     }
    245 
    246     /**
    247      * Rotate binary tree node with right child.
    248      */
    249     private RedBlackNode<AnyType> rotateWithRightChild( RedBlackNode<AnyType> k1 )
    250     {
    251         RedBlackNode<AnyType> k2 = k1.right;
    252         k1.right = k2.left;
    253         k2.left = k1;
    254         return k2;
    255     }
    256 
    257     private static class RedBlackNode<AnyType>
    258     {
    259             // Constructors
    260         RedBlackNode( AnyType theElement )
    261         {
    262             this( theElement, null, null );
    263         }
    264 
    265         RedBlackNode( AnyType theElement, RedBlackNode<AnyType> lt, RedBlackNode<AnyType> rt )
    266         {
    267             element  = theElement;
    268             left     = lt;
    269             right    = rt;
    270             color    = RedBlackTree.BLACK;
    271         }
    272 
    273         AnyType               element;    // The data in the node
    274         RedBlackNode<AnyType> left;       // Left child
    275         RedBlackNode<AnyType> right;      // Right child
    276         int                   color;      // Color
    277     }
    278     
    279     private RedBlackNode<AnyType> header;
    280     private RedBlackNode<AnyType> nullNode;
    281 
    282     private static final int BLACK = 1;    // BLACK must be 1
    283     private static final int RED   = 0;
    284 
    285         // Used in insert routine and its helpers
    286     private RedBlackNode<AnyType> current;
    287     private RedBlackNode<AnyType> parent;
    288     private RedBlackNode<AnyType> grand;
    289     private RedBlackNode<AnyType> great;
    290 
    291 
    292         // Test program
    293     public static void main( String [ ] args )
    294     {
    295         RedBlackTree<Integer> t = new RedBlackTree<>( );
    296         final int NUMS = 400000;
    297         final int GAP  =  35461;
    298 
    299         System.out.println( "Checking... (no more output means success)" );
    300 
    301         for( int i = GAP; i != 0; i = ( i + GAP ) % NUMS )
    302             t.insert( i );
    303 
    304         if( t.findMin( ) != 1 || t.findMax( ) != NUMS - 1 )
    305             System.out.println( "FindMin or FindMax error!" );
    306 
    307         for( int i = 1; i < NUMS; i++ )
    308              if( !t.contains( i ) )
    309                  System.out.println( "Find error1!" );
    310     }
    311 }

    Treap树

      1 // Treap class
      2 //
      3 // CONSTRUCTION: with no initializer
      4 //
      5 // ******************PUBLIC OPERATIONS*********************
      6 // void insert( x )       --> Insert x
      7 // void remove( x )       --> Remove x
      8 // boolean contains( x )  --> Return true if x is found
      9 // Comparable findMin( )  --> Return smallest item
     10 // Comparable findMax( )  --> Return largest item
     11 // boolean isEmpty( )     --> Return true if empty; else false
     12 // void makeEmpty( )      --> Remove all items
     13 // void printTree( )      --> Print tree in sorted order
     14 // ******************ERRORS********************************
     15 // Throws UnderflowException as appropriate
     16 
     17 /**
     18  * Implements a treap.
     19  * Note that all "matching" is based on the compareTo method.
     20  * @author Mark Allen Weiss
     21  */
     22 public class Treap<AnyType extends Comparable<? super AnyType>>
     23 {
     24     /**
     25      * Construct the treap.
     26      */
     27     public Treap( )
     28     {
     29         nullNode = new TreapNode<>( null );
     30         nullNode.left = nullNode.right = nullNode;
     31         nullNode.priority = Integer.MAX_VALUE;
     32         root = nullNode;
     33     }
     34 
     35     /**
     36      * Insert into the tree. Does nothing if x is already present.
     37      * @param x the item to insert.
     38      */
     39     public void insert( AnyType x )
     40     {
     41         root = insert( x, root );
     42     }
     43 
     44     /**
     45      * Remove from the tree. Does nothing if x is not found.
     46      * @param x the item to remove.
     47      */
     48     public void remove( AnyType x )
     49     {
     50         root = remove( x, root );
     51     }
     52 
     53     /**
     54      * Find the smallest item in the tree.
     55      * @return the smallest item, or throw UnderflowException if empty.
     56      */
     57     public AnyType findMin( )
     58     {
     59         if( isEmpty( ) )
     60             throw new UnderflowException( );
     61 
     62         TreapNode<AnyType> ptr = root;
     63 
     64         while( ptr.left != nullNode )
     65             ptr = ptr.left;
     66 
     67         return ptr.element;
     68     }
     69 
     70     /**
     71      * Find the largest item in the tree.
     72      * @return the largest item, or throw UnderflowException if empty.
     73      */
     74     public AnyType findMax( )
     75     {
     76         if( isEmpty( ) )
     77             throw new UnderflowException( );
     78 
     79         TreapNode<AnyType> ptr = root;
     80 
     81         while( ptr.right != nullNode )
     82             ptr = ptr.right;
     83 
     84         return ptr.element;
     85     }
     86 
     87     /**
     88      * Find an item in the tree.
     89      * @param x the item to search for.
     90      * @return true if x is found.
     91      */
     92     public boolean contains( AnyType x )
     93     {
     94         TreapNode<AnyType> current = root;
     95         nullNode.element = x;
     96 
     97         for( ; ; )
     98         {
     99             int compareResult = x.compareTo( current.element );
    100             
    101             if( compareResult < 0 )
    102                 current = current.left;
    103             else if( compareResult > 0 ) 
    104                 current = current.right;
    105             else
    106                 return current != nullNode;
    107         }
    108     }
    109 
    110     /**
    111      * Make the tree logically empty.
    112      */
    113     public void makeEmpty( )
    114     {
    115         root = nullNode;
    116     }
    117 
    118     /**
    119      * Test if the tree is logically empty.
    120      * @return true if empty, false otherwise.
    121      */
    122     public boolean isEmpty( )
    123     {
    124         return root == nullNode;
    125     }
    126 
    127     /**
    128      * Print the tree contents in sorted order.
    129      */
    130     public void printTree( )
    131     {
    132         if( isEmpty( ) )
    133             System.out.println( "Empty tree" );
    134         else
    135             printTree( root );
    136     }
    137 
    138     /**
    139      * Internal method to insert into a subtree.
    140      * @param x the item to insert.
    141      * @param t the node that roots the subtree.
    142      * @return the new root of the subtree.
    143      */
    144     private TreapNode<AnyType> insert( AnyType x, TreapNode<AnyType> t )
    145     {
    146         if( t == nullNode )
    147             return new TreapNode<>( x, nullNode, nullNode );
    148             
    149         int compareResult = x.compareTo( t.element );
    150         
    151         if( compareResult < 0 )
    152         {
    153             t.left = insert( x, t.left );
    154             if( t.left.priority < t.priority )
    155                 t = rotateWithLeftChild( t );
    156         }
    157         else if( compareResult > 0  )
    158         {
    159             t.right = insert( x, t.right );
    160             if( t.right.priority < t.priority )
    161                 t = rotateWithRightChild( t );
    162         }
    163         // Otherwise, it's a duplicate; do nothing
    164 
    165         return t;
    166     }
    167 
    168     /**
    169      * Internal method to remove from a subtree.
    170      * @param x the item to remove.
    171      * @param t the node that roots the subtree.
    172      * @return the new root of the subtree.
    173      */
    174     private TreapNode<AnyType> remove( AnyType x, TreapNode<AnyType> t )
    175     {
    176         if( t != nullNode )
    177         {
    178             int compareResult = x.compareTo( t.element );
    179             
    180             if( compareResult < 0 )
    181                 t.left = remove( x, t.left );
    182             else if( compareResult > 0 )
    183                 t.right = remove( x, t.right );
    184             else
    185             {
    186                     // Match found
    187                 if( t.left.priority < t.right.priority )
    188                     t = rotateWithLeftChild( t );
    189                 else
    190                     t = rotateWithRightChild( t );
    191 
    192                 if( t != nullNode )     // Continue on down
    193                     t = remove( x, t );
    194                 else
    195                     t.left = nullNode;  // At a leaf
    196             }
    197         }
    198         return t;
    199     }
    200 
    201     /**
    202      * Internal method to print a subtree in sorted order.
    203      * @param t the node that roots the tree.
    204      */
    205     private void printTree( TreapNode<AnyType> t )
    206     {
    207         if( t != t.left )
    208         {
    209             printTree( t.left );
    210             System.out.println( t.element.toString( ) );
    211             printTree( t.right );
    212         }
    213     }
    214 
    215     /**
    216      * Rotate binary tree node with left child.
    217      */
    218     private TreapNode<AnyType> rotateWithLeftChild( TreapNode<AnyType> k2 )
    219     {
    220         TreapNode<AnyType> k1 = k2.left;
    221         k2.left = k1.right;
    222         k1.right = k2;
    223         return k1;
    224     }
    225 
    226     /**
    227      * Rotate binary tree node with right child.
    228      */
    229     private TreapNode<AnyType> rotateWithRightChild( TreapNode<AnyType> k1 )
    230     {
    231         TreapNode<AnyType> k2 = k1.right;
    232         k1.right = k2.left;
    233         k2.left = k1;
    234         return k2;
    235     }
    236 
    237     private static class TreapNode<AnyType>
    238     {
    239             // Constructors
    240         TreapNode( AnyType theElement )
    241         {
    242             this( theElement, null, null );
    243         }
    244 
    245         TreapNode( AnyType theElement, TreapNode<AnyType> lt, TreapNode<AnyType> rt )
    246         {
    247             element  = theElement;
    248             left     = lt;
    249             right    = rt;
    250             priority = randomObj.randomInt( );
    251         }
    252 
    253             // Friendly data; accessible by other package routines
    254         AnyType            element;      // The data in the node
    255         TreapNode<AnyType> left;         // Left child
    256         TreapNode<AnyType> right;        // Right child
    257         int                priority;     // Priority
    258 
    259         private static Random randomObj = new Random( );
    260     }
    261     
    262     private TreapNode<AnyType> root;
    263     private TreapNode<AnyType> nullNode;
    264  
    265 
    266         // Test program
    267     public static void main( String [ ] args )
    268     {
    269         Treap<Integer> t = new Treap<>( );
    270         final int NUMS = 40000;
    271         final int GAP  =   307;
    272 
    273         System.out.println( "Checking... (no bad output means success)" );
    274 
    275         for( int i = GAP; i != 0; i = ( i + GAP ) % NUMS )
    276             t.insert( i );
    277         System.out.println( "Inserts complete" );
    278 
    279         for( int i = 1; i < NUMS; i+= 2 )
    280             t.remove( i );
    281         System.out.println( "Removes complete" );
    282 
    283         if( NUMS < 40 )
    284             t.printTree( );
    285         if( t.findMin( ) != 2 || t.findMax( ) != NUMS - 2 )
    286             System.out.println( "FindMin or FindMax error!" );
    287 
    288         for( int i = 2; i < NUMS; i+=2 )
    289             if( !t.contains( i ) )
    290                 System.out.println( "Error: find fails for " + i );
    291 
    292         for( int i = 1; i < NUMS; i+=2 )
    293             if( t.contains( i ) )
    294                 System.out.println( "Error: Found deleted item " + i );
    295     }
    296 }

    后缀树

    后缀树的一小部分应用列举如下:

    1. 找到T中最长的重复子串:遍历树,找到带最大字母深度的内部节点,这就表示了最大的LCP。运行时间是O(|T|)。好可以推广到重复了至少k遍的最长子串。

    2. 找到两个字符串T1和T2的最长公共子串:合成一个字符串T1#T2,其中#是不在任一字符串的某个字符。然后为这个字符串建立后缀树,找到最深的那个内部节点,其至少存在一个后缀是在#之前起始的,一个是在#之后起始的。这个完成时间可以做到跟字符串的总长度成正比,并且推广为解决总长度为N的k个字符串问题的O(kN)算法。

    3. 找到模式P出现的次数:假设后缀树增加了记录,简单地沿着内部节点向下的路径,使每个叶子保持跟踪其下面的后缀的个数;第一个是P的前缀的内部节点提供了答案;如果这样的节点不存在,答案是0和1,可以通过检查搜索终止处的后缀得到。这个花费的时间跟模式P的长度成正比,而与|T|的大小无关。

    4. 找到指定长度L > 1的最常见子串:返回那些字母深度至少为L的节点中规模最大的内部节点。所花时间是O(|T|)。 

      1 import java.util.Arrays;
      2 
      3 class SuffixArray
      4 {
      5     
      6     /*
      7      * Create the LCP array from the suffix array
      8      * @param s the input array populated from 0..N-1, with available pos N
      9      * @param sa the already-computed suffix array 0..N-1
     10      * @param LCP the resulting LCP array 0..N-1
     11      */
     12     public static void makeLCPArray( int [ ] s, int [ ] sa, int [ ] LCP )
     13     {
     14         int N = sa.length;
     15         int [ ] rank = new int[ N ];
     16         
     17         s[ N ] = -1;
     18         for( int i = 0; i < N; i++ )
     19             rank[ sa[ i ] ] = i;
     20         
     21         int h = 0;
     22         for( int i = 0; i < N; i++ )
     23             if( rank[ i ] > 0 )
     24             {
     25                 int j = sa[ rank[ i ] - 1 ];
     26                 
     27                 while( s[ i + h ] == s[ j + h ] )
     28                     h++;
     29                 
     30                 LCP[ rank[ i ] ] = h;
     31                 if( h > 0 )
     32                     h--;
     33             }
     34     }
     35     
     36     /*
     37      * Fill in the suffix array information for String str
     38      * @param str the input String
     39      * @param sa existing array to place the suffix array
     40      */
     41     public static void createSuffixArray( String str, int [ ] sa, int [ ] LCP )
     42     {        
     43         int N = str.length( );
     44         
     45         int [ ] s = new int[ N + 3 ];
     46         int [ ] SA = new int[ N + 3 ];
     47         
     48         for( int i = 0; i < N; i++ )
     49             s[ i ] = str.charAt( i );
     50         
     51         makeSuffixArray( s, SA, N, 256 );
     52         
     53         for( int i = 0; i < N; i++ )
     54             sa[ i ] = SA[ i ];
     55         
     56         makeLCPArray( s, sa, LCP );
     57     }
     58     
     59     
     60     // find the suffix array SA of s[0..n-1] in {1..K}^n
     61     // require s[n]=s[n+1]=s[n+2]=0, n>=2
     62     public static void makeSuffixArray( int [ ] s, int [ ] SA, int n, int K )
     63     {
     64         int n0 = ( n + 2 ) / 3;
     65         int n1 = ( n + 1 ) / 3;
     66         int n2 = n / 3;
     67         int t = n0 - n1;  // 1 iff n%3 == 1
     68         int n12 = n1 + n2 + t;
     69 
     70         int [ ] s12  = new int[ n12 + 3 ];
     71         int [ ] SA12 = new int[ n12 + 3 ];
     72         int [ ] s0   = new int[ n0 ];
     73         int [ ] SA0  = new int[ n0 ];
     74         
     75         // generate positions in s for items in s12
     76         // the "+t" adds a dummy mod 1 suffix if n%3 == 1
     77         // at that point, the size of s12 is n12
     78         for( int i = 0, j = 0; i < n + t; i++ )
     79             if( i % 3 != 0 )
     80                 s12[ j++ ] = i;
     81         
     82         int K12 = assignNames( s, s12, SA12, n0, n12, K );
     83   
     84         computeS12( s12, SA12, n12, K12 );
     85         computeS0( s, s0, SA0, SA12, n0, n12, K );
     86         merge( s, s12, SA, SA0, SA12, n, n0, n12, t );
     87     }
     88     
     89     // Assigns the new supercharacter names.
     90     // At end of routine, SA will have indices into s, in sorted order
     91     // and s12 will have new character names
     92     // Returns the number of names assigned; note that if
     93     // this value is the same as n12, then SA is a suffix array for s12.
     94     private static int assignNames( int [ ] s, int [ ] s12, int [ ] SA12,
     95                                    int n0, int n12, int K )
     96     {
     97            // radix sort the new character trios
     98         radixPass( s12 , SA12, s, 2, n12, K );
     99         radixPass( SA12, s12 , s, 1, n12, K );  
    100         radixPass( s12 , SA12, s, 0, n12, K );
    101 
    102           // find lexicographic names of triples
    103         int name = 0;
    104         int c0 = -1, c1 = -1, c2 = -1;
    105       
    106         for( int i = 0; i < n12; i++ )
    107         {
    108             if( s[ SA12[ i ] ] != c0 || s[ SA12[ i ] + 1 ] != c1
    109                                      || s[ SA12[ i ] + 2 ] != c2 )
    110             { 
    111                 name++;
    112                 c0 = s[ SA12[ i ] ];
    113                 c1 = s[ SA12[ i ] + 1 ];
    114                 c2 = s[ SA12[ i ] + 2 ];
    115             }
    116           
    117             if( SA12[ i ] % 3 == 1 )
    118                 s12[ SA12[ i ] / 3 ]      = name;
    119             else
    120                 s12[ SA12[ i ] / 3 + n0 ] = name; 
    121        }
    122       
    123        return name;
    124     }
    125     
    126     
    127     // stably sort in[0..n-1] with indices into s that has keys in 0..K
    128     // into out[0..n-1]; sort is relative to offset into s
    129     // uses counting radix sort
    130     private static void radixPass( int [ ] in, int [ ] out, int [ ] s, int offset,
    131                                   int n, int K ) 
    132     { 
    133         int [ ] count = new int[ K + 2 ];            // counter array
    134         
    135         for( int i = 0; i < n; i++ )
    136             count[ s[ in[ i ] + offset ] + 1 ]++;    // count occurences
    137         
    138         for( int i = 1; i <= K + 1; i++ )            // compute exclusive sums
    139             count[ i ] += count[ i - 1 ];
    140 
    141         for( int i = 0; i < n; i++ )
    142             out[ count[ s[ in[ i ] + offset ] ]++ ] = in[ i ];      // sort
    143     } 
    144     
    145     // stably sort in[0..n-1] with indices into s that has keys in 0..K
    146     // into out[0..n-1]
    147     // uses counting radix sort
    148     private static void radixPass( int [ ] in, int [ ] out, int [ ] s, int n, int K ) 
    149     { 
    150         radixPass( in, out, s, 0, n, K );
    151     }
    152    
    153 
    154     // Compute the suffix array for s12, placing result into SA12
    155     private static void computeS12( int [ ] s12, int [ ] SA12, int n12, int K12 )
    156     {
    157         if( K12 == n12 ) // if unique names, don't need recursion
    158             for( int i = 0; i < n12; i++ )
    159                 SA12[ s12[i] - 1 ] = i; 
    160         else
    161         {
    162             makeSuffixArray( s12, SA12, n12, K12 );
    163             // store unique names in s12 using the suffix array 
    164             for( int i = 0; i < n12; i++ )
    165                 s12[ SA12[ i ] ] = i + 1;
    166         }
    167     }
    168     
    169     private static void computeS0( int [ ] s, int [ ] s0, int [ ] SA0, int [ ] SA12,
    170                                int n0, int n12, int K )
    171     {
    172         for( int i = 0, j = 0; i < n12; i++ )
    173             if( SA12[ i ] < n0 )
    174                 s0[ j++ ] = 3 * SA12[ i ];
    175         
    176         radixPass( s0, SA0, s, n0, K );
    177     }
    178     
    179     
    180     // merge sorted SA0 suffixes and sorted SA12 suffixes
    181     private static void merge( int [ ] s, int [ ] s12,
    182                               int [ ] SA, int [ ] SA0, int [ ] SA12,
    183                               int n, int n0, int n12, int t )
    184     {      
    185         int p = 0, k = 0;
    186         
    187         while( t != n12 && p != n0 )
    188         {
    189             int i = getIndexIntoS( SA12, t, n0 ); // S12
    190             int j = SA0[ p ];                     // S0
    191             
    192             if( suffix12IsSmaller( s, s12, SA12, n0, i, j, t ) )
    193             { 
    194                 SA[ k++ ] = i;
    195                 t++;
    196             }
    197             else
    198             { 
    199                 SA[ k++ ] = j;
    200                 p++;
    201             }  
    202         } 
    203         
    204         while( p < n0 )
    205             SA[ k++ ] = SA0[ p++ ];
    206         while( t < n12 )
    207             SA[ k++ ] = getIndexIntoS( SA12, t++, n0 ); 
    208     }
    209     
    210     private static int getIndexIntoS( int [ ] SA12, int t, int n0 )
    211     {
    212         if( SA12[ t ] < n0 )
    213             return SA12[ t ] * 3 + 1;
    214         else
    215             return ( SA12[ t ] - n0 ) * 3 + 2;
    216     }
    217     
    218     private static boolean leq( int a1, int a2, int b1, int b2 )
    219       { return a1 < b1 || a1 == b1 && a2 <= b2; }
    220     
    221     private static boolean leq( int a1, int a2, int a3, int b1, int b2, int b3 )
    222       { return a1 < b1 || a1 == b1 && leq( a2, a3,b2, b3 ); }
    223     
    224     private static boolean suffix12IsSmaller( int [ ] s, int [ ] s12, int [ ] SA12,
    225                                              int n0, int i, int j, int t )
    226     {
    227         if( SA12[ t ] < n0 )  // s1 vs s0; can break tie after 1 character
    228             return leq( s[ i ], s12[ SA12[ t ] + n0 ],
    229                         s[ j ], s12[ j / 3 ] );
    230         else                  // s2 vs s0; can break tie after 2 characters
    231             return leq( s[ i ], s[ i + 1 ], s12[ SA12[ t ] - n0 + 1 ],
    232                         s[ j ], s[ j + 1 ], s12[ j / 3 + n0 ] );
    233     }
    234 
    235     public static void printV( int [ ]  a, String comment )
    236     {
    237         System.out.print( comment + ":" );
    238         for( int x : a ) 
    239             System.out.print( x + " " );
    240 
    241         System.out.println( );
    242     }
    243 
    244     public static boolean isPermutation( int [ ] SA, int n )
    245     {
    246         boolean [ ] seen = new boolean [ n ];
    247         
    248         for( int i = 0; i < n; i++ )
    249             seen[ i ] = false;
    250         
    251         for( int i = 0; i < n; i++ )
    252             seen[ SA[ i ] ] = true;
    253         
    254         for( int i = 0; i < n; i++ )
    255             if( !seen[ i ] )
    256                 return false;
    257         
    258         return true;
    259     }
    260 
    261     public static boolean sleq( int  [ ] s1, int start1, int [ ] s2, int start2 )
    262     {
    263         for( int i = start1, j = start2; ; i++, j++ )
    264         {
    265             if( s1[ i ] < s2[ j ] )
    266                 return true;
    267             
    268             if( s1[ i ] > s2[ j ] )
    269                 return false;
    270         }
    271     } 
    272 
    273     // Check if SA is a sorted suffix array for s
    274     public static boolean isSorted( int [ ] SA, int [ ] s, int n )
    275     {
    276         for( int i = 0; i < n-1; i++ )
    277             if( !sleq( s, SA[ i ], s, SA[ i + 1 ] ) )
    278                 return false;
    279       
    280         return true;  
    281     }
    282 
    283 
    284 
    285     public static void assert0( boolean cond )
    286     {
    287         if( !cond )
    288             throw new AssertionException( );
    289     }
    290 
    291 
    292     public static void test( String str )
    293     {
    294         int [ ] sufarr = new int[ str.length( ) ];
    295         int [ ] LCP = new int[ str.length( ) ];
    296 
    297         createSuffixArray( str, sufarr, LCP );
    298         
    299         System.out.println( str + ":" );
    300         for( int i = 0; i < str.length( ); i++ )
    301             System.out.println( i + " " + sufarr[ i ] + " " + LCP[ i ] );
    302         System.out.println( );
    303     }
    304 
    305     public static void main( String [ ] args )
    306     {
    307         test( "banana" );
    308         test( "aaaaaa" );
    309     } 
    310 
    311     /*
    312      * Returns the LCP for any two strings
    313      */
    314     public static int computeLCP( String s1, String s2 )
    315     {
    316         int i = 0;
    317         
    318         while( i < s1.length( ) && i < s2.length( ) && s1.charAt( i ) == s2.charAt( i ) )
    319             i++;
    320         
    321         return i;
    322     }
    323 
    324     /*
    325      * Fill in the suffix array and LCP information for String str
    326      * @param str the input String
    327      * @param SA existing array to place the suffix array
    328      * @param LCP existing array to place the LCP information
    329      * Note: Starting in Java 7, this will use quadratic space.
    330      */
    331     public static void createSuffixArraySlow( String str, int [ ] SA, int [ ] LCP )
    332     {
    333         if( SA.length != str.length( ) || LCP.length != str.length( ) )
    334             throw new IllegalArgumentException( );
    335         
    336         int N = str.length( );
    337         
    338         String [ ] suffixes = new String[ N ];
    339         for( int i = 0; i < N; i++ )
    340             suffixes[ i ] = str.substring( i );
    341         
    342         Arrays.sort( suffixes );
    343         
    344         for( int i = 0; i < N; i++ )
    345             SA[ i ] = N - suffixes[ i ].length( );
    346         
    347         LCP[ 0 ] = 0;
    348         for( int i = 1; i < N; i++ )
    349             LCP[ i ] = computeLCP( suffixes[ i - 1 ], suffixes[ i ] );
    350     }
    351 }
    352 
    353 
    354 class AssertionException extends RuntimeException
    355 {
    356 }

    k - d树

     1 /**
     2  * Quick illustration of a two-dimensional tree.
     3  */
     4 public class KdTree<AnyType extends Comparable<? super AnyType>>
     5 {
     6     private static class KdNode<AnyType>
     7     {
     8         AnyType [ ]     data;
     9         KdNode<AnyType> left;
    10         KdNode<AnyType> right;
    11 
    12         KdNode( AnyType item[ ] )
    13         {
    14             data = (AnyType[]) new Comparable[ 2 ];
    15             data[ 0 ] = item[ 0 ];
    16             data[ 1 ] = item[ 1 ];
    17             left = right = null;
    18         }
    19     }
    20 
    21     private KdNode<AnyType> root;
    22 
    23     public KdTree( )
    24     {
    25         root = null;
    26     }
    27 
    28     public void insert( AnyType [ ] x )
    29     {
    30         root = insert( x, root, 0 );
    31     }
    32 
    33     private KdNode<AnyType> insert( AnyType [ ] x, KdNode<AnyType> t, int level )
    34     {
    35         if( t == null )
    36             t = new KdNode<>( x );
    37         else if( x[ level ].compareTo( t.data[ level ] ) < 0 )
    38             t.left = insert( x, t.left, 1 - level );
    39         else
    40             t.right = insert( x, t.right, 1 - level );
    41         return t;
    42     }
    43 
    44     /**
    45      * Print items satisfying
    46      * low[ 0 ] <= x[ 0 ] <= high[ 0 ] and
    47      * low[ 1 ] <= x[ 1 ] <= high[ 1 ].
    48      */
    49     public void printRange( AnyType [ ] low, AnyType [ ] high )
    50     {
    51         printRange( low, high, root, 0 );
    52     }
    53 
    54     private void printRange( AnyType [ ] low, AnyType [ ] high,
    55                              KdNode<AnyType> t, int level )
    56     {
    57         if( t != null )
    58         {
    59             if( low[ 0 ].compareTo( t.data[ 0 ] ) <= 0 &&
    60                         low[ 1 ].compareTo( t.data[ 1 ] ) <= 0 &&
    61                        high[ 0 ].compareTo( t.data[ 0 ] ) >= 0 &&
    62                        high[ 1 ].compareTo( t.data[ 1 ] ) >= 0 )
    63                 System.out.println( "(" + t.data[ 0 ] + ","
    64                                         + t.data[ 1 ] + ")" );
    65 
    66             if( low[ level ].compareTo( t.data[ level ] ) <= 0 )
    67                 printRange( low, high, t.left, 1 - level );
    68             if( high[ level ].compareTo( t.data[ level ] ) >= 0 )
    69                 printRange( low, high, t.right, 1 - level );
    70         }
    71     }
    72 
    73     public static void main( String [ ] args )
    74     {
    75         KdTree<Integer> t = new KdTree<>( );
    76         
    77         System.out.println( "Starting program" );
    78         for( int i = 300; i < 370; i++ )
    79         {
    80             Integer [ ] it = new Integer[ 2 ];
    81             it[ 0 ] = i;
    82             it[ 1 ] = 2500 - i;
    83             t.insert( it );
    84         }
    85 
    86         Integer [ ] low = { 70, 2186 };
    87         Integer [ ] high = { 1200, 2200 };
    88 
    89         t.printRange( low, high );
    90     }
    91 }

    配对堆

      1 import java.util.ArrayList;
      2 
      3 // PairingHeap class
      4 //
      5 // CONSTRUCTION: with no initializer
      6 //
      7 // ******************PUBLIC OPERATIONS*********************
      8 // Position insert( x )   --> Insert x, return position
      9 // Comparable deleteMin( )--> Return and remove smallest item
     10 // Comparable findMin( )  --> Return smallest item
     11 // boolean isEmpty( )     --> Return true if empty; else false
     12 // int size( )            --> Return size of priority queue
     13 // void makeEmpty( )      --> Remove all items
     14 // void decreaseKey( Position p, newVal )
     15 //                        --> Decrease value in node p
     16 // ******************ERRORS********************************
     17 // Exceptions thrown for various operations
     18 
     19 /**
     20  * Implements a pairing heap.
     21  * Supports a decreaseKey operation.
     22  * Note that all "matching" is based on the compareTo method.
     23  * @author Mark Allen Weiss
     24  * @see PriorityQueue.Position
     25  */
     26 public class PairingHeap<AnyType extends Comparable<? super AnyType>>
     27 {    
     28     /**
     29      * The Position interface represents a type that can
     30      * be used for the decreaseKey operation.
     31      */
     32     public interface Position<AnyType>
     33     {
     34         /**
     35          * Returns the value stored at this position.
     36          * @return the value stored at this position.
     37          */
     38         AnyType getValue( );
     39     }
     40     
     41     /**
     42      * Construct the pairing heap.
     43      */
     44     public PairingHeap( )
     45     {
     46         root = null;
     47         theSize = 0;
     48     }
     49 
     50     /**
     51      * Insert into the priority queue, and return a Position
     52      * that can be used by decreaseKey.
     53      * Duplicates are allowed.
     54      * @param x the item to insert.
     55      * @return the node containing the newly inserted item.
     56      */
     57     public Position<AnyType> insert( AnyType x )
     58     {
     59         PairNode<AnyType> newNode = new PairNode<>( x );
     60 
     61         if( root == null )
     62             root = newNode;
     63         else
     64             root = compareAndLink( root, newNode );
     65             
     66         theSize++;
     67         return newNode;
     68     }
     69 
     70     /**
     71      * Find the smallest item in the priority queue.
     72      * @return the smallest item.
     73      * @throws UnderflowException if pairing heap is empty.
     74      */
     75     public AnyType findMin( )
     76     {
     77         if( isEmpty( ) )
     78             throw new UnderflowException( );
     79         return root.element;
     80     }
     81 
     82     /**
     83      * Remove the smallest item from the priority queue.
     84      * @return the smallest item.
     85      * @throws UnderflowException if pairing heap is empty.
     86      */
     87     public AnyType deleteMin( )
     88     {
     89         if( isEmpty( ) )
     90             throw new UnderflowException( );
     91 
     92         AnyType x = findMin( );
     93         root.element = null; // null it out in case used in decreaseKey
     94         if( root.leftChild == null )
     95             root = null;
     96         else
     97             root = combineSiblings( root.leftChild );
     98 
     99         theSize--;
    100         return x;
    101     }
    102 
    103     /**
    104      * Change the value of the item stored in the pairing heap.
    105      * @param pos any Position returned by insert.
    106      * @param newVal the new value, which must be smaller
    107      *    than the currently stored value.
    108      * @throws IllegalArgumentException if pos is null.
    109      * @throws IllegalArgumentException if new value is larger than old.
    110      */
    111     public void decreaseKey( Position<AnyType> pos, AnyType newVal )
    112     {
    113         if( pos == null )
    114             throw new IllegalArgumentException( "null Position passed to decreaseKey" );
    115 
    116         PairNode<AnyType> p = (PairNode<AnyType>) pos;
    117         
    118         if( p.element == null )
    119             throw new IllegalArgumentException( "pos already deleted" );
    120         if( p.element.compareTo( newVal ) < 0 )
    121             throw new IllegalArgumentException( "newVal/oldval: " + newVal + " /" + p.element );
    122         p.element = newVal;
    123         if( p != root )
    124         {
    125             if( p.nextSibling != null )
    126                 p.nextSibling.prev = p.prev;
    127             if( p.prev.leftChild == p )
    128                 p.prev.leftChild = p.nextSibling;
    129             else
    130                 p.prev.nextSibling = p.nextSibling;
    131 
    132             p.nextSibling = null;
    133             root = compareAndLink( root, p );
    134         }
    135     }
    136 
    137     /**
    138      * Test if the priority queue is logically empty.
    139      * @return true if empty, false otherwise.
    140      */
    141     public boolean isEmpty( )
    142     {
    143         return root == null;
    144     }
    145 
    146     /**
    147      * Returns number of items stored in the priority queue.
    148      * @return size of the priority queue.
    149      */
    150     public int size( )
    151     {
    152         return theSize;
    153     }
    154 
    155     /**
    156      * Make the priority queue logically empty.
    157      */
    158     public void makeEmpty( )
    159     {
    160         root = null;
    161         theSize = 0;
    162     }
    163     
    164     /**
    165      * Private static class for use with PairingHeap.
    166      */
    167     private static class PairNode<AnyType> implements Position<AnyType> 
    168     {
    169         /**
    170          * Construct the PairNode.
    171          * @param theElement the value stored in the node.
    172          */
    173         public PairNode( AnyType theElement )
    174         {
    175             element     = theElement;
    176             leftChild   = null;
    177             nextSibling = null;
    178             prev        = null;
    179         }
    180 
    181         /**
    182          * Returns the value stored at this position.
    183          * @return the value stored at this position.
    184          */
    185         public AnyType getValue( )
    186         {
    187             return element;
    188         }
    189         
    190             // Friendly data; accessible by other package routines
    191         public AnyType    element;
    192         public PairNode<AnyType>   leftChild;
    193         public PairNode<AnyType>   nextSibling;
    194         public PairNode<AnyType>   prev;
    195     }
    196 
    197     private PairNode<AnyType> root;
    198     private int theSize;
    199 
    200     /**
    201      * Internal method that is the basic operation to maintain order.
    202      * Links first and second together to satisfy heap order.
    203      * @param first root of tree 1, which may not be null.
    204      *    first.nextSibling MUST be null on entry.
    205      * @param second root of tree 2, which may be null.
    206      * @return result of the tree merge.
    207      */
    208     private PairNode<AnyType> compareAndLink( PairNode<AnyType> first, PairNode<AnyType> second )
    209     {
    210         if( second == null )
    211             return first;
    212 
    213         if( second.element.compareTo( first.element ) < 0 )
    214         {
    215             // Attach first as leftmost child of second
    216             second.prev = first.prev;
    217             first.prev = second;
    218             first.nextSibling = second.leftChild;
    219             if( first.nextSibling != null )
    220                 first.nextSibling.prev = first;
    221             second.leftChild = first;
    222             return second;
    223         }
    224         else
    225         {
    226             // Attach second as leftmost child of first
    227             second.prev = first;
    228             first.nextSibling = second.nextSibling;
    229             if( first.nextSibling != null )
    230                 first.nextSibling.prev = first;
    231             second.nextSibling = first.leftChild;
    232             if( second.nextSibling != null )
    233                 second.nextSibling.prev = second;
    234             first.leftChild = second;
    235             return first;
    236         }
    237     }
    238 
    239     private PairNode<AnyType> [ ] doubleIfFull( PairNode<AnyType> [ ] array, int index )
    240     {
    241         if( index == array.length )
    242         {
    243             PairNode<AnyType> [ ] oldArray = array;
    244 
    245             array = new PairNode[ index * 2 ];
    246             for( int i = 0; i < index; i++ )
    247                 array[ i ] = oldArray[ i ];
    248         }
    249         return array;
    250     }
    251    
    252         // The tree array for combineSiblings
    253     private PairNode<AnyType> [ ] treeArray = new PairNode[ 5 ];
    254 
    255     /**
    256      * Internal method that implements two-pass merging.
    257      * @param firstSibling the root of the conglomerate;
    258      *     assumed not null.
    259      */
    260     private PairNode<AnyType> combineSiblings( PairNode<AnyType> firstSibling )
    261     {
    262         if( firstSibling.nextSibling == null )
    263             return firstSibling;
    264 
    265             // Store the subtrees in an array
    266         int numSiblings = 0;
    267         for( ; firstSibling != null; numSiblings++ )
    268         {
    269             treeArray = doubleIfFull( treeArray, numSiblings );
    270             treeArray[ numSiblings ] = firstSibling;
    271             firstSibling.prev.nextSibling = null;  // break links
    272             firstSibling = firstSibling.nextSibling;
    273         }
    274         treeArray = doubleIfFull( treeArray, numSiblings );
    275         treeArray[ numSiblings ] = null;
    276 
    277             // Combine subtrees two at a time, going left to right
    278         int i = 0;
    279         for( ; i + 1 < numSiblings; i += 2 )
    280             treeArray[ i ] = compareAndLink( treeArray[ i ], treeArray[ i + 1 ] );
    281 
    282             // j has the result of last compareAndLink.
    283             // If an odd number of trees, get the last one.
    284         int j = i - 2;
    285         if( j == numSiblings - 3 )
    286             treeArray[ j ] = compareAndLink( treeArray[ j ], treeArray[ j + 2 ] );
    287 
    288             // Now go right to left, merging last tree with
    289             // next to last. The result becomes the new last.
    290         for( ; j >= 2; j -= 2 )
    291             treeArray[ j - 2 ] = compareAndLink( treeArray[ j - 2 ], treeArray[ j ] );
    292 
    293         return (PairNode<AnyType>) treeArray[ 0 ];
    294     }
    295 
    296         // Test program
    297     public static void main( String [ ] args )
    298     {
    299         PairingHeap<Integer> h = new PairingHeap<>( );
    300         int numItems = 10000;
    301         int i = 37;
    302         int j;
    303 
    304         System.out.println( "Checking; no bad output is good" );
    305         for( i = 37; i != 0; i = ( i + 37 ) % numItems )
    306            h.insert( i );
    307         for( i = 1; i < numItems; i++ )
    308             if( h.deleteMin( ) != i )
    309                 System.out.println( "Oops! " + i );
    310 
    311         ArrayList<PairingHeap.Position<Integer>> p = new ArrayList<>( );
    312         for( i = 0; i < numItems; i++ )
    313                 p.add( null );
    314         
    315         for( i = 0, j = numItems / 2; i < numItems; i++, j =(j+71)%numItems )
    316             p.set( j, h.insert( j + numItems ) );
    317         for( i = 0, j = numItems / 2; i < numItems; i++, j =(j+53)%numItems )
    318             h.decreaseKey( p.get( j ), p.get( j ).getValue( ) - numItems );
    319         i = -1;
    320         while( !h.isEmpty( ) )
    321             if( h.deleteMin( ) != ++i )
    322                 System.out.println( "Oops! " + i + " " );
    323         System.out.println( "Check completed" );
    324     }
    325 }
  • 相关阅读:
    Spring MVC 迁移项目搭建运行
    linux 安装 nginx
    linux 安装 redis
    linux 安装 jdk
    存储过程之游标插入数据
    存储过程之基础语法
    AES加密解密,自定义加密规则记录
    idea破解记录
    Mysql-explain之Using temporary和Using filesort解决方案
    C#多线程学习笔记(朝夕eleven) Task启动方式、Task阻塞、Task.Delay()、多线程异常处理、任务取消、多线程的临时变量、共享数据的lock、Task返回值
  • 原文地址:https://www.cnblogs.com/tjj-love-world/p/10628309.html
Copyright © 2011-2022 走看看