Sunteți pe pagina 1din 51

ALGORITMI

ȘI STRUCTURI DE DATE

Cap.9: Stive. Cozi. Mape

IE.2021

© Cătălin STRÎMBEI & Octavian DOSPINESCU


1
Plan
● (i) Stive
● (ii) Cozi și cozi cu priorități
● (iii) Tabele asociative (mape)

2
1. Stive
● Definiție/concepte:
○ Principiul LIFO
● Tipul abstract de date Stivă/Stack:
○ Interfața Stack
● Implementări:
○ bazate pe tablouri
○ bazate pe liste simplu înlănțuite
● Scurtă aplicație practică cu stive: HanoiTowerWithStack

3
Stiva: Concept
● O stivă (stack) reprezintă o structură de date de tip colecție în care
elementele sunt adăugate și îndepărtate conform principiului LIFO
○ Last-In-First-Out: obiectele pot fi oricând și în orice ordine adăugate, însă direct accesibile
sunt doar cele mai recente (cele din capătul superior - top - al stivei).

4
Stive: exemple

5
Tipul abstract de date Stivă (Stack)
public interface Stack<E> {
Operația Descriere
int size();
size() Returnează capacitatea stivei. boolean isEmpty();
void push(E e);
isEmpty() Returnează un boolean care
E top();
specifică dacă stiva este goală.
E pop();
push(e) Alimentează stiva cu un nou element }
adăugat la capătul superior

pop() Returnează și eliberează elementul


de la capătul superior

top() Returnează fără a elibera elementul


de la capătul superior

6
Exemplu

7
Implementare tip Stiva pe baza unui tablou
● Structura internă a clasei ArrayStack [extras (Goodrich14)]:
public class ArrayStack<E> implements Stack<E> {
/** Default array capacity. */
public static final int CAPACITY=1000; // default array capacity
/** Generic array used for storage of stack elements. */
private E[] data; // generic array used for storage
/** Index of the top element of the stack in the array. */
private int t = -1;
public ArrayStack() { this(CAPACITY); } // constructs stack with default capacity
public ArrayStack(int capacity) { // constructs stack with given capacity
data = (E[]) new Object[capacity]; // safe cast; compiler may give warning
}
...
}
8
Implementare TAD Stiva pe baza unui tablou
● Metode implementare operații în clasa ArrayStack:
public class ArrayStack<E> implements Stack<E> {
public int size() { return (t + 1); }
public boolean isEmpty() { return (t == -1); }
public void push(E e) throws IllegalStateException {
if (size() == data.length) throw new IllegalStateException("Stack is full");
data[++t] = e;
}
public E top() {
if (isEmpty()) return null; return data[t];
}
public E pop() {
if (isEmpty()) return null;
E answer = data[t]; data[t] = null; t--;
return answer;
}
}
9
Implementare TAD Stiva
pe baza unei liste simplu înlănțuite
● Metode Implementare operații în clasa LinkedStack [extras (Goodrich14)]:
public class LinkedStack<E> implements Stack<E> {
/** The primary storage for elements of the stack */
private SinglyLinkedList<E> list = new SinglyLinkedList<>(); // an empty list

public int size() { return list.size(); }


public boolean isEmpty() { return list.isEmpty(); }
public void push(E element) { list.addFirst(element); }
public E top() { return list.first(); }
public E pop() { return list.removeFirst(); }
}

10
Aplicație practică/Studiu de caz Stivă
Recursivitate: Turnul din Hanoi cu Stive
public static <E> void Hanoi(int n, Stack<E> src, Stack<E> dst, Stack<E> tmp) {
if (n > 0) {
// muta toate discurile in tmp cu exceptia celui mai mare
Hanoi(n - 1, src, tmp, dst);

// muta discul cel mai mare (ultimul, adica discul n) in destinatie


dst.push(src.pop());

// recursiv: muta toate discurile din tmp in destinatie (peste discul cel mai mare)
// folosing src ca si tmp de aceasta data
Hanoi(n - 1, tmp, dst, src);
}
}

