Lezione 8 Ricorsione Code.

Slides:



Advertisements
Presentazioni simili
                      Insertion-Sort
Advertisements

Uso avanzato di C.
Ricorsione Procedure e funzioni ricorsive. Definizioni Un oggetto si dice ricorsivo se è definito totalmente o parzialmente in termini di sé stesso La.
Tipi di dato astratti Lista, Pila, Coda, Albero.
Estendere i linguaggi: i tipi di dato astratti
Strutture dati lineari
Procedure e funzioni ricorsive
UD 3: “Le Liste” UD 4: “Pile e Code” UD 5: “Alberi e grafi”
Strutture dati elementari
Code con priorità Ordinamento
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 1 Usa la tecnica del.
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 1 Ordinamenti ottimi.
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 1 Usa la tecnica del.
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 1 Usa la tecnica del.
Fondamenti di Informatica II Ingegneria Informatica / Automatica (A-I) Meccanica Prof. M.T. PAZIENZA a.a – 3° ciclo.
Fondamenti di Informatica II Ingegneria Informatica / Automatica (A-I) Meccanica Prof. M.T. PAZIENZA a.a – 3° ciclo.
Fondamenti di Informatica 2 Ingegneria Informatica Docente: Giovanni Macchia a.a
PROGRAMMI DI RICERCA E ORDINAMENTO
Algoritmi e strutture Dati - Lezione 7
Capitolo 4 Ordinamento Algoritmi e Strutture Dati.
Algoritmi e Strutture Dati
CORSO DI PROGRAMMAZIONE II Introduzione alla ricorsione
Progetto di algoritmi: metodologia "Divide et Impera"
07/04/2003Algoritmi Ricerca in una sequenza di elementi Data una sequenza di elementi, occorre verificare se un elemento fa parte della sequenza oppure.
Lalgoritmo MergeSort Applica la strategia del divide et impera Divide: suddivide la sequenza di n elementi data in due sottosequenze di n/2 elementi Impera:
QuickSort Quick-Sort(A,s,d) IF s < d THEN q = Partiziona(A,s,d) Quick-Sort(A,s,q-1) Quick-Sort(A,q + 1,d)
memoria gestita staticamente:
La Programmazione Ricorsiva
Elementi di programmazione ad oggetti a. a. 2009/2010 Corso di Laurea Magistrale in Ingegneria Elettronica Docente: Mauro Mazzieri, Dipartimento di Ingegneria.
30 ottobre Mergesort F. Bombi 30 ottobre 2002.
Algoritmi e Strutture Dati
Corso di informatica Athena – Periti Informatici
Complessità di un algoritmo
Teoria degli algoritmi e della computabilità Terza giornata: Ricerca e ordinamento ottimi. P vs NP, algoritmi di approssimazione, e il potere della randomizzazione.
Nota (rif. alla lezione precedente): Vector vs ArrayList Le classi generiche Vector e ArrayList sono sostanzialmente equivalenti, ma: I metodi.
Definizione di un algoritmo
Array (ordinamento) CORDA – Informatica A. Ferrari.
Esercitazioni su liste
1 FONDAMENTI DI INFORMATICA II Ingegneria Gestionale a.a ° Ciclo Pile e Code.
La ricorsione.
Heap concetti ed applicazioni. maggio 2002ASD - Heap2 heap heap = catasta condizione di heap 1.albero binario perfettamente bilanciato 2.tutte le foglie.
Esercitazione su Vector. Permette di definire collezioni di dati generiche, che sono in grado di memorizzare elementi di ogni sottotipo di Object Definito.
AlgoLab - Pile e Code Pile e code Laboratorio di Algoritmi 02/03 Prof. Ugo de’ Liguoro.
Allievi Elettrici - AA Le funzioni ricorsive in C
TECNICA DIVIDE ET IMPERA
Algoritmi e Strutture Dati Strutture Dati Elementari.
Algoritmi e Strutture Dati
Paola Disisto, Erika Griffini, Yris Noriega.  Insieme ordinato di operazioni non ambigue ed effettivamente computabili che, quando eseguito, produce.
CORSO DI PROGRAMMAZIONE II
1. 2 Ricordiamo che: La pila o stack è una struttura astratta composta da più elementi omogenei. Una pila è uno stack di dati con accessi del tipo LIFO.
1 Il linguaggio C Precisazioni sull’esperienza in laboratorio.
Algoritmi e strutture Dati - Lezione 7 1 Algoritmi di ordinamento ottimali L’algoritmo Merge-Sort ha complessità O(n log(n))  Algoritmo di ordinamento.
1 Informatica Generale Marzia Buscemi Ricevimento: Giovedì ore , Dipartimento di Informatica, stanza 306-PS o per posta.
Ordinamento dei vettori (SELECTION-SORT) Ordinamento per selezione (selection- sort) Si cerca l’elemento più piccolo e si scambia con l’elemento in posizione.
Il problema della ricerca Algoritmi e Strutture Dati.
Copyright © Istituto Italiano Edizioni Atlas
Complessità Computazionale
Problema dell’Ordinamento. Problema dell’ordinamento Formulazione del problema –Si vuole ordinare una lista di elementi secondo una data proprietà P Esempio:
Algoritmi e Strutture Dati
Capitolo 4 Ordinamento: lower bound Ω(n log n) e MergeSort ((*) l’intera lezione) Algoritmi e Strutture Dati.
Divide et Impera Parte 11 - Risoluzione di problemi per divisione in sottoproblemi “bilanciati” Corso A: Prof. Stefano Berardi
Algoritmi e Strutture Dati HeapSort. Select Sort: intuizioni L’algoritmo Select-Sort  scandisce tutti gli elementi dell’array a partire dall’ultimo elemento.
Corso di Algoritmi e Strutture Dati con Laboratorio Tipi di dato pila e coda.
Algoritmi e Strutture Dati Università di Camerino Corso di Laurea in Informatica (12 CFU) I periodo didattico Emanuela Merelli
Algoritmi e Strutture Dati Luciano Gualà
Lezione n. Parole chiave: Corso di Laurea: Insegnamento: Docente: A.A Salvatore Cuomo Strutture dati di tipo astratto 19 Strutture dati,
Rudimenti di Complessità Corso di Programmazione II Prof. Dario Catalano.
Lezione n. Parole chiave: Corso di Laurea: Insegnamento: Docente: A.A Salvatore Cuomo La ricorsione 15 Approccio ricorsivo, esercizi sulla.
1 MODULO STRUTTURE DATI FONDAMENTALI: Strutture dinamiche classe 4° INDUSTRIALE INFORMATICA Focus on.
L’algoritmo MergeSort
Transcript della presentazione:

