CompSci-61B Lecture Topic 6
Searching For Values In Data Structures

Instructor: Prof. Robert Burns

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)


Expanding MyList to be Sortable
public interface MySortedList<T extends Comparable<? super T>> extends MyList<T>
{
  public boolean remove(T value);
}
Methods in a Dictionary Interface
public boolean add(K key, V value); // adds value to dictionary with a unique key, returns true if successful
public V remove(K key); // retrieves value reference to matching key and removes it from the dictionary
public V getValue(K key); // retrieves reference to matching key
public boolean contains(K key); // returns true if key is in dictionary
public Iterator keyIterator(); // return an interator on the keys
public Iterator iterator(); // return an interator on the values (for use with for-each)
public boolean isEmpty(); // true if #of values is zero
public boolean isFull(); // true if #of values equals capacity
public int size(); // return #of values
public void clear(); // remove all values

[ Home | Contact Prof. Burns ]