11
Aplicație practică/Studiu de caz Stivă
Recursivitate: Turnul din Hanoi cu Stive
public static void main(String[] args) {
Stack<String> stack_A = new ArrayStack<String>();
Stack<String> stack_B = new ArrayStack<String>();
Stack<String> stack_C = new ArrayStack<String>();

stack_A.push("disc_1____");
stack_A.push("disc_2___");
stack_A.push("disc_3__");
stack_A.push("disc_4_");
System.out.println("Stack_A: " + stack_A);
System.out.println("Stack_B: " + stack_B);
System.out.println("Stack_C: " + stack_C);

Hanoi(4, stack_A, stack_C, stack_B);


System.out.println("Stack_A: " + stack_A);
System.out.println("Stack_B: " + stack_B);
System.out.println("Stack_C: " + stack_C);
} 12
2. Cozi
● Definiție/concepte:
○ Principiul FIFO
● Tipulul abstract de date Coadă/Queue:
○ Interfața Queue
● Implementări
○ bazate pe tablouri
○ bazate pe liste înlănțuite
● Scurtă aplicație cu cozi: WarehouseQueue

13
Coada: concept
● O coadă (queue) reprezintă o structură de date de tip colecție în care
elementele sunt adăugate și îndepărtate conform principiului FIFO:
○ First-In-First-Out: obiectele pot fi adăugate oricând și în orice ordine, însă direct accesibile
sunt doar cele mai “vechi”.

14
Tipul abstract Coadă/Queue
public interface Queue<E> {
Operația Descriere
int size();
size() Returnează capacitatea cozii. boolean isEmpty();
void enqueue(E e);
isEmpty() Returnează un boolean care
E dequeue();
specifică dacă coada este goală.
E first();
enqueue(e) Alimentează coada cu un nou }
element adăugat la capătul superior

dequeue() Returnează și eliberează primul


element din coadă.

first() Returnează fără a elibera primul


element din coadă.

15
Implementare tip Coadă pe baza unui tablou
● Structura internă a clasei ArrayQueue [extras (Goodrich14)]:
public class ArrayQueue<E> implements Queue<E> {
/** Default array capacity. */
public static final int CAPACITY = 1000; // default array capacity
/** Generic array used for storage of queue elements. */
private E[] data; // generic array used for storage
/** Index of the top element of the queue in the array. */
private int f = 0; // index of the front element
/** Current number of elements in the queue. */
private int sz = 0; // current number of elements

public ArrayQueue() {this(CAPACITY);} // constructs queue with default capacity


public ArrayQueue(int capacity) { // constructs queue with given capacity
data = (E[]) new Object[capacity]; // safe cast; compiler may give warning
}
}

16
Implementare tip Coadă pe baza unui tablou
● Metode Implementare operații în clasa ArrayQueue
public class ArrayQueue<E> implements Stack<E> {
public int size() { return sz; }
public boolean isEmpty() { return (sz == 0); }
public void enqueue(E e) throws IllegalStateException {
if (sz == data.length) throw new IllegalStateException("Queue is full");
int avail = (f + sz) % data.length; // use modular arithmetic
data[avail] = e; sz++;
}
public E first() {
if (isEmpty()) return null;
return data[f];
}
public E dequeue() {
if (isEmpty()) return null;
E answer = data[f]; data[f] = null;
f = (f + 1) % data.length; sz--;
return answer;
}
} 17
Implementare tip Coadă pe baza unui tablou

18
Implementare tip Coadă:
pe baza unei liste simplu înlănțuite
● Metode Implementare operații în clasa LinkedQueue [extras (Goodrich14)]:

public class LinkedQueue<E> implements Queue<E> {


/** The primary storage for elements of the queue */
private SinglyLinkedList<E> list = new SinglyLinkedList<>()

public int size() { return list.size(); }


public boolean isEmpty() { return list.isEmpty(); }
public void enqueue(E element) { list.addLast(element); }
public E first() { return list.first(); }
public E dequeue() { return list.removeFirst(); }
}

