Ref: Carrano ch.16-18
Searching Algorithms
sequential: one-at-a time, O(n)
binary: halving sorted structures, O(log n)
Sequential Searching Of A List
for classes with indexed getEntry...
...searching a for match to value :
int i = 0; // so that "i" survives the loop
for (; i < size; i++)
if (value.equals(a.getEntry(i)))
break;
if (i == size)
not found -- unsuccessful search
else
found at index "i"
return index of -1 to indicate unsuccess
for singly-linked list, this is O(n2 )
for doubly-linked list w/current, this is...
Sequential Searching Of An Ordered List
if list implements "MySortedList", unsuccessful searches
can be made faster by quitting when
greater value is found in ordered sequence
for (; i < size; i++)
{
if (value.equals(a.getEntry(i)))
break;
if (value.compareTo(a.getEntry(i)) < 0)
i = size - 1; // forces loop to quit
}
...
in a "MySortedList" version of the function
can have 2 versions: "overloading"
Binary Searching Of An Ordered List
if list implements "MySortedList", can use "bisection"
requires ordered array
not for unordered lists
not for linked lists
using the over-under bisection method
using recursion: easier solution
here's the algorithm:
Look in array of "n" values:
Look at the middle value.
If it matches, SUCCESS!
If there is only one value, FAIL!
If middle value is greater,
look in first n/2 values
If middle value is less,
look in last n/2 values
click here for code sample
solution is "tail-recursive", so can be iterative
Looking Up Database Records
generic list classes store any data type
to be sortable, the data type must implement "Comparable"
built-in Java data types implement "Comparable"
but what about programmer-defined data types, like in lab 1?
Comparing Two Objects
result: equal, lesser, or greater
numeric
alphabetical or alphanumeric
lexicographical
tie-breakers for multi-valued objects (e.g. records)
as a static method: int compare(T a, T b)
return 0 if equal
return a NEGATIVE value if a is LESS THAN b
return a POSITIVE value if a is GREATER THAN b
as an instance method: int compare(T value)
return 0 if equal
return a NEGATIVE value if host object is LESS THAN value
return a POSITIVE value if host object is GREATER THAN value
Implementing The Comparable Interface
one solution:
public class Animal implements Comparable<Animal>
{
private String name;
private Integer age;
private Double weight;
... more data members, accessors, and mutators
public int compareTo(Animal anotherAnimal)
{
int compare = name.compareToIgnoreCase(anotherAnimal.name);
if (compare == 0) // go to 1st tie-breaker
{
compare = age.compareTo(anotherAnimal.age);
if (compare == 0) // go to 2nd tie-breaker
{
compare = weight.compareTo(anotherAnimal.weight);
} }
return compare;
}
}
still, indexing is required for retrieval
Implementing A "Sorted" Interface
a "list" that maintains values in order
redefining the indexed add operation
no longer supported -- added value's
lexicographical value determines its index
private method: getIndex (see topic 5)
determines index for indexed operations...
...to maintain sorted order
in addition to the indexed remove operation
match a value , not an index
public boolean remove(T value)
redefining non-indexed add operation
no longer adding at end
determine index for adding, to maintain order
unsupported operations:
public boolean add(int index, T value)
public boolean replace(int index, T value)
MySortedArrayList and MySortedLinkedList
Implementing A "Dictionary" Interface
another solution: specify which
data member to use for comparing
no tie breakers, though
no indexing -- similar to sorted lists
replace index with key
now two generic references:
K key
V value (replaces T value )
public interface MyDictionary<K, V>
modified MyList :
newly formulated methods without index :
public boolean add(K key , V value);
public V remove(K key );
public V getValue(K key );
public boolean contains(K key );
iteration support: bases on V and K
total iteration support:
public Iterator<V > iterator(); works with for-each
public Iterator<K > keyIterator ();
An Array-based Dictionary
no duplicates allowed -- validate on this instead of index
introducing a (Serializable) "node"
private class Node<K, V> ...
{
private K key;
private V value;
}
Store an array of nodes:
private Node<K, V>[] data; // data storage
private method to convert a value into its index:
private int locateIndex(K key)
{
int index;
for (index = 0; index < nValues; index++)
if (data[index].equals(key))
break;
return index; // may equal nValues
}
Declaration:
MyDictionary<Integer, String> a =
new MyArrayDictionary<Integer, String>();
A Linked Dictionary
no duplicates allowed -- validate on this instead of index
expanding the "node" class:
private class Node<K, V> ...
{
private K key;
private V value;
... link(s)
}
Algorithm Efficiency Issues
locateIndex is O(n)
so operations that use it are no better than O(n)
retrievals are expensive
except for full iteration
improved approaches would have to achieve
O(1) or O(log n) to convert key to index
possible solution: hashing (topic 7)
another possible solution: binary trees (topic 9)