| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| */ |
| package org.apache.directory.server.core.avltree; |
| |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Comparator; |
| import java.util.List; |
| |
| |
| /** |
| * A data structure simulating a tree (ie, a sorted list of elements) using an array. |
| * |
| * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> |
| */ |
| public class ArrayTree<K> |
| { |
| /** The Comparator used for comparing the keys */ |
| private Comparator<K> comparator; |
| |
| /** The array containing the data */ |
| private K[] array; |
| |
| /** The current number of elements in the array. May be lower than the array size */ |
| private int size; |
| |
| /** The extend size to use when increasing the array size */ |
| private static final int INCREMENT = 16; |
| |
| |
| /** |
| * Creates a new instance of AVLTree. |
| * |
| * @param comparator the comparator to be used for comparing keys |
| */ |
| public ArrayTree( Comparator<K> comparator ) |
| { |
| this.comparator = comparator; |
| array = ( K[] ) new Object[INCREMENT]; |
| size = 0; |
| } |
| |
| |
| /** |
| * Creates a new instance of AVLTree. |
| * |
| * @param comparator the comparator to be used for comparing keys |
| */ |
| public ArrayTree( Comparator<K> comparator, K[] array ) |
| { |
| this.comparator = comparator; |
| |
| if ( array != null ) |
| { |
| size = array.length; |
| int arraySize = size; |
| |
| if ( size % INCREMENT != 0 ) |
| { |
| arraySize += INCREMENT - size % INCREMENT; |
| } |
| |
| this.array = ( K[] ) new Object[arraySize]; |
| System.arraycopy( array, 0, this.array, 0, size ); |
| } |
| } |
| |
| |
| /** |
| * @return the comparator associated with this tree |
| */ |
| public Comparator<K> getComparator() |
| { |
| return comparator; |
| } |
| |
| |
| /** |
| * Inserts a key. Null value insertion is not allowed. |
| * |
| * @param key the item to be inserted, should not be null |
| * @return the replaced key if it already exists |
| * Note: Ignores if the given key already exists. |
| */ |
| public K insert( K key ) |
| { |
| if ( key == null ) |
| { |
| // We don't allow null values in the tree |
| return null; |
| } |
| |
| // Check if the key already exists, and if so, return the |
| // existing one |
| K existing = find( key ); |
| |
| if ( existing != null ) |
| { |
| return existing; |
| } |
| |
| if ( size == array.length ) |
| { |
| // The array is full, let's extend it |
| K[] newArray = ( K[] ) new Object[size + INCREMENT]; |
| |
| System.arraycopy( array, 0, newArray, 0, size ); |
| array = newArray; |
| } |
| |
| // Currently, just add the element at the end of the array |
| // and sort the array. We could be more efficient by inserting the |
| // element at the right position by splitting the array in two |
| // parts and copying the right part one slot on the right. |
| array[size++] = key; |
| Arrays.sort( array, 0, size, comparator ); |
| |
| return null; |
| } |
| |
| |
| /**q< |
| * Reduce the array size if neede |
| */ |
| private void reduceArray() |
| { |
| // We will reduce the array size when the number of elements |
| // in it is leaving twice the number of INCREMENT empty slots. |
| // We then remove INCREMENT slots |
| if ( ( array.length - size ) > ( INCREMENT << 1 ) ) |
| { |
| K[] newArray = ( K[] ) new Object[array.length - INCREMENT]; |
| System.arraycopy( array, 0, newArray, 0, array.length ); |
| } |
| } |
| |
| |
| /** |
| * Removes a key present in the tree |
| * |
| * @param key the value to be removed |
| * @return the removed key, if any, or null if the key does not exist |
| */ |
| public K remove( K key ) |
| { |
| // Search for the key position in the tree |
| int pos = getPosition( key ); |
| |
| if ( pos != -1 ) |
| { |
| // Found... |
| if ( pos != size - 1 ) |
| { |
| // If the element is not the last one, we have to |
| // move the end of the array one step to the left |
| System.arraycopy( array, pos + 1, array, pos, size - pos - 1 ); |
| |
| reduceArray(); |
| } |
| |
| size--; |
| |
| return key; |
| } |
| else |
| { |
| return null; |
| } |
| } |
| |
| |
| /** |
| * Tests if the tree is empty. |
| * |
| * @return true if the tree is empty, false otherwise |
| */ |
| public boolean isEmpty() |
| { |
| return size == 0; |
| } |
| |
| |
| /** |
| * returns the number of nodes present in this tree. |
| * |
| * @return the number of nodes present in this tree |
| */ |
| public int size() |
| { |
| return size; |
| } |
| |
| |
| /** |
| * @return a list of the stored keys in this tree |
| */ |
| public List<K> getKeys() |
| { |
| List<K> list = new ArrayList<K>( size ); |
| |
| for ( int i = 0; i < size; i++ ) |
| { |
| list.add( array[i] ); |
| } |
| |
| return list; |
| } |
| |
| |
| /** |
| * Prints the contents of AVL tree in pretty format |
| */ |
| public void printTree() |
| { |
| if ( isEmpty() ) |
| { |
| System.out.println( "Tree is empty" ); |
| return; |
| } |
| |
| boolean isFirst = false; |
| |
| for ( K key : array ) |
| { |
| if ( isFirst ) |
| { |
| isFirst = false; |
| } |
| else |
| { |
| System.out.print( ", " ); |
| } |
| |
| System.out.println( key ); |
| } |
| } |
| |
| |
| /** |
| * Get the element at a given position |
| * @param position The position in the tree |
| * @return The found key, or null if the position is out of scope |
| * @throws ArrayIndexOutOfBoundsException If the position is not within the array boundaries |
| */ |
| public K get( int position ) throws ArrayIndexOutOfBoundsException |
| { |
| if ( ( position < 0 ) || ( position >= size ) ) |
| { |
| throw new ArrayIndexOutOfBoundsException(); |
| } |
| |
| return array[position]; |
| } |
| |
| |
| /** |
| * Get the first element in the tree. It sets the current position to this |
| * element. |
| * @return The first element of this tree |
| */ |
| public K getFirst() |
| { |
| if ( size != 0 ) |
| { |
| return array[0]; |
| } |
| else |
| { |
| return null; |
| } |
| } |
| |
| |
| /** |
| * Get the last element in the tree. It sets the current position to this |
| * element. |
| * @return The last element in this tree |
| */ |
| public K getLast() |
| { |
| if ( size != 0 ) |
| { |
| return array[size - 1]; |
| } |
| else |
| { |
| return null; |
| } |
| } |
| |
| |
| /** |
| * Finds a key higher than the given key. Sets the current position to this |
| * element. |
| * |
| * @param key the key to find |
| * @return the LinkedAvlNode<K> whose key is greater than the given key ,<br> |
| * null if there is no node with a higher key than the given key. |
| */ |
| public K findGreater( K key ) |
| { |
| if ( key == null ) |
| { |
| return null; |
| } |
| |
| switch ( size ) |
| { |
| case 0: |
| return null; |
| |
| case 1: |
| if ( comparator.compare( array[0], key ) > 0 ) |
| { |
| return array[0]; |
| } |
| else |
| { |
| return null; |
| } |
| |
| case 2: |
| if ( comparator.compare( array[0], key ) > 0 ) |
| { |
| return array[0]; |
| } |
| else if ( comparator.compare( array[1], key ) > 0 ) |
| { |
| return array[1]; |
| } |
| else |
| { |
| return null; |
| } |
| |
| default: |
| // Split the array in two parts, the left part an the right part |
| int current = size >> 1; |
| int start = 0; |
| int end = size - 1; |
| |
| while ( end - start + 1 > 2 ) |
| { |
| int res = comparator.compare( array[current], key ); |
| |
| if ( res == 0 ) |
| { |
| // Current can't be equal to zero at this point |
| return array[current + 1]; |
| } |
| else if ( res < 0 ) |
| { |
| start = current; |
| current = ( current + end + 1 ) >> 1; |
| } |
| else |
| { |
| end = current; |
| current = ( current + start + 1 ) >> 1; |
| } |
| } |
| |
| switch ( end - start + 1 ) |
| { |
| case 1: |
| int res = comparator.compare( array[start], key ); |
| |
| if ( res <= 0 ) |
| { |
| if ( start == size ) |
| { |
| return null; |
| } |
| else |
| { |
| return array[start + 1]; |
| } |
| } |
| |
| return array[start]; |
| |
| case 2: |
| res = comparator.compare( array[start], key ); |
| |
| if ( res <= 0 ) |
| { |
| res = comparator.compare( array[start + 1], key ); |
| |
| if ( res <= 0 ) |
| { |
| if ( start == size - 2 ) |
| { |
| return null; |
| } |
| |
| return array[start + 2]; |
| } |
| |
| return array[start + 1]; |
| } |
| |
| return array[start]; |
| } |
| } |
| |
| return null; |
| } |
| |
| |
| /** |
| * Finds a key higher than the given key. |
| * |
| * @param key the key |
| * @return the key chich is greater than the given key ,<br> |
| * null if there is no higher key than the given key. |
| */ |
| public K findGreaterOrEqual( K key ) |
| { |
| if ( key == null ) |
| { |
| return null; |
| } |
| |
| switch ( size ) |
| { |
| case 0: |
| return null; |
| |
| case 1: |
| if ( comparator.compare( array[0], key ) >= 0 ) |
| { |
| return array[0]; |
| } |
| else |
| { |
| return null; |
| } |
| |
| case 2: |
| if ( comparator.compare( array[0], key ) >= 0 ) |
| { |
| return array[0]; |
| } |
| else if ( comparator.compare( array[1], key ) >= 0 ) |
| { |
| return array[1]; |
| } |
| else |
| { |
| return null; |
| } |
| |
| default: |
| // Split the array in two parts, the left part an the right part |
| int current = size >> 1; |
| int start = 0; |
| int end = size - 1; |
| |
| while ( end - start + 1 > 2 ) |
| { |
| int res = comparator.compare( array[current], key ); |
| |
| if ( res == 0 ) |
| { |
| return array[current]; |
| } |
| else if ( res < 0 ) |
| { |
| start = current; |
| current = ( current + end + 1 ) >> 1; |
| } |
| else |
| { |
| end = current; |
| current = ( current + start + 1 ) >> 1; |
| } |
| } |
| |
| switch ( end - start + 1 ) |
| { |
| case 1: |
| int res = comparator.compare( array[start], key ); |
| |
| if ( res >= 0 ) |
| { |
| return array[start]; |
| } |
| else |
| { |
| if ( start == size - 1 ) |
| { |
| return null; |
| } |
| else |
| { |
| return array[start + 1]; |
| } |
| } |
| |
| case 2: |
| res = comparator.compare( array[start], key ); |
| |
| if ( res < 0 ) |
| { |
| res = comparator.compare( array[start + 1], key ); |
| |
| if ( res < 0 ) |
| { |
| if ( start == size - 2 ) |
| { |
| return null; |
| } |
| |
| return array[start + 2]; |
| } |
| |
| return array[start + 1]; |
| } |
| |
| return array[start]; |
| } |
| } |
| |
| return null; |
| } |
| |
| |
| /** |
| * Finds a key which is lower than the given key. |
| * |
| * @param key the key |
| * @return the key lower than the given key ,<br> |
| * null if there is no node with a lower key than the given key. |
| */ |
| public K findLess( K key ) |
| { |
| if ( key == null ) |
| { |
| return null; |
| } |
| |
| switch ( size ) |
| { |
| case 0: |
| return null; |
| |
| case 1: |
| if ( comparator.compare( array[0], key ) >= 0 ) |
| { |
| return null; |
| } |
| else |
| { |
| return array[0]; |
| } |
| |
| case 2: |
| if ( comparator.compare( array[0], key ) >= 0 ) |
| { |
| return null; |
| } |
| else if ( comparator.compare( array[1], key ) >= 0 ) |
| { |
| return array[0]; |
| } |
| else |
| { |
| return array[1]; |
| } |
| |
| default: |
| // Split the array in two parts, the left part an the right part |
| int current = size >> 1; |
| int start = 0; |
| int end = size - 1; |
| |
| while ( end - start + 1 > 2 ) |
| { |
| int res = comparator.compare( array[current], key ); |
| |
| if ( res == 0 ) |
| { |
| // Current can't be equal to zero at this point |
| return array[current - 1]; |
| } |
| else if ( res < 0 ) |
| { |
| start = current; |
| current = ( current + end + 1 ) >> 1; |
| } |
| else |
| { |
| end = current; |
| current = ( current + start + 1 ) >> 1; |
| } |
| } |
| |
| switch ( end - start + 1 ) |
| { |
| case 1: |
| // Three cases : |
| // o The value is equal to the current position, or below |
| // the current position : |
| // - if the current position is at the beginning |
| // of the array, return null |
| // - otherwise, return the previous position in the array |
| // o The value is above the current position : |
| // - return the current position |
| int res = comparator.compare( array[start], key ); |
| |
| if ( res >= 0 ) |
| { |
| // start can be equal to 0. Check that |
| if ( start == 1 ) |
| { |
| return null; |
| } |
| else |
| { |
| return array[start - 1]; |
| } |
| } |
| else |
| { |
| return array[start]; |
| } |
| |
| case 2: |
| // Four cases : |
| // o the value is equal the current position, or below |
| // the first position : |
| // - if the current position is at the beginning |
| // of the array, return null |
| // - otherwise, return the previous element |
| // o the value is above the first position but below |
| // or equal the second position, return the first position |
| // o otherwise, return the second position |
| res = comparator.compare( array[start], key ); |
| |
| if ( res >= 0 ) |
| { |
| if ( start == 0 ) |
| { |
| return null; |
| } |
| else |
| { |
| return array[start - 1]; |
| } |
| } |
| else if ( comparator.compare( array[start + 1], key ) >= 0 ) |
| { |
| return array[start]; |
| } |
| else |
| { |
| return array[start + 1]; |
| } |
| } |
| } |
| |
| return null; |
| } |
| |
| |
| /** |
| * Finds a key chich is lower than the given key. |
| * |
| * @param key the key |
| * @return the key which is lower than the given key ,<br> |
| * null if there is no node with a lower key than the given key. |
| */ |
| public K findLessOrEqual( K key ) |
| { |
| if ( key == null ) |
| { |
| return null; |
| } |
| |
| switch ( size ) |
| { |
| case 0: |
| return null; |
| |
| case 1: |
| if ( comparator.compare( array[0], key ) <= 0 ) |
| { |
| return array[0]; |
| } |
| else |
| { |
| return null; |
| } |
| |
| case 2: |
| int res = comparator.compare( array[0], key ); |
| |
| if ( res > 0 ) |
| { |
| return null; |
| } |
| else if ( res == 0 ) |
| { |
| return array[0]; |
| } |
| |
| res = comparator.compare( array[1], key ); |
| |
| if ( res == 0 ) |
| { |
| return array[1]; |
| } |
| else if ( comparator.compare( array[1], key ) > 0 ) |
| { |
| return array[0]; |
| } |
| else |
| { |
| return array[1]; |
| } |
| |
| default: |
| // Split the array in two parts, the left part an the right part |
| int current = size >> 1; |
| int start = 0; |
| int end = size - 1; |
| |
| while ( end - start + 1 > 2 ) |
| { |
| res = comparator.compare( array[current], key ); |
| |
| if ( res == 0 ) |
| { |
| return array[current]; |
| } |
| else if ( res < 0 ) |
| { |
| start = current; |
| current = ( current + end + 1 ) >> 1; |
| } |
| else |
| { |
| end = current; |
| current = ( current + start + 1 ) >> 1; |
| } |
| } |
| |
| switch ( end - start + 1 ) |
| { |
| case 1: |
| // Three cases : |
| // o The value is equal to the current position, or below |
| // the current position : |
| // - if the current position is at the beginning |
| // of the array, return null |
| // - otherwise, return the previous position in the array |
| // o The value is above the current position : |
| // - return the current position |
| res = comparator.compare( array[start], key ); |
| |
| if ( res > 0 ) |
| { |
| // start can be equal to 0. Check that |
| if ( start == 1 ) |
| { |
| return null; |
| } |
| else |
| { |
| return array[start - 1]; |
| } |
| } |
| else |
| { |
| return array[start]; |
| } |
| |
| case 2: |
| // Four cases : |
| // o the value is equal the current position, or below |
| // the first position : |
| // - if the current position is at the beginning |
| // of the array, return null |
| // - otherwise, return the previous element |
| // o the value is above the first position but below |
| // or equal the second position, return the first position |
| // o otherwise, return the second position |
| res = comparator.compare( array[start], key ); |
| |
| if ( res > 0 ) |
| { |
| if ( start == 0 ) |
| { |
| return null; |
| } |
| else |
| { |
| return array[start - 1]; |
| } |
| } |
| |
| res = comparator.compare( array[start + 1], key ); |
| |
| if ( res > 0 ) |
| { |
| return array[start]; |
| } |
| else |
| { |
| return array[start + 1]; |
| } |
| } |
| } |
| |
| return null; |
| } |
| |
| |
| /** |
| * Find an element in the array. |
| * |
| * @param key the key to find |
| * @return the found node, or null |
| */ |
| public K find( K key ) |
| { |
| if ( key == null ) |
| { |
| return null; |
| } |
| |
| switch ( size ) |
| { |
| case 0: |
| return null; |
| |
| case 1: |
| if ( comparator.compare( array[0], key ) == 0 ) |
| { |
| return array[0]; |
| } |
| else |
| { |
| return null; |
| } |
| |
| case 2: |
| if ( comparator.compare( array[0], key ) == 0 ) |
| { |
| return array[0]; |
| } |
| else if ( comparator.compare( array[1], key ) == 0 ) |
| { |
| return array[1]; |
| } |
| else |
| { |
| return null; |
| } |
| |
| default: |
| // Split the array in two parts, the left part an the right part |
| int current = size >> 1; |
| int start = 0; |
| int end = size - 1; |
| |
| while ( end - start + 1 > 2 ) |
| { |
| int res = comparator.compare( array[current], key ); |
| |
| if ( res == 0 ) |
| { |
| return array[current]; |
| } |
| else if ( res < 0 ) |
| { |
| start = current; |
| current = ( current + end + 1 ) >> 1; |
| } |
| else |
| { |
| end = current; |
| current = ( current + start + 1 ) >> 1; |
| } |
| } |
| |
| switch ( end - start + 1 ) |
| { |
| case 1: |
| if ( comparator.compare( array[start], key ) == 0 ) |
| { |
| return array[start]; |
| } |
| else |
| { |
| return null; |
| } |
| |
| case 2: |
| if ( comparator.compare( array[start], key ) == 0 ) |
| { |
| return array[start]; |
| } |
| else if ( comparator.compare( array[end], key ) == 0 ) |
| { |
| return array[end]; |
| } |
| else |
| { |
| return null; |
| } |
| } |
| } |
| |
| return null; |
| } |
| |
| |
| /** |
| * Find the element position in the array. |
| * |
| * @param key the key to find |
| * @return the position in the array, or -1 if not found |
| */ |
| public int getPosition( K key ) |
| { |
| if ( key == null ) |
| { |
| return -1; |
| } |
| |
| switch ( size ) |
| { |
| case 0: |
| return -1; |
| |
| case 1: |
| if ( comparator.compare( array[0], key ) == 0 ) |
| { |
| return 0; |
| } |
| else |
| { |
| return -1; |
| } |
| |
| case 2: |
| if ( comparator.compare( array[0], key ) == 0 ) |
| { |
| return 0; |
| } |
| else if ( comparator.compare( array[1], key ) == 0 ) |
| { |
| return 1; |
| } |
| else |
| { |
| return -1; |
| } |
| |
| default: |
| // Split the array in two parts, the left part an the right part |
| int current = size >> 1; |
| int start = 0; |
| int end = size - 1; |
| |
| while ( end - start + 1 > 2 ) |
| { |
| int res = comparator.compare( array[current], key ); |
| |
| if ( res == 0 ) |
| { |
| return current; |
| } |
| else if ( res < 0 ) |
| { |
| start = current; |
| current = ( current + end + 1 ) >> 1; |
| } |
| else |
| { |
| end = current; |
| current = ( current + start + 1 ) >> 1; |
| } |
| } |
| |
| switch ( end - start + 1 ) |
| { |
| case 1: |
| if ( comparator.compare( array[start], key ) == 0 ) |
| { |
| return start; |
| } |
| else |
| { |
| return -1; |
| } |
| |
| case 2: |
| if ( comparator.compare( array[start], key ) == 0 ) |
| { |
| return start; |
| } |
| else if ( comparator.compare( array[end], key ) == 0 ) |
| { |
| return end; |
| } |
| else |
| { |
| return -1; |
| } |
| } |
| } |
| |
| return -1; |
| } |
| |
| |
| /** |
| * Find the element position in the array, or the position of the closest greater element in the array. |
| * |
| * @param key the key to find |
| * @return the position in the array, or -1 if not found |
| */ |
| public int getAfterPosition( K key ) |
| { |
| if ( key == null ) |
| { |
| return -1; |
| } |
| |
| switch ( size ) |
| { |
| case 0: |
| return -1; |
| |
| case 1: |
| if ( comparator.compare( array[0], key ) > 0 ) |
| { |
| return 0; |
| } |
| else |
| { |
| return -1; |
| } |
| |
| case 2: |
| if ( comparator.compare( array[0], key ) > 0 ) |
| { |
| return 0; |
| } |
| |
| if ( comparator.compare( array[1], key ) > 0 ) |
| { |
| return 1; |
| } |
| else |
| { |
| return -1; |
| } |
| |
| default: |
| // Split the array in two parts, the left part an the right part |
| int current = size >> 1; |
| int start = 0; |
| int end = size - 1; |
| |
| while ( end - start + 1 > 2 ) |
| { |
| int res = comparator.compare( array[current], key ); |
| |
| if ( res == 0 ) |
| { |
| if ( current != size - 1 ) |
| { |
| return current + 1; |
| } |
| else |
| { |
| return -1; |
| } |
| } |
| else if ( res < 0 ) |
| { |
| start = current; |
| current = ( current + end + 1 ) >> 1; |
| } |
| else |
| { |
| end = current; |
| current = ( current + start + 1 ) >> 1; |
| } |
| } |
| |
| switch ( end - start + 1 ) |
| { |
| case 1: |
| if ( comparator.compare( array[start], key ) > 0 ) |
| { |
| return start; |
| } |
| else |
| { |
| return -1; |
| } |
| |
| case 2: |
| if ( comparator.compare( array[start], key ) > 0 ) |
| { |
| return start; |
| } |
| |
| if ( comparator.compare( array[end], key ) > 0 ) |
| { |
| return end; |
| } |
| else |
| { |
| return -1; |
| } |
| } |
| } |
| |
| return -1; |
| } |
| |
| |
| /** |
| * Find the element position in the array, or the position of the closest greater element in the array. |
| * |
| * @param key the key to find |
| * @return the position in the array, or -1 if not found |
| */ |
| public int getBeforePosition( K key ) |
| { |
| if ( key == null ) |
| { |
| return -1; |
| } |
| |
| switch ( size ) |
| { |
| case 0: |
| return -1; |
| |
| case 1: |
| if ( comparator.compare( array[0], key ) < 0 ) |
| { |
| return 0; |
| } |
| else |
| { |
| return -1; |
| } |
| |
| case 2: |
| if ( comparator.compare( array[1], key ) < 0 ) |
| { |
| return 1; |
| } |
| |
| if ( comparator.compare( array[0], key ) < 0 ) |
| { |
| return 0; |
| } |
| else |
| { |
| return -1; |
| } |
| |
| default: |
| // Split the array in two parts, the left part an the right part |
| int current = size >> 1; |
| int start = 0; |
| int end = size - 1; |
| |
| while ( end - start + 1 > 2 ) |
| { |
| int res = comparator.compare( array[current], key ); |
| |
| if ( res == 0 ) |
| { |
| if ( current == 0 ) |
| { |
| return -1; |
| } |
| else |
| { |
| return current - 1; |
| } |
| } |
| else if ( res < 0 ) |
| { |
| start = current; |
| current = ( current + end + 1 ) >> 1; |
| } |
| else |
| { |
| end = current; |
| current = ( current + start + 1 ) >> 1; |
| } |
| } |
| |
| switch ( end - start + 1 ) |
| { |
| case 1: |
| if ( comparator.compare( array[start], key ) < 0 ) |
| { |
| return start; |
| } |
| else |
| { |
| return -1; |
| } |
| |
| case 2: |
| if ( comparator.compare( array[end], key ) < 0 ) |
| { |
| return end; |
| } |
| |
| if ( comparator.compare( array[start], key ) < 0 ) |
| { |
| return start; |
| } |
| else |
| { |
| return -1; |
| } |
| } |
| } |
| |
| return -1; |
| } |
| |
| |
| /** |
| * Tells if a key exist in the array. |
| * |
| * @param key The key to look for |
| * @return true if the key exist in the array |
| */ |
| public boolean contains( K key ) |
| { |
| return find( key ) != null; |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public String toString() |
| { |
| if ( isEmpty() ) |
| { |
| return "[]"; |
| } |
| |
| StringBuilder sb = new StringBuilder(); |
| |
| boolean isFirst = true; |
| |
| for ( int i = 0; i < size; i++ ) |
| { |
| K key = array[i]; |
| |
| if ( isFirst ) |
| { |
| isFirst = false; |
| } |
| else |
| { |
| sb.append( ", " ); |
| } |
| |
| sb.append( key ); |
| } |
| |
| return sb.toString(); |
| } |
| } |