19
Aplicație practică/Studiu de caz Coadă
Gestionare elemente în depozit
public class WarehouseQueue<E> {
private Double threshold = 0.0;
private Double fillingLevel = 0.0;
private Double warehouseMaxCapacity = 0.0;
private LinkedQueue<WarehouseEntry<E>> wQueue = new LinkedQueue<>();
//
public static class WarehouseEntry<E>{
private E entry;
private Double amount;
... ... // getters&setters&constructors
}
//
public WarehouseQueue(Double threshold, Double warehouseMaxCapacity) {
this.threshold = threshold;
this.warehouseMaxCapacity = warehouseMaxCapacity;
}
}
20
Aplicație practică/Studiu de caz Coadă
Gestionare elemente în depozit
public Stack<E> addIntoWarehouse(E entry, Double amount){
// check if there is enough room even after releasing some older items
if (this.fillingLevel + amount > this.warehouseMaxCapacity &&
this.threshold + amount > this.warehouseMaxCapacity)
throw new RuntimeException("Not enough space in warehouse!");

// firstly remove some items to make enough room for the new entry
Stack<E> releasedItems = releaseItemsFromWarehouse();

WarehouseEntry<E> newEntry = new WarehouseEntry<E>(entry, amount);


// add the new entry
this.wQueue.enqueue(newEntry);
// increase warehouse filling level
this.fillingLevel += newEntry.getAmount();
return releasedItems;
}

21
Aplicație practică/Studiu de caz Coadă
Gestionare elemente în depozit
private Stack<E> releaseItemsFromWarehouse() {
Stack<E> releasedItems = new ArrayStack<E>();
WarehouseEntry<E> releasedEntry;
// release item until warehouse filling level fall under warehouse threshold
while(this.fillingLevel > this.threshold) {
// release item under FIFO rule
releasedEntry = this.wQueue.dequeue();
// increase warehouse filling level
this.fillingLevel -= releasedEntry.getAmount();
releasedItems.push(releasedEntry.getEntry());
}
return releasedItems;
}

22
Aplicație practică/Studiu de caz Coadă
Gestionare elemente în depozit - Test
public static void main(String[] args) {
WarehousePQueue<String> warehouseQueue = new WarehousePQueue<String>(60.0, 100.0);
Stack<String> releasedItems;
//
releasedItems = warehouseQueue.addIntoWarehouse("Item_1", 20.0);
System.out.println(">>> Warehouse: " + warehouseQueue);
System.out.println(">>> >>> releasedItems: " + releasedItems);
System.out.println("-------------------------------------------");

releasedItems = warehouseQueue.addIntoWarehouse("Item_2", 40.0);


System.out.println(">>> Warehouse: " + warehouseQueue);
System.out.println(">>> >>> releasedItems: " + releasedItems);
System.out.println("-------------------------------------------");

releasedItems = warehouseQueue.addIntoWarehouse("Item_3", 30.0);


System.out.println(">>> Warehouse: " + warehouseQueue);
System.out.println(">>> >>> releasedItems: " + releasedItems);
System.out.println("-------------------------------------------");
... ...
}

23
Aplicație practică/Studiu de caz Coadă
Gestionare elemente în depozit - Test
public static void main(String[] args) {
... ...
releasedItems = warehouseQueue.addIntoWarehouse("Item_4", 20.0);
System.out.println(">>> Warehouse: " + warehouseQueue);
System.out.println(">>> >>> releasedItems: " + releasedItems);
System.out.println("-------------------------------------------");

releasedItems = warehouseQueue.addIntoWarehouse("Item_5", 15.0);


System.out.println(">>> Warehouse: " + warehouseQueue);
System.out.println(">>> >>> releasedItems: " + releasedItems);
System.out.println("-------------------------------------------");

releasedItems = warehouseQueue.addIntoWarehouse("Item_6", 10.0);


System.out.println(">>> Warehouse: " + warehouseQueue);
System.out.println(">>> >>> releasedItems: " + releasedItems);
System.out.println("-------------------------------------------");

releasedItems = warehouseQueue.addIntoWarehouse("Item_7", 40.0);


System.out.println(">>> Warehouse: " + warehouseQueue);
System.out.println(">>> >>> releasedItems: " + releasedItems);
System.out.println("-------------------------------------------");
} 24
Cozi cu priorități PriorityQueue
● Definiție/concepte:
○ Definire priorități
● Tipul abstract de date coadă-cu-priorități PriorityQueue:
○ Interfața PriorityQueue
● Implementare
○ Structura EntryComposite
○ Comparabilitate pentru stabilire priorități: interfețele Comparable și Comparator
○ Clasa abstractă AbstractPriorityQueue
○ Implementare AbstractPriorityQueue (prin mecanismul LinkedPositionalList) folosind o listă
nesortată.
● Scurtă aplicație cu cozi: WarehousePQueue