Lezione 8 Ricorsione Code

Sommario Paradigma di programmazione Divide et Impera Ricorsione e tempo di calcolo Pile e code un ADT Pila

Ricorsione Molti algoritmi hanno una struttura ricorsiva l’algoritmo è definito in termini di se stesso un algoritmo è ricorsivo quando contiene una o più istruzioni di chiamata a se stesso le chiamate ricorsive non possono succedersi in modo infinito altrimenti l’algoritmo non terminerebbe mai deve sempre esistere una condizione di terminazione che determina quando l’algoritmo smette di richiamarsi in questo caso la computazione prosegue eseguendo un insieme di istruzioni dette passo base

Divide et Impera Paradigma di programmazione Divide et Impera Si sfrutta la soluzione ricorsiva di un problema Il procedimento è caratterizzato dai seguenti passi: Divide: suddivisione del problema in sottoprolemi Impera: soluzione ricorsiva dei sottoproblemi. Problemi piccoli sono risolti direttamente. Combina: le soluzioni dei sottoproblemi sono ricoombinate per ottenere la soluzione del problema originale

Esempio di algoritmo Divide et Impera: merge sort L’algoritmo merge sort ordina un vettore di elementi nel modo seguente: Divide: ogni sequenza di n elementi da ordinare è suddivisa in 2 sottosequenze di n/2 elementi Impera: ordina (sort) ricorsivamente le sottosequenze Combina: fonde (merge) le due sottosequenze per produrre la sequenza ordinata La condizione di terminazione si ha quando si deve ordinare una sequenza di lunghezza 1 (in quanto già ordinata)

Spiegazione intuitiva L’operazione chiave è la procedura di fusione L’idea è di fondere fra di loro due sottosequenze già ordinate (in ordine decrescente ad esempio) Si confrontano in ordine gli elementi delle due sottosequenze Si trascrive l’elemento più piccolo Si reitera il procedimento a partire dall’elemento successivo a quello già considerato

