• No results found

lecture-DS-10-ADT-Dictionary-2011-1.pdf

N/A
N/A
Protected

Academic year: 2020

Share "lecture-DS-10-ADT-Dictionary-2011-1.pdf"

Copied!
62
0
0

Loading.... (view fulltext now)

Full text

(1)
(2)

Specifications for the ADT Dictionary

Specifications for the ADT Dictionary

• Contains entries that each have two parts

p

– A key word or search key

– A value associated with the key

• The fact that every entry in a dictionary has a search key

distinguishes a dictionary from a List

A E

li h di ti

(3)

Specifications for the ADT Dictionary

Specifications for the ADT Dictionary

• Data

Data

– Pairs of objects (key, value)

Number of pairs in the collection

– Number of pairs in the collection

• Operations

add

remove

isEmpty

isFull

getValue

contains

isFull

getSize

(4)

Dictionary types

Dictionary types

• Distinct search Keys (Dictionary of

Distinct search Keys (Dictionary of

students, where Records organized by ID.

And ID’s are unique).

q

)

– if a key is already exists then refuse or

replace

• Duplicate search Key allowed.

• Sorted Dictionaries according to the

search key.

(5)

ADT Dictionary Interface

/** A dictionary with distinct search keys. */

import java.util.Iterator;

public interface DictionaryInterface

