第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 }

 

posted @ 2019-03-30 17:54  tjjloveworld  阅读(454)  评论(0编辑  收藏  举报