Cátia Vaz
Cátia Vaz
Cátia Vaz
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
Tipos de Dados Abstratos<br />
Algoritmos e Estruturas de Dados<br />
Verão 2012<br />
Cátia <strong>Vaz</strong><br />
1
Tipos Abstratos<br />
n Um tipo abstrato é:<br />
n<br />
n<br />
n<br />
um tipo genérico de dados, dos quais não se conhece os<br />
valores<br />
uma interface que define os acessos e as operações sobre<br />
os dados<br />
O conjunto das propriedades algébricas da interface, que<br />
delimitam as possíveis implementações.<br />
n<br />
n<br />
Um programa que usa um tipo abstrato é um<br />
cliente. O cliente não tem acesso à implementação.<br />
Um programa que especifique o tipo de dados é<br />
uma implementação.<br />
Cátia <strong>Vaz</strong><br />
2
Pilha - Stack<br />
n<br />
Operações abstratas:<br />
n<br />
n<br />
n<br />
n<br />
inicialização;<br />
colocação de um elemento na pilha;<br />
remoção de um elemento (o último colocado); LIFO<br />
indicar se pilha está vazia.<br />
n interface para uma pilha que contenha inteiros:<br />
public interface intStack{<br />
public boolean empty();<br />
public void push(int i);<br />
}<br />
várias<br />
public int pop();<br />
Usando a mesma interface,<br />
podem ser definidas<br />
implementações!<br />
Cátia <strong>Vaz</strong><br />
3
Pilha - Stack<br />
n<br />
Operações abstratas:<br />
n<br />
n<br />
n<br />
n<br />
inicialização;<br />
colocação de um elemento na pilha;<br />
remoção de um elemento (o último colocado); LIFO<br />
indicar se pilha está vazia.<br />
n interface para uma pilha genérica:<br />
public interface Stack< E > {<br />
public boolean isEmpty();<br />
}<br />
public E push(E i);<br />
várias<br />
implementações!<br />
public E pop();<br />
public E peek();<br />
Usando a mesma interface,<br />
podem ser definidas<br />
Cátia <strong>Vaz</strong><br />
4
Pilha (Stack) - inserção<br />
5
Pilha (Stack) - remoção<br />
6
Implementação do tipo pilha<br />
usando um array<br />
//Não compila!!<br />
public class StackArray implements Stack{<br />
private E[] s;<br />
private int top;<br />
public StackArray(int capacity) {<br />
s=new E[capacity];<br />
}<br />
//! a criação de um array genérico não é permitida em Java<br />
public boolean isEmpty(){ return top == 0; }<br />
public E peek() {<br />
if(isEmpty()) throw new EmptyStackException();<br />
return s[top-1]; }<br />
}<br />
public E push(E item) {<br />
if( top == s.length ) return null;<br />
s[top++] = item; return item;<br />
}<br />
public E pop() {<br />
if(isEmpty()) throw new EmptyStackException();<br />
E e = s[--top]; s[top] = null;<br />
return e;<br />
}<br />
Cátia <strong>Vaz</strong><br />
7
Implementação do tipo pilha<br />
usando um array<br />
public class StackArray implements Stack{<br />
private E[] s;<br />
private int top;<br />
public StackArray(int capacity) {<br />
s= ( E[] ) new Object[capacity]; //solução!<br />
}<br />
public boolean isEmpty(){ return top == 0; }<br />
public E peek() {<br />
if(isEmpty()) throw new EmptyStackException();<br />
}<br />
return s[top-1]; }<br />
public E push(E item) {<br />
if( top == s.length ) return null;<br />
s[top++] = item; return item;<br />
}<br />
public E pop() {<br />
if(isEmpty()) throw new EmptyStackException();<br />
E e = s[--top]; s[top] = null;<br />
return e;<br />
}<br />
Vantagens: simplicidade.<br />
Desvantagens: tamanho<br />
máximo limitado à partida.<br />
Cátia <strong>Vaz</strong><br />
8
Lista Simplesmente Ligada<br />
n<br />
n<br />
Uma lista ligada é uma colecção de objectos, designados por<br />
nós , em que cada um contêm dados e apenas uma referência<br />
para outro nó, de modo a formarem uma lista. O primeiro nó é<br />
designado por head node.<br />
Uma lista ligada diz-se simplesmente ligada quando cada nó<br />
contém uma referência para o próximo nó.<br />
private class Node{<br />
private E data;<br />
private Node next;<br />
...<br />
}<br />
Exemplo:<br />
:SLinkedList<br />
head<br />
:Node<br />
item<br />
next<br />
“c”<br />
:Node<br />
item<br />
next<br />
“g”<br />
null<br />
Cátia <strong>Vaz</strong><br />
9
Implementação do tipo pilha<br />
usando um lista ligada<br />
public class StackList implements Stack{<br />
private static class Node {<br />
E item; Node next;<br />
Node(E i, Node n){ item=i; next = n;}<br />
}<br />
private Node head;<br />
public boolean isEmpty() {return head == null; }<br />
public E peek() {<br />
if(isEmpty()) throw new EmptyStackException();<br />
return head.item; }<br />
public E push(E item) {<br />
head = new Node(item, head);<br />
return item;<br />
}<br />
public E pop() {<br />
if(isEmpty()) throw new EmptyStackException();<br />
E item = head.item;<br />
head = head.next;<br />
return item;<br />
}<br />
}<br />
Vantagens:<br />
- aumenta e diminui consoante se<br />
inserem ou removem novos<br />
elementos na pilha.<br />
Desvantagens:<br />
- ocupa mais memória.<br />
- acesso mais lento.<br />
Cátia <strong>Vaz</strong><br />
10
Que estrutura de dados<br />
escolher?<br />
§ Depende :<br />
n<br />
n<br />
das operações que sejam mais frequentes no algoritmo a<br />
implementar:<br />
n Se a escolha for entre arrays e listas, dever-se-á escolher:<br />
n<br />
n<br />
n<br />
n<br />
arrays se forem predominantes as operações de acesso e<br />
modificação;<br />
listas se forem predominantes as operações de inserção e<br />
remoção.<br />
Usar listas simples, se estas operações ocorrem sempre no início.<br />
Usar listas simples com ponteiro adicional para o fim da lista,<br />
se a inserção se fizer no fim e a remoção no início.<br />
da previsibilidade sobre a memória necessária:<br />
n o uso de arrays pressupõe que se saiba que memória é<br />
suficiente;<br />
n quando não é previsível é necessário gerir a memória<br />
dinamicamente.<br />
Cátia <strong>Vaz</strong><br />
11
PriorityQueue<br />
public interface PriorityQueue{<br />
public void add(E elem, P prio, KeyExtractor keyExtractor);<br />
}<br />
public E pick();<br />
public E poll();<br />
public E update(int key, P prio);<br />
public void remove(int key);<br />
public interface KeyExtractor{<br />
public int getKey(E e);<br />
}<br />
12
Fila-Queue<br />
n<br />
Operações abstratas:<br />
n<br />
n<br />
n<br />
n<br />
inicialização;<br />
colocação de um elemento na fila;<br />
remoção de um elemento (FIFO);<br />
indicar se fila está vazia.<br />
n interface para uma fila :<br />
public interface Queue{<br />
public boolean isEmpty();<br />
}<br />
public boolean offer(E i);<br />
public E poll();<br />
public E remove();<br />
public E peek();<br />
Usando a mesma interface,<br />
podem ser definidas várias<br />
implementações!<br />
Cátia <strong>Vaz</strong><br />
13
Fila (Queue) - inserção<br />
14
Fila (Queue) - remoção<br />
15
Implementação do tipo fila<br />
usando um array<br />
public class QueueArray implements Queue {<br />
private E[] q;<br />
private int size, head, tail;<br />
public QueueArray(int maxN) { q=(E[])new Object[maxN]; }<br />
public boolean isEmpty() { return size == 0 ;}<br />
public boolean offer(E e){<br />
if( size == q.length) return false;<br />
q[tail] = e;<br />
tail = (tail+1) % q.length; ++size;<br />
return true;<br />
}<br />
public E remove() {<br />
if(isEmpty()) throw new NoSuchElementException();<br />
E e= q[head]; q[head]= null;<br />
head= (head+1)%q.length; --size;<br />
return e;<br />
}<br />
public E poll(){ return ( size == 0 ) ? null : remove();}<br />
public E peek() {return ( size == 0 ) ? null : q[head]; }<br />
}<br />
16
Implementação do tipo fila<br />
usando uma lista ligada<br />
public class QueueList implements Queue {<br />
private static class Node {<br />
E item; Node next;<br />
Node() { next=this; }<br />
Node(E i, Node n) { item=i; next = n; }<br />
}<br />
private Node tail = new Node();<br />
public boolean isEmpty() { return tail == tail.next; }<br />
public boolean offer(E e){<br />
tail.next = new Node( e, tail.next ); tail = tail.next;<br />
return true;<br />
}<br />
public E remove() {<br />
if(isEmpty()) throw new NoSuchElementException();<br />
Node rem = tail.next.next; tail.next.next = rem.next;<br />
if ( rem == tail ) tail = tail.next;<br />
return rem.item;<br />
}<br />
public E poll() { return ( isEmpty() ) ? null : remove(); }<br />
public E peek() { return ( isEmpty()) ? null :<br />
tail.next.next.item; }<br />
}<br />
17
ADTs<br />
§ ADTs permitem programação modular:<br />
§ separam o programa em módulos mais pequenos;<br />
§ clientes diferentes podem partilhar a mesma ADT.<br />
§ ADTs permitem o encapsulamento:<br />
§ mantêm-se os módulos independentes;<br />
§ podem-se substituir as várias classes que implementam a<br />
mesma interface, sem alterar o cliente.<br />
§ Aspectos do desenho de uma ADT:<br />
§ especificação formal do problema;<br />
§ a implementação tem tendência a tornar-se obsoleta.<br />
Cátia <strong>Vaz</strong><br />
18
Lista duplamente ligada<br />
Inserção<br />
19
Lista duplamente ligada<br />
Pesquisa<br />
20
Lista duplamente ligada<br />
Remoção<br />
21
Lista Duplamente Ligada<br />
public interface DList extends Iterable{<br />
public int size();<br />
public boolean isEmpty();<br />
public void add(E e);<br />
public boolean remove(E e);<br />
}<br />
Cátia <strong>Vaz</strong><br />
22
Iteradores<br />
public interface Iterable {<br />
public Iterator iterator();<br />
}<br />
public interface Iterator {<br />
public boolean hasNext();<br />
public E next();<br />
public void remove();<br />
}<br />
Cátia <strong>Vaz</strong><br />
23
Lista Duplamente Ligada<br />
public class DLinkedList1 implements DList {<br />
private static class DNode {<br />
public DNode next, prev;<br />
public T key;<br />
public DNode() { }<br />
public DNode(T e ) { key=e; }<br />
}<br />
protected int size;<br />
protected DNode head;<br />
public int size() { return size;}<br />
public boolean isEmpty(){ return head == null;}<br />
public void add(E e) { // Adiciona o elemento no inicio da lista ligada<br />
DNode n=new DNode(e);<br />
if(head!=null){ n.next=head; head.prev=n;}<br />
head=n; }<br />
//(continua...)<br />
}<br />
Cátia <strong>Vaz</strong><br />
24
Lista Duplamente Ligada<br />
public class DLinkedList1 implements DList {<br />
//(continuação...)<br />
// Remove o primeiro elemento da lista igual a e<br />
public boolean remove (E e){<br />
DNode aux=search(e);<br />
if(aux!=null){<br />
if(aux.prev != null) {aux.prev.next = aux.next;}<br />
else{head = aux.next;}<br />
if(aux.next != null){ aux.next.prev = aux.prev;}<br />
return true;<br />
}<br />
else return false;<br />
}<br />
protected DNode search( E e ){<br />
DNode aux = head;<br />
while( aux != null && !aux.key.equals(e))<br />
aux=aux.next;<br />
return aux;<br />
}<br />
//(continua...)<br />
}<br />
Cátia <strong>Vaz</strong><br />
25
Lista Duplamente Ligada<br />
public class DLinkedList1 implements DList {<br />
//(continuação...)<br />
public static void show(DNode l){<br />
System.out.print("< ");<br />
while(l != null){ System.out.print(l.key+" "); l = l.next;}<br />
System.out.println(">");<br />
}<br />
public void reverse() {<br />
DNode iter = head, aux;<br />
while( iter != null ) {<br />
head = iter;<br />
aux = iter.next;<br />
iter.next = iter.prev;<br />
iter.prev = aux;<br />
iter = aux;<br />
}<br />
}<br />
//(continua...)<br />
}<br />
Cátia <strong>Vaz</strong><br />
26
Lista Duplamente Ligada-<br />
Iteradores<br />
public class DLinkedList1 implements DList {<br />
//(continuação...)<br />
private class LinkedIterator implements Iterator {<br />
// Nó dos dados retornados pelo next() seguinte.<br />
protected DNode node = head;<br />
/* Nó retornado pelo next() anterior. Como inicialmente não existiu next() referecia<br />
null. Depois de um remove() permite assinalar que não existe next() anterior.*/<br />
protected DNode prev = null;<br />
// Retorna true se existem mais elementos para iterar.<br />
public boolean hasNext() { return node != null; }<br />
// Retorna o elemento da posição corrente e avança.<br />
public E next() {<br />
if ( node == null )throw new NoSuchElementException();<br />
prev = node; node = node.next; // Avança<br />
return prev.key;<br />
}<br />
//(continua...)<br />
}<br />
Cátia <strong>Vaz</strong><br />
27
Lista Duplamente Ligada-<br />
Iteradores<br />
public class DLinkedList1 implements DList {<br />
//(continuação...)<br />
public void remove() {<br />
// Se a última operação não foi next() lança excepção<br />
if ( prev == null ) throw new IllegalStateException();<br />
// Remove o nó do elemnto retornado pelo último next<br />
DLinkedList1.this.remove(prev);<br />
prev = null; // Assinala que a operação anterior não foi um next()<br />
}<br />
}//termina a classe LinkedIterator<br />
public Iterator iterator() {return new LinkedIterator(); }<br />
protected void remove( DNode rem ){<br />
if ( rem.next != null) rem.next.prev=rem.prev;<br />
if ( rem.prev != null )<br />
rem.prev.next=rem.next;<br />
else<br />
head = rem.next;<br />
--size;<br />
}<br />
//(...)<br />
}<br />
Cátia <strong>Vaz</strong><br />
28
Lista com sentinela<br />
Inserção<br />
29
Lista com sentinela<br />
Remoção<br />
30
Lista com sentinela<br />
Pesquisa<br />
31
Lista Duplamente Ligada<br />
public interface DCList{<br />
public int size();<br />
public boolean isEmpty();<br />
}<br />
public void add(E e);<br />
public boolean remove(E e);<br />
Cátia <strong>Vaz</strong><br />
32
Lista Duplamente Ligada com<br />
Sentinela e Circular<br />
public class DLinkedList3 implements DCList{<br />
private static class DNode {<br />
public DNode next, prev;<br />
public E key;<br />
public DNode() { }<br />
public DNode(E e ) { key=e; }<br />
}<br />
private int size;<br />
protected DNode dummy;<br />
public DLinkedList3() {<br />
dummy=new DNode(); dummy.next= dummy.prev = dummy;}<br />
public int size()<br />
{ return size;}<br />
public boolean isEmpty() { return dummy.next == dummy;}<br />
//(continua...)<br />
}<br />
Cátia <strong>Vaz</strong><br />
33
Lista Duplamente Ligada com<br />
Sentinela e Circular<br />
public class DLinkedList3 implements DCList {<br />
//(continuação...)<br />
public E getFirst() { return dummy.next.key; }<br />
public E getLast() { return dummy.prev.key; }<br />
// Adiciona o elemento no fim da lista ligada<br />
public void add(E e) {<br />
DNode n=new DNode(e); ++size;<br />
n.prev=dummy.prev;<br />
n.next=dummy;<br />
dummy.prev.next=n;<br />
dummy.prev=n;<br />
}<br />
public boolean remove(E e){<br />
DNode aux=search(e);<br />
if(aux!=null){<br />
aux.next.prev=aux.prev; aux.prev.next=aux.next; return true;}<br />
return false;<br />
}<br />
//(continua..)<br />
}<br />
Cátia <strong>Vaz</strong><br />
34
Lista Duplamente Ligada com<br />
Sentinela e Circular<br />
public class DLinkedList3 implements DCList {<br />
//(continuação...)<br />
public DNode search(E e){<br />
DNode aux=dummy.next;<br />
while(aux!=dummy){<br />
if(aux.key.equals(e)){ return aux;}<br />
aux=aux.next;<br />
}<br />
return null;<br />
}<br />
//(continua...)<br />
}<br />
Cátia <strong>Vaz</strong><br />
35
Lista Duplamente Ligada com<br />
Sentinela e Circular<br />
public class DLinkedList3 implements DCList {<br />
//(...)/*Move os nós da lista 2 para a lista 1. Assume que as duas listas estão ordenadas<br />
*pela ordem dada pelo comparador. A lista 1 permanece ordenada e a lista 2 fica vazia.*/<br />
public static < E > DNode merge( DNode dummy1, DNode dummy2,<br />
Comparator cmp) {<br />
DNode head1 = dummy1.next; DNode head2 = dummy2.next;<br />
while (head1 != dummy1 && head2 != dummy2 ) {<br />
if ( cmp.compare( head1.key, head2.key)
Lista Duplamente Ligada com<br />
Sentinela e Circular<br />
public class DLinkedList3 implements DList{<br />
//(...)/*Move os nós da lista 2 para a lista 1. Assume que as duas listas estão ordenadas<br />
*pela ordem dada pelo comparador. A lista 1 permanece ordenada e a lista 2 fica vazia.*/<br />
public static < E > DNode merge( DNode dummy1, DNode dummy2,<br />
Comparator cmp) {<br />
DNode head1 = dummy1.next; DNode head2 = dummy2.next;<br />
while (head1 != dummy1 && head2 != dummy2 ) {<br />
if ( cmp.compare( head1.key, head2.key)
Exercício<br />
n Implementar o algoritmo merge sort para<br />
duas listas duplamente ligadas.<br />
☺<br />
Cátia <strong>Vaz</strong><br />
38