{{

/** Task: Adds a new entry to the dictionary. If the given search

* key already exists in the dictionary, replaces the

* corresponding value.

* @param key an object search key of the new entry

* @param value an object associated with the search key

* @return either null if the new entry was added to the dictionary

*

or the value that was associated with key if the value

or the value that was associated with key if the value

* was replaced */

public Object add(Object key, Object value);

/** T

k R

ifi

t

f

th di ti

/** Task: Removes a specific entry from the dictionary.

(6)

ADT Dictionary Interface

/** Task: Retrieves the value associated with a given search key.

* @param key an object search key of the entry to be retrieved

* @return either the value that is associated with the search key

*

ll if

h bj

t

i t */

* or null if no such object exists */

public Object getValue(Object key);

/** Task: Determines whether a specific entry is in the dictionary.

p

y

y

* @param key an object search key of the desired entry

* @return true if key is associated with an entry in the

* dictionary */

public boolean contains(Object key);

public boolean contains(Object key);

/** Task: Creates an iterator that traverses all search keys in the

* dictionary.

* @return an iterator that provides sequential access to the search

* keys in the dictionary */

(7)

ADT Dictionary Interface

/** Task: Creates an iterator that traverses all values in the

* dictionary.

* @return an iterator that provides sequential access to the

@return an iterator that provides sequential access to the

* values in the dictionary */

public Iterator getValueIterator();

/** Task: Determines whether the dictionary is empty.

* @return true if the dictionary is empty */

public boolean isEmpty();

p

p y()

/** Task: Determines whether the dictionary is full.

* @return true if the dictionary is full */

(8)

ADT Dictionary Interface

ADT Dictionary Interface

/** Task: Gets the size of the dictionary.

y

* @return the number of entries (key-value

* pairs) currently in the dictionary */

p

)

y

y

public int getSize();

/** Task: Removes all entries from the

dictionary. */

bli

id l

()

public void clear();

(9)

Applications on Dictionary ADT

Applications on Dictionary ADT

• Checking the meaning of a word

Checking the meaning of a word

• look it up in the Dictionary

• Needing an Address of somebody

• Needing an Address of somebody

• consult address book

• Needing tel Number

• Needing tel-Number

(10)

Using the ADT Dictionary

Using the ADT Dictionary

(11)

Using the ADT Dictionary

Using the ADT Dictionary

import java.io.*;

import java.util.*;

public class TelephoneDirectory

{

private DictionaryInterface phoneBook;

private static final String DELIMITERS = " \n\r\t";

p

g

public TelephoneDirectory()

{{

(12)

Using the ADT Dictionary

/** Task: Reads a text file of names and telephone numbers.

* @param dataFile a text file that is open for input */

public void readFile(BufferedReader dataFile) throws IOException

{{

String line = dataFile.readLine();

while (line != null)

{

StringTokenizer tokenizer = new StringTokenizer(line, DELIMITERS);

StringTokenizer tokenizer new StringTokenizer(line, DELIMITERS);

String firstName = (String)tokenizer.nextToken();

String lastName = (String)tokenizer.nextToken();

String phoneNumber = (String)tokenizer.nextToken();

String phoneNumber (String)tokenizer.nextToken();

Name fullName = new Name(firstName, lastName);

phoneBook.add(fullName, phoneNumber);

line = dataFile.readLine();

} // end while

(13)

Using the ADT Dictionary

Using the ADT Dictionary

public String getPhoneNumber(String firstName,

p

g g

(

g

,

String lastName)

{

Name fullName = new Name(firstName,

lastName);

(14)

Using the ADT Dictionary

Using the ADT Dictionary

public static void main(String[] args)

{{

TelephoneDirectory directory = new TelephoneDirectory();

String fileName = "data.txt";

try

try

{

FileReader reader = new FileReader(fileName);

BufferedReader dataFile = new BufferedReader(reader);

directory.readFile(dataFile);

} // end try

catch (IOException e)

catch (IOException e)

{

(15)

iterators

iterators

getKeyIterator

and

getValueIterator

return iterators

Example:

Iterator keyIterator=myTable.getKeyIterator();

(16)

Java Class Library: The Interface

Map

Java Class Library: The Interface

Map

• A list of method signatures in Map

A list of method signatures in Map

– Note similarity to methods developed in our

ADT

ADT

public

Object put(Object key, Object value);

public

Object remove(Object key);

public

Object get(Object key);

p

j

g (

j

y);

public boolean

containsKey(Object key);

public boolean

containsValue(Object value);

public

Set keySet();

public

Collection values();

public

Collection values();

public boolean

isEmpty();

public int

size();

(17)

Array Based Implementations

• Each entry consists of two parts

– A search key

– A value

• Strategies

– Encapsulate the two parts into an object

j

– Use two parallel arrays

(18)

Array Based Implementations

Array Based Implementations

3 ways to use arrays

y

y

to represent

dictionary entries:

( )

f

t

(a) an array of entry

objects;

(b) parallel arrays of

(b) parallel arrays of

search keys and

values;

(19)

The Entries

The Entries

• A class to represent the two-part entries

i t l E t i l t

private class Entry implements

{ private Object key;

private Object value;

i t E t (Obj t hK Obj t d t V l )

private Entry(Object searchKey, Object dataValue) { key = searchKey;

value = dataValue; } // end constructor

i t Obj t tK ()

private Object getKey()

{ return key; } // end getKey

private Object getValue()}

{ return value; } // end getValue

private void setValue(Object dataValue)

(20)

Unsorted Array-Based Dictionary

Unsorted Array Based Dictionary

• Unsorted array-

Unsorted, array

based dictionary:

• (a) adding an

• (a) adding an

entry;

(b)

i

(21)

Sorted Array-Based Dictionary

Sorted Array Based Dictionary

Adding an entry to

Adding an entry to

a sorted

array-based dictionary:

based dictionary:

(a) search;

(22)

Array-Based Implementations

Array Based Implementations

• Unsorted worst-case efficiencies

– Addition O(1)

– Removal O(n)

– Retrieval O(n)

– Traversal O(n)

• Sorted worst case efficiencies

• Sorted worst-case efficiencies

– Addition O(n)

– Removal O(n)

( )

(23)

Sorted Array-Based Dictionary

Sorted Array Based Dictionary

Beginning of the class

public class

SortedArrayDictionary

implements

DictionaryInterface,

{

private

Entry [] entries;

// array of sorted entries

private int

currentSize = 0; // number of entries

private int

currentSize 0; // number of entries

private final static int

DEFAULT_MAX_SIZE = 25;

public

SortedArrayDictionary()

{

entries =

new

Entry[DEFAULT_MAX_SIZE];

currentSize = 0;

currentSize 0;

} // end default constructor

public

SortedArrayDictionary(

int

maxSize)

{

entries =

new

Entry[maxSize];

(24)

Sorted Array-Based Dictionary

public Object add(Object key, Object value)

{

Object result = null;

i t k I d l t I d (k ) int keyIndex = locateIndex(key); if ( (keyIndex < currentSize)

&& key.equals(entries[keyIndex].getKey()) ) {{

// key found; return and replace old value result = entries[keyIndex].getValue(); entries[keyIndex].setValue(value); } else else { if (isArrayFull())

doubleArray(); // expand array makeRoom(keyIndex);

entries[keyIndex] = new Entry(key, value); currentSize++;

(25)

Sorted Array-Based Dictionary

Sorted Array Based Dictionary

private int locateIndex(Object key)

{

// sequential search

Comparable cKey = (Comparable) key;

int index = 0;

while ( (index < currentSize) &&

( (

)

cKey.compareTo(entries[index].getKey()) > 0 )

index++;

return index;

(26)

Vector-Based Implementations

Vector Based Implementations

• Similar in spirit to the array-based version

Similar in spirit to the array based version

• With vector no need for …

makeRoom

makeRoom

doubleArray

isArrayFull

isArrayFull

– Counting entries, vector does so for you

• Downside

• Downside

(27)

Vector-Based Implementations

Vector Based Implementations

• Beginning of the class

g

g

public class

SortedVectorDictionary

implements

DictionaryInterface,

{

private

Vector entries;

public

SortedVectorDictionary()

{entries =

new

Vector();

//

{entries =

new

Vector();

// as needed, vector doubles its size

} // end default constructor

public

SortedVectorDictionary(

int

maxSize)

{

entries

new

Vector(maxSize);

{

entries =

new

Vector(maxSize);

(28)

Vector-Based Implementations

public Object add(Object key, Object value)

{

Object result = null;

int keyIndex = locateIndex(key);

int keyIndex locateIndex(key);

if ( (keyIndex < entries.size()) &&

key.equals(((Entry)entries.elementAt(keyIndex)).getKey()))

{{

// key found; return and replace old value

Entry currentEntry = (Entry) entries.elementAt(keyIndex);

result = currentEntry.getValue();

currentEntry.setValue(value);

currentEntry.setValue(value);

}

else // add new entry

{

Entry newEntry = new Entry(key, value);

Entry newEntry new Entry(key, value);

entries.insertElementAt(newEntry, keyIndex);

} // end if

(29)

Linked Implementations

Linked Implementations

(30)

Linked Implementations

Linked Implementations

(31)

Linked Implementations

Linked Implementations

(32)

Linked Implementations

Linked Implementations

(33)

Linked Implementations

Linked Implementations

• Unsorted worst-case efficiencies

– Addition O(1)

– Removal O(n)

– Retrieval O(n)

– Traversal O(n)

• Sorted worst case efficiencies

• Sorted worst-case efficiencies

(34)

Linked Implementations

public class SortedLinkedDictionary implements DictionaryInterface { private int currentSize; // number of entries

private Node firstNode; // reference to first node of chain public SortedLinkedDictionary()

{{

firstNode = null; currentSize = 0;

} // end default constructor

public Object add(Object key, Object value) {

Object result = null;

Node newNode = new Node(key, value); // create new node Node newNode new Node(key, value); // create new node Node currentNode = firstNode;

Node nodeBefore = null;

C bl K (C bl ) k Comparable cKey = (Comparable) key;

(35)

Linked Implementations

while ( (currentNode != null) && cKey compareTo(currentNode getKey()) > 0 ) while ( (currentNode ! null) && cKey.compareTo(currentNode.getKey()) > 0 )

{

nodeBefore = currentNode;

currentNode = currentNode.getNextNode(); } // end while

if ( (currentNode != null) && key.equals(currentNode.getKey()) ) {

result = currentNode.getKey();

currentNode.setValue(value); // replace value( ); p }

// should insertion be at beginning of chain? else if (isEmpty() || (nodeBefore == null)) {

newNode setNextNode(firstNode); newNode.setNextNode(firstNode); firstNode = newNode;

currentSize++; }

else // add elsewhere in non-empty list {

(36)

Hashing as a Dictionary Implementation

Hashing as a Dictionary Implementation

• What is Hashing?

g

• A technique that determines an index or location

for storage of an item in a data structure

• The hash function receives the search key

– Returns the index of an element in an array called the

hash table

hash table

– The index is known as the hash index

(37)
(38)

What is Hashing?

What is Hashing?

• Two steps of the hash function

Two steps of the hash function

– Convert the search key into an integer called

the hash code

the hash code

– Compress the hash code into the range of

indices for the hash table

indices for the hash table

• Typical hash functions are not perfect

They can allow more than one search key to

– They can allow more than one search key to

map into a single index

(39)

What is Hashing?

What is Hashing?

Let TableSize= 100

Let TableSize 100

(40)

Hash Functions

Hash Functions

• General characteristics of a good hash

General characteristics of a good hash

function

Minimize collisions

– Minimize collisions

– Distribute entries uniformly throughout the

hash table

hash table

(41)

Computing Hash Codes

Computing Hash Codes

• The hash code for a string,

s

int

hash = 0;

int

n = s.length();

for

(

(

int

i = 0; i < n; i++)

;

;

)

hash = g * hash + s.charAt(i); // g is a positive

constant

• Hash code for a primitive type

p

yp

– Use the primitive typed key itself (casting to int)

– Manipulate internal binary representations (ignore part of internal

binary representation )

U

f ldi

– Use folding

1) Divining a primitive data type into several pieces

2) Combination of pieces by using addition or

(42)

Computing Hash Codes

Computing Hash Codes

• Example: Folding

Example: Folding

(int) key ^ (key>> 32)

• Key>> 32 shifting a 64-bit key to the right

Key>> 32 shifting a 64 bit key to the right

by 32 bits (the right half will be eliminated)

• ^ is exclusive or

is exclusive or

• For a 8-bit binary number:

1) 10101100 >> 4 = 00001010

1) 10101100 >> 4 00001010

2) 10101100 ^ 00001010= 10100110

(43)

Compressing a Hash Code

Compressing a Hash Code

• Must compress the hash code so it fits into the index

p

range

• Typical method for a code

c

is to compute

c

modulo

n

n

n

is a prime number (the size of the table)

is a prime number (the size of the table)

– Index will then be between 0 and

n – 1

private int

getHashIndex(Object key)

{

int

hashIndex = key.hashCode() %

hashTable.length;

if

(hashIndex < 0)

hashIndex = hashIndex + hashTable.length;

return

hashIndex;

(44)

Open Addressing with Linear Probing

Open Addressing with Linear Probing

• Open addressing

Open addressing

scheme locates alternate

location

– New location must be

open, available

• Linear probing

– If collision occurs at

h

hT bl [k] l

k

hashTable[k], look

successively at location

k + 1 k + 2

(45)

Open Addressing, Quadratic Probing

Open Addressing, Quadratic Probing

• Change the probe sequence

Change the probe sequence

– Given search key k

Probe to

k + 1 k + 2

2

k + 3

2

k + n

2

– Probe to k + 1, k + 2

2

, k + 3

2

, … k + n

2

• Reaches every location in the hash table if

t bl

i

i

i

b

(46)

Open Addressing with Double Hashing

Open Addressing with Double Hashing

• Resolves collision by examining locations

Resolves collision by examining locations

– At original hash index

– Plus an increment determined by 2

Plus an increment determined by 2

nd

function

function

• Second hash function

– Different from first

Different from first

– Depends on search key

– Returns nonzero value

(47)

Example of double hashing

Example of double hashing

h1( key)= key % 7

(

y)

y

h2

(

key)= 5- (key % 5)

h1( 16)= 16%7= 2

h2( 16)= 5- (16%5)= 5-1=4

The probe sequence start at 2 and probes locations

increment of 4

increment of 4

(48)

Example of double hashing

Example of double hashing

(49)

Separate Chaining

Separate Chaining

• Alter the structure of the hash table

Alter the structure of the hash table

• Each location can represent multiple values

– Each location called a bucket

Each location called a bucket

• Bucket can be a(n)

– List

– Sorted list

– Chain of linked nodes

– Array

(50)

Separate Chaining

Separate Chaining

(51)

Separate Chaining

Separate Chaining

(52)

A Dictionary Implementation That Uses Hashing

(53)

A Dictionary Implementation That Uses Hashing

• Beginning of private class

Beginning of private class

TableEntry

TableEntry

– Made internal to dictionary class

private clas

s TableEntry {

private

Object entryKey;

p

j

y

y;

private

Object entryValue;

private boolean

inTable;

// true if entry is in hash table

private

TableEntry(Object key, Object value)

{

entryKey = key;

{

entryKey = key;

entryValue = value;

inTable =

true

;

(54)

A Dictionary Implementation That Uses Hashing

public class HashedMapOpenAddressing implements DictionaryInterface,

j

i S i li

bl

java.io.Serializable

{

private TableEntry[] hashTable; // dictionary entries

private int currentSize; // current number of entries

p

;

private static final int DEFAULT_SIZE = 101; // must be prime

// fraction of hash table that can be filled

private static final double MAX LOAD FACTOR = 0 5;

private static final double MAX_LOAD_FACTOR = 0.5;

public HashedMapOpenAddressing()

{

hashTable = new TableEntry[DEFAULT_SIZE];

currentSize = 0;

(55)

A Dictionary Implementation That Uses

H

hi

Hashing

public HashedMapOpenAddressing(int

public HashedMapOpenAddressing(int

tableSize)

{{

int primeSize = getNextPrime(tableSize);

hashTable = new TableEntry[primeSize];

hashTable new TableEntry[primeSize];

currentSize = 0;

(56)

A Dictionary Implementation That Uses

H

hi

Hashing

public Object getValue(Object key)

{{

Object result = null;

int index = getHashIndex(key);

int index = getHashIndex(key);

index = locate(index, key);

if (index != -1)

if (index ! 1)

result = hashTable[index].getValue(); // key found; get value

// else key not found; result is null

y

;

(57)

A Dictionary Implementation That Uses

H

hi

Hashing

public Object remove(Object key)

{{

Object result = null;

int index = getHashIndex(key);

index = locate(index key);

index = locate(index, key);

if (index != -1)

{ // key found; flag entry as removed and return its value

hashTable[index] setToRemoved();

hashTable[index].setToRemoved();

result = hashTable[index].getValue();

currentSize--;

} // end if

// else key not found; result is null

// else key not found; result is null

(58)

A Dictionary Implementation That Uses Hashing

private int locate(int index, Object key) {

boolean found = false;

boolean repeatedIndex = false;

int firstIndex = index; // first index in probe sequence int firstIndex = index; // first index in probe sequence

while ( !found && !repeatedIndex && (hashTable[index] != null) ) {

if ( hashTable[index].isIn() && key.equals(hashTable[index].getKey()) ) found = true; // key found

else // follow probe sequence

index = (index + 1) % hashTable.length; // linear probing if (index == firstIndex)

if (index firstIndex)

repeatedIndex = true; // probe sequence is repeating } // end while

// Assertion: either key is found or a null location is reached i t lt 1

int result = -1; if (found)

(59)

A Dictionary Implementation That Uses Hashing

private int getHashIndex(Object key)

p

g

(

j

y)

{

int hashIndex = key.hashCode() %

y

()

hashTable.length;

if (hashIndex < 0)

hashIndex = hashIndex + hashTable.length;

h

hI d

(60)

A Dictionary Implementation That Uses Hashing

public Object add(Object key, Object value)

{

Object oldValue; // value to return if (isHashTableTooFull())

rehash();

int index = getHashIndex(key);

index = probe(index, key); // check for and resolve collision // Assertion: index is within legal range for hashTable

if ( (hashTable[index] == null) || hashTable[index].isRemoved()) { // key not found, so insert new entry

{ // key not found, so insert new entry

hashTable[index] = new TableEntry(key, value); currentSize++;

oldValue = null; }

l else

{ // key found; get old value for return and then replace it oldValue = hashTable[index].getValue();

hashTable[index].setValue(value); } // end if

(61)

A Dictionary Implementation That Uses Hashing

private int probe(int index, Object key)

{

boolean found = false;

boolean repeatedIndex = false;

int firstIndex = index; // first index in probe sequence i t dSt t I d 1 // i d f fi t l ti i int removedStateIndex = -1; // index of first location in

// removed state

while ( !found && !repeatedIndex && (hashTable[index] != null) ) {

if (hashTable[index].isRemoved()) {{

// save index of first not-in-use location found if (removedStateIndex == -1)

removedStateIndex = index;

index = (index + 1) % hashTable.length; // linear probing }

else if (key.equals(hashTable[index].getKey())) found = true; // key found

else // follow probe sequence

index = (index + 1) % hashTable.length; // linear probing

if (i d fi tI d ) if (index == firstIndex)

repeatedIndex = true; // probe sequence is repeating } // end while

// Assertion: either key or null is found at hashTable[index]

(62)

A Dictionary Implementation That Uses

H

hi

Hashing

private void rehash()

{{

TableEntry[] oldTable = hashTable;

int oldSize = hashTable.length;

int newSize = getNextPrime(oldSize + oldSize);

hashTable = new TableEntry[newSize]; // increase size of array

hashTable = new TableEntry[newSize]; // increase size of array

currentSize = 0; // reset size of dictionary, since it will be

// incremented by add during rehash

// rehash dictionary entries from old array to the new and bigger

// rehash dictionary entries from old array to the new and bigger

// array; skip both null locations and removed entries

for (int index = 0; index < oldSize; index++)

{

if ( (oldTable[index] != null) && oldTable[index] isIn() )

if ( (oldTable[index] != null) && oldTable[index].isIn() )

add(oldTable[index].getKey(), oldTable[index].getValue());

} // end for

References

Related documents