25
Coadă cu priorități: concept
● O coadă cu priorități (priority queue) reprezintă o structură de date de tip
colecție în care elementele sunt adăugate arbitrar și sunt accesate și
îndepărtate (mai întâi) elementele cu prioritatea cea mai mare (primele în
ordinea priorității).
○ Prioritatea reprezintă o proprietate specifică elementelor desemnată printr-o cheie ale cărei
valori minimale desemnează prioritățile cele mai importante.

26
Tipul abstract CoadăCuPriorități PriorityQueue
public interface PriorityQueue<K,V> {
Operația Descriere
int size();
size() Returnează capacitatea cozii. boolean isEmpty();
Entry<K,V> insert(K key, V value)
isEmpty() Returnează un boolean care
Entry<K,V> min();
specifică dacă coada este goală.
Entry<K,V> removeMin();
insert(k, v) Alimentează coada cu o nouă intrare }
cu prioritatea k și valoarea v.
// Entry Composite
min() Returnează intrarea cu cheia (k) cea public interface Entry<K,V> {
mai mică din coadă (fără eliberare). K getKey();
removeMin() Returnează și eliberează intrarea cu V getValue();
cheia (k) cea mai mică din coadă. }

27
Comparabilitatea cheilor de prioritate
● Conceptul de cheie minimală este definit prin:
○ kmin <= k, pentru orice k din setul de chei.
● Conceptul de prioritate sau de cheie minimală este abstractizat prin
formalizarea conceptului de comparabilitate - definit în Java prin interfețele:
○ Comparable<T>, care impune pentru instanțele claselor conforme (care o implementează)
sintaxa
■ a.compareTo(b);
○ Comparator<T>, care permite compararea instanțelor unor clase arbitrare printr-un obiect
extern prin sintaxa:
■ comparator.compare(a, b);

28
Exemplu implementare comparabilitate
public class StringLengthComparator implements Comparator<String> {
/** Compares two strings according to their lengths. */
public int compare(String a, String b) {
if (a.length() < b.length()) return -1;
else if (a.length() == b.length()) return 0;
else return 1;
}
}

public class DefaultComparator<E> implements Comparator<E> {


public int compare(E a, E b) throws ClassCastException {
return ((Comparable<E>) a).compareTo(b);
}
}
29
Implementare TAD Coadă cu priorități
Clasa de bază (abstractă)
● Structura clasei de bază AbstractPriorityQueue [extras (Goodrich14)]:

public class AbstractPriorityQueue<E> implements Stack<E> {


... ...
protected static class PQEntry<K,V> implements Entry<K,V> {...}
protected AbstractPriorityQueue() { this(new DefaultComparator<K>()); }
protected AbstractPriorityQueue(Comparator<K> c) { comp = c; }

/** Method for comparing two entries according to key */


protected int compare(Entry<K,V> a, Entry<K,V> b) {
return comp.compare(a.getKey(), b.getKey());
}
public boolean isEmpty() { return size() == 0; }
... ...
}
30
Implementare TAD Coadă cu priorități
Folosirea unei liste nesortate
● Structura internă a clasei de bază UnsortedPriorityQueue [extras (Goodrich14)]:
public class UnsortedPriorityQueue<K,V> extends AbstractPriorityQueue<K,V> {
/** primary collection of priority queue entries */
private PositionalList<Entry<K,V>> list = new LinkedPositionalList<>();
private Position<Entry<K,V>> findMin() { // only called when nonempty
Position<Entry<K,V>> small = list.first();
for (Position<Entry<K,V>> walk : list.positions())
if (compare(walk.getElement(), small.getElement()) < 0)
small = walk; // found an even smaller key
return small;
}
public Entry<K,V> insert(K key, V value) throws IllegalArgumentException {
... ...
Entry<K,V> newest = new PQEntry<>(key, value);
list.addLast(newest);
return newest;
}
... ...
31
}
Implementare tip Coadă cu priorități:
Folosirea unei liste nesortate (c.)
● Structura internă a clasei de bază UnsortedPriorityQueue:

public class UnsortedPriorityQueue<K,V> extends AbstractPriorityQueue<K,V> {


... ...
public Entry<K,V> min() {
if (list.isEmpty()) return null;
return findMin().getElement();
}
public Entry<K,V> removeMin() {
if (list.isEmpty()) return null;
return list.remove(findMin());
}
public int size() { return list.size(); }
}

32
Aplicație practică/Studiu de caz Coadă
Gestionare elemente în depozit
public class WarehousePQueue<E> {
private Double threshold = 0.0;
private Double fillingLevel = 0.0;
private Double warehouseMaxCapacity = 0.0;
private PriorityQueue<Double, WarehouseEntry<E>> wQueue = new UnsortedPriorityQueue<>();
//
public static class WarehouseEntry<E>{
private E entry;
private Double amount;
... ...
}
//
public WarehouseQueue(Double threshold, Double warehouseMaxCapacity) {
this.threshold = threshold;
this.warehouseMaxCapacity = warehouseMaxCapacity;
}
}
33
Aplicație practică/Studiu de caz Coadă
Gestionare elemente în depozit
public Stack<E> addIntoWarehouse(E entry, Double amount){
System.out.println("... adding:" + entry + " with: " + amount);

// check if there is enough room even after releasing some older items
if (this.fillingLevel + amount > this.warehouseMaxCapacity &&
this.threshold + amount > this.warehouseMaxCapacity)
throw new RuntimeException("Not enough space in warehouse!");
// firstly remove some items to make enough room for the new entry
Stack<E> releasedItems = releaseItemsFromWarehouse();

WarehouseEntry<E> newEntry = new WarehouseEntry<E>(entry, amount);


// add the new entry
this.wQueue.insert(newEntry.getAmount(), newEntry);
// increase warehouse filling level
this.fillingLevel += newEntry.getAmount();
return releasedItems;
}
34
Aplicație practică/Studiu de caz Coadă
Gestionare elemente în depozit
private Stack<E> releaseItemsFromWarehouse() {
Stack<E> releasedItems = new ArrayStack<E>();
WarehouseEntry<E> releasedEntry;
// release item until warehouse filling level fall under warehouse threshold
while(this.fillingLevel > this.threshold) {
// release item under FIFO rule
releasedEntry = this.wQueue.removeMin().getValue();
// increase warehouse filling level
this.fillingLevel -= releasedEntry.getAmount();
releasedItems.push(releasedEntry.getEntry());
}
return releasedItems;
}

35
Aplicație practică/Studiu de caz Coadă
Gestionare elemente în depozit
public class WarehousePQueue<E> {
private Double threshold = 0.0;
private Double fillingLevel = 0.0;
private Double warehouseMaxCapacity = 0.0;
// Folosim ComparatorWarehouseAmount pentru a elimina cu prioritate articolele cele mai mari
private PriorityQueue<Double, WarehouseEntry<E>> wQueue =
new UnsortedPriorityQueue<>(new ComparatorWarehouseAmount());

//
private static class ComparatorWarehouseAmount implements Comparator<Double>{
@Override
public int compare(Double o1, Double o2) {
return -o1.compareTo(o2);
}
}
... ...
}
36
}
3. Tabele asociative (mape). Sumar
● Definiție/concepte:
○ Conceptul de cheie de căutare
○ Tablouri asociative/Tabele de simboluri
● Tipul abstract de date Map :
○ Interfața Map
● Implementări
○ Structura MapEntry
○ Clasa abstractă AbstractMap
■ Structuri: KeyIterator și ValueIterator
○ Implementare AbstractMap (prin mecanismul ArrayList)
■ folosind o listă nesortată UnsortedTableMap
● Scurtă aplicație cu mape: WordCount

