Listas Encadeadas Circulares Motivao para listas duplamente encadeadas e circulares 3 LISTAS CIRCULARES Um dos inconvenientes do emprego de listas encadeadas consiste no caso de, dado um ponteiro para um n p de uma lista encadeada, no se ter acesso aos ns que precedem o n p Este inconveniente pode ser contornado com o emprego de listas circulares Listas circulares so listas encadeadas nas quais o ponteiro do ltimo n deixa de ser aterrado para apontar o primeiro n da lista 4 LISTAS CIRCULARES Uma lista circular no tem um primeiro n nem ltimo n naturais Uma conveno til apontar o ponteiro externo (tail para a lista circular) para o ltimo n, sendo o conceito de ltimo vindo de tempo de incluso O ponteiro head torna-se permanentemente aterrado e o ponteiro tail aponta o ltimo elemento da lista Outra alternativa consiste em usar apenas um ponteiro externo head
5 Listas circulares
6 Ponteiros aterrados representam listas circulares vazias Listas circulares incluso Incluso de um n com endereo apontado por tmp na frente e na retaguarda de uma lista circular apontada por tail A incluso na retaguarda uma incluso na frente seguida de tail tmp
7 tmp tmp tmp Listas circulares excluso Excluso do n da frente de uma lista circular na qual tail aponta o ltimo n com a recuperao da informao desse n em y
8 Implementao Java Listas circulares incluso na frente // frente ser o sucessor de tail
public void insertFront(Object item){ Element tmp = new Element (item, null); if (tail = null) tail = tmp; else { tmp.next = tail.next; } tail.next = tmp; }
10 Listas circulares incluso no final // frente ser o sucessor de tail // depois tail ser tail.next public void insertRear(Object item){ Element tmp = new Element (item, null); if (tail = null) tail = tmp; else { tmp.next = tail.next; } tail.next = tmp; tail = tmp; // transformar primeiro em ltimo }
11 Listas circulares excluso public void extractLast(Object item) { if (tail = null) throw new IllegalArgumentException ("item not found"); Element tmp = tail.next; item = tmp.datum; tail.next = tmp.next if (tail = tmp) tail = null; }
16 Listas Duplamente Encadeadas LISTAS DUPLAMENTE ENCADEADAS Alterando-se os ns de listas encadeadas de forma que cada n passe a contar, alm do registro de informao e do ponteiro para o sucessor, tambm um ponteiro para antecessor se obtm listas duplamente encadeadas 18 LISTAS DUPLAMENTE ENCADEADAS datum datum d a tu m datum null null Fig. 5.7 Listas duplamente encadeadas 19 LISTAS DUPLAMENTE ENCADEADAS Uma propriedade caracterstica das listas duplamente encadeadas expressa por: p.next.prev = p = p.prev.next EXEMPLO
20 LISTAS DUPLAMENTE ENCADEADAS Endereo prev datum next 100 NULL a 200 150 200 c 220 200 100 b 150 220 150 d 300 300 220 e NULL
21 Memria LISTAS DUPLAMENTE ENCADEADAS
Incluso incluso do n apontado por q direita do n apontado por p
22 LISTAS DUPLAMENTE ENCADEADAS
Excluso excluso do n apontado por q
23 Implementao Java Classe DoubleLinkedList public class DoubleLinkedList { protected Element head; // cabea protected Element tail; // cauda public final class Element { // elemento do lista Object datum; // dado do elemento ou item Element next; // ponteiro para sucessor Element prev; // ponteiro para antecessor Element(Object datum, Element next, Element prev) { // construtor this.datum = datum; this.next = next; this.prev = prev; } public Object getDatum() // obter dado { return datum; } public Element getNext() // obter sucessor { return next; } public Element getPrev() // obter antecessor { return prev; } // ... } // ... } 25 Mtodos Construtor e purge public class DoubleLinkedList { protected Element head; protected Element tail; public DoubleLinkedList () // construir uma lista {}
public void purge () // esvaziar uma lista { head = null; tail = null; } // ... } 26 Mtodos getHead, getTail e isEmpty public class DoubleLinkedList { protected Element head; protected Element tail; public Element getHead () // cabea da lista { return head; }
public Element getTail () // cauda da lista { return tail; }
public boolean isEmpty () //teste de lista vazia { return head == null; }
// ... } 27 Mtods getFirst e getLast public class DoubleLinkedList { protected Element head; protected Element tail; public Object getFirst() { // obter o primeiro elemento //da lista if(head == null) throw new ContainerEmptyException(); return head.datum; }
public Object getLast() { // obter o ltimo elemento //da lista if(tail == null) throw new ContainerEmptyException(); return tail.datum; } // ... } 28 Mtodo prepend public class DoubleLinkedList { protected Element head; protected Element tail;
// inluir o objeto item no incio da lista corrente public void prepend(Object item) { Element tmp = new Element(item, head, null); if(head == null) tail = tmp; head.prev = tmp; head = tmp; }
// ... } 29 Mtodo append public class DoubleLinkedList { protected Element head; protected Element tail;
// incluir o objeto item no final da lista corrente public void append (Object item) { Element tmp = new Element (item, null, tail); if(head == null) head = tmp; else tail.next = tmp; tail = tmp; }
// ... } 30 Mtodo assign public class DoubleLinkedList { protected Element head; protected Element tail; // a lista corrente ser uma cpia da lista list public void assign(DoubleLinkedList list) { if(list != this) { purge (); for(Element ptr = list.head; ptr != null; ptr = ptr.next) { append (ptr.datum); } } } // ... } 31 Mtodo extract (1) public class DoubleLinkedList { protected Element head; protected Element tail; // Exclui objeto item public void extract(Object item) { Element ptr = head; while(ptr != null && ptr.datum != item) { ptr = ptr.next; } if(ptr == null) throw new IllegalArgumentException ("item not found"); if(head == tail) { head = null; tail = null; }
32 Mtodo extract (2)
if(ptr == head) // exclui head { ptr.next.prev = null; head = ptr.next; } else if(ptr == tail) // exclui tail { ptr.prev.next = null; tail = ptr.prev; } else { ptr.prev.next = ptr.next; ptr.next.prev = ptr.prev; } } // fim do extract } // fim da classe DoubleLinkedList 33 Mtodo insertAfter // Inclui item depois do objeto corrente public void insertAfter(Object item) { Element tmp = new Element (item, next, this); if(tail == this){ this.next = tmp; tail = tmp; } else { this.next.prev = tmp; this.next = tmp; }
} 34 Mtodo insertBefore // Inclui item antes do objeto corrente public void insertBefore(Object item) { Element tmp = new Element(item, this, this.prev); if(head == this) { this.prev = tmp; head = tmp; } else { prev.next = tmp; this.prev = tmp; } } // ... } // ... } 35 Implementao C++ Definio das Classes DoubleLinkedList<T>
e ListElement<T> (1) template <class T> class DoubleLinkedList;
template <class T> class ListElement { T datum; ListElement* next; ListElement* prev; ListElement (T const&, ListElement*); public: T const& Datum () const; ListElement const* Next () const; ListElement const* Prev() const:
friend DoubleLinkedList<T>; }; 37 Definio das Classes DoubleLinkedList<T>
e ListElement<T> (2) template <class T> class DoubleLinkedList { ListElement<T>* head; ListElement<T>* tail; public: DoubleLinkedList (); ~DoubleLinkedList ();