Strutture dati dinamiche

Похожие документы
Laboratorio di Programmazione

Strutture Dinamiche. Fondamenti di Informatica

Programmazione I - Laboratorio

Esercitazione 11. Liste semplici

Liste concatenate e allocazione dinamica

La struttura dati CODA

E12 Esercizi su Strutture dati dinamiche in C

Linguaggio C. Esercizio 1

PILE E CODE. Pile (stack):

Linguaggio C: Strutture e Liste Concatenate Valeria Cardellini

Strutture dati dinamiche in C (II)

Il linguaggio C. Puntatori e dintorni

Gestione dinamica della memoria

L'Allocazione Dinamica della Memoria nel linguaggio C

Inserimento in una lista ordinata

Hash Table. Hash Table

Questa soluzione va contemplata quando le lunghezze stimate dalle liste usate sono significativamente maggiori delle dimensioni di un elemento.

La Struttura Dati Lista

Esercizi Strutture dati di tipo astratto

Lezione 8 Struct e qsort

5. Quinta esercitazione autoguidata: liste semplici

Consideriamo un vettore allocato dinamicamente

Allocazione dinamica della memoria

Struct e liste concatenate

Implementazione di Liste puntate

Laboratorio di Calcolatori 1 Corso di Laurea in Fisica A.A. 2006/2007

Транскрипт:

Strutture dati dinamiche - Liste concatenate - Pile -> LIFO (last in first out) - Code -> FIFO (first in first out) - Alberi binari: gestione dati in algoritmi complessi Liste Concatenate Formata da elementi creati dinamicamente il cui numero cambia durante l esecuzione. Ogni elemento, o nodo, contiene un puntatore all elemento successivo, mentre il primo elemento, chiamato testa, contiene il puntatore alla lista. L ultimo elemento contiene come puntatore all elemento successivo il valore NULL per indicare che è la fine della lista. La lista è una struttura dati ricorsiva che viene definita utilizzando anche un puntatore a sé stesso. Per definire delle strutture dati ricorsive si usa il TAG, ovvero mette il nome dopo struct. struct nodo { int dato; struct nodo *next; ; struct nodo *newnodo; Si può dichiarare un nodo anche attraverso un tipodato (typedef): da ciò posso fare operazioni del tipo: typedef struct N { int dato; struct N *next; nodo; typedef nodo* Ptrnodo; nodo n1,n2;

La possibilità di creare un nuovo nodo per la lista in run-time (ovvero durante l esecuzione), è offerta dalla funzione malloc (memory alloc) che riceve come parametro una dimensione in bit (dimensione da riservare nella memoria dinamica del calcolatore) e ritorna un puntatore a tale spazio. Utile a questo scopo è la funzione sizeof, che riceve in ingresso un tipo di dato e ne ritorna la corrispondente dimensione in bit. L unione di queste due funzioni permette la giusta allocazione in memoria del nodo per la lista. Definito Ptrnodo un puntatore ad un nodo, l allocazione in memoria la eseguiamo nel seguente modo: Ptrnodo ptr = (Ptrnodo) malloc(sizeof(nodo)); Dopo questa istruzione la variabile ptr conterrà l indirizzo di memoria del nodo appena creato; tramite ptr è possibile quindi andare a modificare i valori del nodo stesso. Lavorando in memoria dinamica è presenta anche la funzione free che riceve in ingresso il puntatore del nodo e cancella i dati dalla memoria, liberandola. free(ptr); Sia la funzione malloc che free sono contenute nella libreria stdlib.h che va inclusa all inizio del programma. Nelle pagine successive vedremo come costruire delle funzioni necessarie alla gestione della lista a puntatori.

Creazione di un nodo: Cercare un elemento nella lista: L elemento del campo next del nodo precedente permette l accesso a quello successivo. Per fare questo si usa un secondo puntatore che inizialmente lo si fa puntare all inizio della lista e poi lo si sposta in avanti per cercare l elemento desiderato. Inserimento: - Inserimento in testa - Inserimento in coda - Inserimento ordinato int d; Ptrnodo lista, punt; //Creazione della lista, immagine precedente scanf( %d, &d); punt = lista; while(punt!=null && punt->dato!=d){ punt=punt->next; if (punt==null) { printf( Elemento non trovato ); else { printf( Elemento trovato ); Inserimento in testa: Bisogna creare un nuovo elemento quindi si ha bisogno di un puntatore a nodo, segue la creazione della variabile dinamica e la sua inizializzazione. Il campo next del nuovo elemento deve puntare al primo della lista e il puntatore list al nuovo elemento.

Ptrnodo instesta (Ptrnodo lista, int el) { Ptrnodo punt = malloc(sizeof(nodo)); punt->dato=el; punt->next=lista; return punt; Nel main o da dove è stata chiamata la funzione si fa: Ptrnodo lista1; int val; lista1=instesta(lista1, val); Inserimento in coda: Si procede in maniera quasi analoga all inserimento in testa. Ptrnodo inscoda (Ptrnodo lista, int el) { Ptrnodo punt, cur; cursore = lista; punt = malloc(sizeof(nodo)); punt->dato=el; punt->next=null; while(cur->next!=null){ cur=cur->next; cur->next=punt; Nel main o dove viene richiamata la funzione: Ptrnodo lista1; int val; lista1=inscoda(lista1, val);

Inserimento ordinato: un po più complesso, c è bisogno di un secondo puntatore di appoggio. Ptrnodo insordinato (Ptrnodo lista, int el) { Ptrnodo punt, cur, ptrprec; cur = lista; ptrprec = NULL; punt = malloc(sizeof(nodo)); punt->dato=el; while (cur!=null && el>cur->dato) { ptrprec = cur; cur = cur->next; punt->next = cur; if ( ptrprec!= NULL) { ptrprec->next=punt; else { return punt; Nel main o dove viene richiamata la funzione: Ptrnodo lista1; int val; lista1=inscoda(lista1, val); Cancellazione: Funzione unica che permette la cancellazione di un elemento ricercato nella lista. Ptrnodo cancellaelemento (Ptrnodo lista, int el) { Ptrnodo cur, ptrprec; ptrprec = NULL; for ( cur=lista; cur!=null && cur->dato!=el; cur=cur->next) { ptrprec=cur; if (cur==null) { else if (ptrprec==null) { lista = lista->next; else {

ptrprec->next=cur->next; free(cur); LISTE VISTE IN MANIERA RICORSIVA Abbiamo due casi: - Lista vuota - Un nodo più una lista È possibile definire le funzioni che gestiscono la lista in maniera ricorsiva Ptrnodo inizializzazione(void) { return NULL; int listavuota (Ptrnodo lista) { /*Restituisce 1 se vuota, 0 altrimenti*/ if (lista == NULL) { return 1; else { return 0; int dimlista (Ptrnodo lista) { if (listavuota(lista)) { return 0; else { return 1 + dimlista(lista->next); int verifica (Ptrnodo lista, int el) { if (listavuota(lista)) { return 0; if (lista->dato==el) { return 1; return verifica(lista->next, el);

Ptrnodo inscoda (Ptrnodo lista, int el) { Ptrnodo punt; if (listavuota(lista)) { punt=malloc(sizeof(nodo)); punt-> dato = el; punt-> next = NULL; return punt; else { lista->next = inscoda(lista->next, el);