37
Tabela asociativă: concept
● O tabelă asociativă (mapă) reprezintă o structură de date pentru stocarea și
regăsirea eficientă a valorilor (elementelor) identificate în mod unic printr-o
cheie de căutare.
○ În mod specific, o tabelă asociativă gestioneză perechi cheie-valoare (k, v), numite intrări, ale
căror chei sunt unice în cadrul tabelei.
○ O strategie de implementare ar putea consta în transformarea cheilor în valori Integer care ar
putea fi folosite drept indecși pentru referențierea în cadrul unui tablou.
● Cazuri de utilizare pentru tabele asociative:
○ Sistemul informațional universitar - gestiune școlaritate
■ Matricol → ÎnregistrareStudent
○ Sistemul de gestiune a numelor de domeniu DNS
■ HostName → AddressURL
○ Site social media
■ Username → Profile
38
Tipul abstract Map
Operația Descriere

size() Returnează numărul de intrări din tabelă.

isEmpty() Returnează un boolean care specifică dacă tabela este goală.

get(k) Returnează valoare v asociată cu cheia k.

put(k,v) Dacă tabela nu are o intrare cu cheia k, atunci va fi adăugată intrarea (k,v) și
returnează null; altfel va înlocui cu v valoare existentă (din intrarea existentă cu cheia k)
și va returna vechea valoare.

remove(k) Șterge intrarea cu cheia k și returnează valoare v asociată.

keySet() Returnează o colecție iterabilă conținând toate cheile din tabelă.

values() Returnează o colecție iterabilă conținând toate valorile (intrărilor) din tabelă, eventual
duplicate dacă mai multe chei sunt asociate cu aceeași valoare.

entrySet() Returnează o colecție iterabilă conținând toate intrările cheie-valoare din tabelă.
39
Interfața Java pentru tipul abstract Map
public interface Map<K,V> {
int size();
boolean isEmpty();
V get(K key);
V put(K key, V value);
V remove(K key);
Iterable<V> values();
Iterable<Entry<K,V>> entrySet();
}

40
TAD Map