Visualizzazione del concetto di fusione Sequenze: A: 2 4 6 8 B: 1 3 5 7 R: Step di fusione: 1) B: _ 3 5 7 R: 1 2) A: _ 4 6 8 R: 1 2 3) A: _ 4 6 8 B: _ _ 5 7 R: 1 2 3 4) A: _ _ 6 8 R: 1 2 3 4 5) B: _ _ _ 7 R: 1 2 3 4 5 6) A: _ _ _ 8 B: _ _ _ 7 R: 1 2 3 4 5 6 7) B: _ _ _ _ R: 1 2 3 4 5 6 7 8) A: _ _ _ _ R: 1 2 3 4 5 6 7 8

Visualizzazione del concetto di fusione ricorsiva 1 2 2 3 4 5 6 6 2 4 5 6 1 2 3 6 2 5 4 6 1 3 2 6 5 2 4 6 1 3 2 6 Sequenza: 5 2 4 6 1 3 2 6

Pseudo Codice MERGE-SORT(A,p,r) 1 if p<r 2 then q(p+r)/2 3 MergeSort(A,p,q) 4 MergeSort(A,q+1,r) 5 Merge(A,p,q,r)

Pseudo Codice MERGE(A,p,q,r) 1 aux  A 2 i  p 3 j  q+1 4 for k  p to r 5 do if i=q+1 6 then A[k]  aux[j++] 7 else if j=r+1 8 then A[k]  aux[i++] 9 else if aux[i]<aux[j] 10 then A[k]  aux[i++] 11 else A[k]  aux[j++]

Il merge sort in C++ (l’algoritmo) typedef int Item; // tipo di ogni elemento da ordinare void merge(Item A[], int p, int q, int r) { const int MaxItems=1000; static Item aux[MaxItems]; int i,j; for (i = q+1; i > p; i--) aux[i-1] = A[i-1]; for (j = q; j < r; j++) aux[r+q-j] = A[j+1]; for (int k = p; k <= r; k++) if (aux[j] < aux[i]) A[k] = aux[j--]; else A[k] = aux[i++]; }

Nota: Si è copiata la seconda sottosequenza in ordine decrescente in modo da poter gestire il caso in cui la sequenza originale è formata da un numero dispari di elementi e quindi una sottosequenza è più piccola dell’altra in questo modo non si devono effettuare controlli sugli indici infatti quando l’indice i si riferisce ad un elemento della seconda sottosequenza (B) questa risulterà sicuramente  degli elementi di B ancora da elaborare

