26.06.2015 Views

Cátia Vaz

Cátia Vaz

Cátia Vaz

SHOW MORE
SHOW LESS

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

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!