41
Implementare TAD Map:
Folosirea unei liste nesortate (ArrayList)
● Structura internă a clasei de bază UnsortedTableMap: size(), entrySet()
public class UnsortedTableMap<K,V> extends AbstractMap<K,V> {
private ArrayList<MapEntry<K,V>> table = new ArrayList<>();
public int size() { return table.size(); }
//---------------- nested EntryIterator class ----------------
private class EntryIterator implements Iterator<Entry<K,V>> {
private int j=0;
public boolean hasNext() { return j < table.size(); }
public Entry<K,V> next() {
if (j == table.size()) throw new NoSuchElementException("No further entries");
return table.get(j++);
} ...
}
//---------------- nested EntryIterable class ----------------
private class EntryIterable implements Iterable<Entry<K,V>> {
public Iterator<Entry<K,V>> iterator() { return new EntryIterator(); }
}
public Iterable<Entry<K,V>> entrySet() { return new EntryIterable(); }
...}
42
Implementare TAD Map:
Clasa de bază (abstractă)
● Structura clasei de bază AbstractMap - key iterator [extras (Goodrich14)]:
public class AbstractMap<K,V> implements Map<K,V> {
... ...
//---------------- nested KeyIterator class ----------------
private class KeyIterator implements Iterator<K> {
private Iterator<Entry<K,V>> entries = entrySet().iterator(); // reuse entrySet
public boolean hasNext() { return entries.hasNext(); }
public K next() { return entries.next().getKey(); } // return key!
public void remove() { throw new UnsupportedOperationException("remove not supported"); }
}
//---------------- nested KeyIterable class ----------------
private class KeyIterable implements Iterable<K> {
public Iterator<K> iterator() { return new KeyIterator(); }
}
public Iterable<K> keySet() { return new KeyIterable(); }
... ...
}
43
Implementare TAD Map:
Clasa de bază (abstractă)
● Structura clasei de bază AbstractMap - values iterator
public class AbstractMap<K,V> implements Map<K,V> {
... ...
//---------------- nested ValueIterator class ----------------
private class ValueIterator implements Iterator<V> {
private Iterator<Entry<K,V>> entries = entrySet().iterator(); // reuse entrySet
public boolean hasNext() { return entries.hasNext(); }
public V next() { return entries.next().getValue(); } // return value!
public void remove() { throw new UnsupportedOperationException("remove not supported"); }
}
//---------------- nested ValueIterable class ----------------
private class ValueIterable implements Iterable<V> {
public Iterator<V> iterator() { return new ValueIterator(); }
}
public Iterable<V> values() { return new ValueIterable(); }
... ...
}
44
Implementare TAD Map:
Folosirea unei liste nesortate (ArrayList)
● Structura internă a clasei de bază UnsortedTableMap: get()
public class UnsortedTableMap<K,V> extends AbstractMap<K,V> {
private int findIndex(K key) {
int n = table.size();
for (int j=0; j < n; j++)
if (table.get(j).getKey().equals(key))
return j;
return -1; // special value denotes that key was not found
}
public V get(K key) {
int j = findIndex(key);
if (j == -1) return null; // not found
return table.get(j).getValue();
}
public boolean isEmpty() { return size() == 0; }
... ...
}
45
Implementare TAD Map:
Folosirea unei liste nesortate (ArrayList)
● Structura internă a clasei de bază UnsortedTableMap: put(), remove()
public class UnsortedTableMap<K,V> extends AbstractMap<K,V> {
public V put(K key, V value) {
int j = findIndex(key);
if (j == -1) {
table.add(new MapEntry<>(key, value)); // add new entry
return null;
} else // key already exists
return table.get(j).setValue(value); // replaced value is returned
}
public V remove(K key) {
int j = findIndex(key); int n = size();
if (j == -1) return null; // not found
V answer = table.get(j).getValue();
if (j != n - 1)
table.set(j, table.get(n-1)); // relocate last entry to 'hole' created by removal
table.remove(n-1); // remove last entry of table
return answer;
}
} 46
Aplicație practică/Studiu de caz Tabelă asociativă
WordCount
public static Map<String, Integer> wordFrequences(String text){
String[] words = text.split("\\W+");
Map<String, Integer> wordFrequences = new UnsortedTableMap<>();
for(String word: words) {
if (wordFrequences.get(word) == null)
wordFrequences.put(word, 0);
wordFrequences.put(word, wordFrequences.get(word)+1);
}
return wordFrequences;
}

47
Aplicație practică/Studiu de caz Tabelă asociativă
WordCount
public static String maxWordCount(String text) {
Map<String, Integer> wordFrequences = wordFrequences(text);
int max = 0;
String mostFrequentWord = null;
for (String word: wordFrequences.keySet()) {
System.out.println("Word: " + word + ": " + wordFrequences.get(word));
if (wordFrequences.get(word) > max) {
max = wordFrequences.get(word);
mostFrequentWord = word;
}
}
return mostFrequentWord;
}

48
Aplicație practică/Studiu de caz Tabelă asociativă
WordCount - Test
public class WordCount {
public static String maxWordCount(String text) { ... }
public static String wordFrequences(String text) { ... }

public static void main(String[] args) {


String text = ... ;
Map<String, Integer> wordFrequences = wordFrequences(text);
String word = maxWordCount(text);
System.out.println("most frequent word: " + word + " -> " +
wordFrequences.get(word));

}
}

49
Referințe Java

2014_Data Structures and Algorithms in 2011_Sedgewick_Algorithms(Sedgewick11)


Java (Goodrich14)
● C1.3 Bags, Queues, Stacks p120
● Chapter 6: Stacks, Queues, and ● C2.4 Priority Queues p308
Deques, p225 ● C3.4 Hash Tables p458
● Chapter 9: Priority Queues, p359
● Chapter 10: Maps, Hash Tables, and
Skip Lists, p401

50
Bibliografie
● Michael T. Goodrich, Roberto Tamassia, Michael H. Goldwasser, Data
Structures and Algorithms in Java™, Sixth Edition, Wiley, 2014 [Goodrich14]
● Robert Sedgewick, Kevin Wayne, Algorithms, Fourth Edition,
Addison-Wesley, 2011 [Sedgewick11]

51

S-ar putea să vă placă și