Il merge sort in C++ void mergesort(Item A[], int p, int r) { if (p<r) { //passo base: quando p==r int q = (r+p)/2; mergesort(A, p, q); mergesort(A, q+1, r); merge(A, p, q, r); }

Il merge sort in C++ int main() { const int N=100; Item A[N]; for (int i=0; i<N; ++i) A[i] = rand()%1000; mergesort(A,0,N-1); for (int i=0; i<N; ++i) { cout << A[i]; if ((i+1)%10==0) cout << endl; else cout << " "; } return 0;

Il merge sort in C++ (l’algoritmo con template) template <class Item> void merge(Item A[], int p, int q, int r){ const int MaxItems=1000; static Item aux[MaxItems]; int i,j; for (i = q+1; i > p; i--) aux[i-1] = A[i-1]; for (j = q; j < r; j++) aux[r+q-j] = A[j+1]; for (int k = p; k <= r; k++) if (aux[j] < aux[i]) A[k] = aux[j--]; else A[k] = aux[i++]; }

Il merge sort in C++ (l’algoritmo con template) template <class Item> void mergesort(Item A[], int p, int r){ if (p<r) { int q = (r+p)/2; mergesort(A, p, q); mergesort(A, q+1, r); merge(A, p, q, r); }

Il merge sort in C++ (l’algoritmo con template) int main(){ const int N=100; int A[N]; for (int i=0; i<N; ++i) A[i] = rand()%1000; mergesort(A,0,N-1); for (int i=0; i<N; ++i) { cout << A[i]; if ((i+1)%10==0)cout << endl; else cout << " "; } double B[N]; for (int i=0; i<N; ++i)B[i] = double(rand()%1000)/1000.0; mergesort(B,0,N-1); cout << B[i]; return 0;

Il merge sort in C++ (l’algoritmo con confronto generico) #include<iostream> #include<stdlib.h> #include <function.h> #include "Student.h" template <class Item, class Compare> void merge(Item A[], int p, int q, int r){ const int MaxItems=1000; static Item aux[MaxItems]; int i,j; Compare key_compare; // oggetto usato per il confronto for (i = q+1; i > p; i--) aux[i-1] = A[i-1]; for (j = q; j < r; j++) aux[r+q-j] = A[j+1]; for (int k = p; k <= r; k++) if (key_compare(aux[j],aux[i])) A[k] = aux[j--]; else A[k] = aux[i++]; }

Nota In <function.h> sono incluse i seguenti oggetti funzioni: template <class _Tp> struct less : public binary_function<_Tp,_Tp,bool> { bool operator()(const _Tp& __x, const _Tp& __y) const { return __x < __y; } }; // oltre a questa esistono anche (con l'ovvio significato) less_equal,greater, greater_equal, equal_to, not_equal_to

Il merge sort in C++ (l’algoritmo con confronto generico) template <class Item, class Compare> void mergesort(Item A[], int p, int r){ if (p<r) { int q = (r+p)/2; mergesort<Item,Compare>(A, p, q); mergesort<Item,Compare>(A, q+1, r); merge<Item,Compare>(A, p, q, r); }

Il merge sort in C++ (l’algoritmo con confronto generico) class BigStudent: public Student{ private: string birthplace; string birthdate; string address1; string address2; string email; // ... etc etc... public: BigStudent(int _id=0, string _name=""): Student(_id,_name) {} }; typedef BigStudent* BigStudentPtr; struct bigstudent_less{ bool operator()(const BigStudentPtr & x, const BigStudentPtr & y) const { return x->getid() < y->getid(); } 124: // Ok adesso una breve dimostrazione 125: int main() 126: { 127: const int N=5; 128: // Array di 5 studenti 129: Student A[N]; 131: // esempio di valori... 132: A[0] = Student(13, "Paolo"); 133: A[1] = Student(32, "Luca"); 134: A[2] = Student(15, "Giovanni"); 135: A[3] = Student(52, "Mario"); 136: A[4] = Student(34, "Gianni"); 138: // istanziazione del mergesort per Student con ordinamento decrescente 139: mergesort<Student, greater<Student> >(A,0,N-1); 140: for (int i=0; i<N; ++i) { 141: cout << A[i]; 142: if ((i+1)%10==0) 143: cout << endl; 144: else 145: cout << " "; 146: } 147: cout << endl; 150: // Oggetti grandi: conviene un array di puntatori!! 151: BigStudentPtr Ap[N]; 153: // esempio di valori... 154: Ap[0] = new BigStudent(13, "Paolo"); 155: Ap[1] = new BigStudent(32, "Luca"); 156: Ap[2] = new BigStudent(15, "Giovanni"); 157: Ap[3] = new BigStudent(52, "Mario"); 158: Ap[4] = new BigStudent(34, "Gianni"); 160: // istanziazione del mergesort per BigStudentPtr con ordinamento decrescente 161: mergesort<BigStudentPtr, bigstudent_less>(Ap,0,N-1); 162: for (int i=0; i<N; ++i) { 163: cout << *(Ap[i]); 164: if ((i+1)%10==0) 165: cout << endl; 166: else 167: cout << " "; 168: } 169: cout << endl; 170: 171: return 0; 172: }

Il merge sort in C++ (l’algoritmo con confronto generico) int main(){ const int N=5; Student A[N]; // Array di 5 studenti // esempio di valori... A[0] = Student(13, "Paolo"); A[1] = Student(32, "Luca"); A[2] = Student(15, "Giovanni"); A[3] = Student(52, "Mario"); A[4] = Student(34, "Gianni"); mergesort<Student, less<Student> >(A,0,N-1); for (int i=0; i<N; ++i) { cout << A[i]; if ((i+1)%10==0)cout << endl; else cout << " "; } cout << endl;

Il merge sort in C++ (l’algoritmo con confronto generico) // Oggetti grandi: conviene un array di puntatori!! BigStudentPtr Ap[N]; Ap[0] = new BigStudent(13, "Paolo"); Ap[1] = new BigStudent(32, "Luca"); Ap[2] = new BigStudent(15, "Giovanni"); Ap[3] = new BigStudent(52, "Mario"); Ap[4] = new BigStudent(34, "Gianni"); mergesort<BigStudentPtr, bigstudent_less>(Ap,0,N-1); for (int i=0; i<N; ++i) { cout << *(Ap[i]); if ((i+1)%10==0)cout << endl; else cout << " "; } cout << endl; return 0;

Il tempo di calcolo del merge sort Per semplificare l’analisi: numero di elementi da ordinare sia una potenza di 2 così per ogni applicazione del merg sort si lavora con sotto sequenze di lunghezza identica Tempo per elaborare sequenze di 1 elemento (1) quando si hanno n>1 elementi Divide: calcolo dell’indice mediano della sequenza (1) Impera: si risolvono ricorsivamente due sotto problemi di dimensione n/2, quindi 2T(n/2) Combina: il tempo di calcolo per la procedura Merge fra due sotto sequenze di n/2 elementi è (n)

Il tempo di calcolo del merge sort Si ha pertanto: T(n)= (1)+2T(n/2)+(n) = 2T(n/2)+(n) O più precisamente: T(n)=(1) per n=1 T(n)= 2T(n/2)+(n) Vedremo che T(n)= (n lg n)

Il tempo di calcolo di un algoritmo ricorsivo Per risolvere il calcolo di ricorrenze del tipo T(n)=aT(n/b)+f(n) si usa il Teorema Principale (non lo dimostreremo) Le ricorrenze del tipo indicato descrivono i tempi di calcolo di algoritmi che dividono un problema di dimensione n in a sottoproblemi di dimensione n/b risolvono i sotto problemi in tempo T(n/b) determinano come dividere e come ricomporre i sottoproblemi in un tempo f(n)

Il Teorema principale Sia T(n)=aT(n/b)+f(n) con a,b>1 e f(n) asintoticamente positiva allora T(n) può essere asintoticamente limitato se f(n)=O(nlogba-e) per qualche costante e allora T(n)=(nlogba) se f(n)=(nlogba ) allora T(n)=(nlogba lg n) se f(n)=(nlogba+e) per qualche costante e allora se af(n/b)<cf(n) per qualche c<1 e per n>n0 allora T(n)=(f(n))

Significato intuitivo Si confronta f(n) con nlogba. La soluzione è determinata dalla più grande fra le due funzioni se prevale nlogba allora la soluzione è (nlogba) cioè il tempo è dominato dalla soluzione ricorsiva dei sottoproblemi se prevale f(n) allora la soluzione è (f(n)) cioè il tempo è dominato dalle procedure di divisione e ricombinazione delle soluzioni parziali se hanno lo stesso ordine di grandezza allora la soluzione è (f(n)ln n)

Nota Cosa significa che una funzione prevale sull’altra? Nel primo caso non solo si deve avere f(n)< nlogba ma deve esserlo in modo polinomiale, cioè deve esserlo per un fattore ne per un qualche e Nel terzo caso f(n) deve essere polinomialmente più grande di nlogba e inoltre devono valere le condizioni di regolarità af(n/b)<cf(n) ATTENZIONE. Se f(n) è più piccola (o più grande) di nlogba ma non in modo polinomiale allora non si può utilizzare il teorema per risolvere la ricorrenza

Applicazione del Teorema Principale T(n)=2T(n/2)+n f(n)=n, a=2, b=2 nlogba = nlog22 =n pertanto, dato che f(n)=(nlogba )=(n) allora (caso 2) T(n)=(n lg n) T(n)=9T(n/3)+n f(n)=n, a=9, b=3 nlogba = nlog39 =n2 pertanto, dato che f(n)=O(nlogba-1)=O(n1) allora (caso 1) T(n)= (n2)

Applicazione del Teorema Principale T(n)=T(2n/3)+1 f(n)=1, a=1, b=3/2 nlogba = nlogb1 = n0 =(1) pertanto, dato che f(n)=(nlogba )=(1) allora (caso 2) T(n)= (lg n) T(n)=3T(n/4)+n lg n f(n)=n lg n, a=3, b=4 nlogba = nlog43 =n0.79.. pertanto, dato che f(n)=(nlogba+e)= (n1) allora se f(n) è regolare siamo nel caso 3 af(n/b)<cf(n) ovvero 3 n/4 lg n/4< c n lg n, ok se c=3/4 T(n)= (n lg n)

Applicazione del Teorema Principale T(n)=2T(n/2)+n lg n f(n)=n lg n, a=2, b=2 nlogba = nlog22 =n pertanto, dato che f(n) è più grande di n ovvero f(n)=(nlogba+e)= (n1) allora se f(n) è polinomialmente minore allora potremo essere nel caso 3 deve essere f(n) / nlogba > ne per qualche e ma f(n)/ nlogba =(n lg n)/n=lg n lg n è sempre minore di ne per qualsiasi e pertanto non possiamo usare il Teorema

Pile e code Pile e Code sono insiemi dinamici sono definite le operazioni di inserzione e cancellazione l’operazione di cancellazione elimina un elemento predefinito pile e code si distinguono per le politiche di eliminazione

Pila o Stack Il termine Pila (Stack) ed il nome delle operazioni di inserzione (push) e cancellazione (pop) derivano da quelli usati per descrivere le operazioni di caricamento per le pile di piatti a molla. Solo il piatto in cima può essere rimosso. Nuovi piatti vengono posti in cima. La politica di cancellazione è del tipo ultimo arrivato primo servito o LIFO (Last In First Out)

Implementazione di una Pila Una Pila si può realizzare con un vettore di n elementi S Un attributo top[S] indica la posizione dell’elemento inserito più di recente che è anche quello da cancellare quando top[S] è 0 si dice che la pila è vuota

Pseudo codice per le operazioni su Pila Stack-Empty(S) 1 if top[S]=0 2 then return TRUE 3 else return FALSE PUSH(S,x) 1 top[S] top[S]+1 2 top[S] x POP(S) 1 if not Stack-Empty(S) 2 then top[S]  top[S]-1 3 return S[top[S]+1]

Codice C++ #include <iostream> #include <cassert> using namespace std; template<class T> class ADT_Stack{ public: virtual void push(T)=0; virtual T pop()=0; };

Codice C++ template<class T> class Array_Stack: public ADT_Stack<T>{ public: Array_Stack(int usr_size=10):size(usr_size),top(0){data=new T[size];} ~Array_Stack(){delete[] data;} void push(T); T pop(); private: T * data; int size; int top; };

Codice C++ template<class T> void Array_Stack<T>::push(T item){ assert(top<size); data[top]=item; top++; } template<class T> T Array_Stack<T>::pop(){ top--; assert(top>=0); return data[top];

Codice C++ int main(){ const int DIM=10; Array_Stack<int> array_stack(DIM); int v[]={1,2,3,4,5,6,7,8,9,10,11}; ADT_Stack<int> *stack=&array_stack; for(int i=0;i<DIM;i++) stack.push(v[i]); cout<<stack.pop()<<" "; cout<<endl; return 0; }

Coda La politica di cancellazione per una coda è di tipo FIFO (First In First Out), primo arrivato primo servito, cioè il primo elemento ad essere stato inserito è anche il primo elemento ad essere eliminato La operazione di inserzione viene chiamata Enqueue e l’operazione di eliminazione Dequeue Quando un nuovo elemento viene inserito prende posto in fondo alla coda

Implementazione di una coda E’ possibile realizzare una coda con un vettore Q La coda ha attributi head[Q] e tail[Q] che rappresentano gli indici degli elementi in testa e in coda alla struttura L’attributo tail[Q] indica la posizione in cui sarà inserito il prossimo elemento Gli elementi della coda sono alle locazioni head[Q], head[Q]+1,…,tail[Q]-1 La locazione 1 segue la locazione n (ordine circolare) quando head[Q]=tail[Q] la coda è vuota quando head[Q]=tail[Q]+1 la coda è piena

Pseudocodice coda ENQUEUE(Q,x) 1 Q[tail[Q]] x 2 if tail[Q]=length[Q] 3 then tail[Q]  1 4 else tail[Q]  tail[Q]+1 DEQUEUE(x) 1 x  Q[head[Q]] 2 if head[Q]=length[Q] 3 then head[Q]  1 4 else head[Q]  head[Q]+1 5 return x

Visualizzazione operazioni su coda 1 2 3 4 5 6 7 8 9 10 5 4 3 8 head[Q]=6 tail[Q]=10 1 2 3 4 5 6 7 8 9 10 4 6 5 4 3 8 3 tail[Q]=3 Inserzione degli elementi 3,4,6 head[Q]=6 1 2 3 4 5 6 7 8 9 10 4 6 3 8 3 Cancellazione di 2 elementi tail[Q]=3 head[Q]=8