Visualizzazione dei risultati da 1 a 5 su 5
  1. #1
    Utente di HTML.it
    Registrato dal
    Sep 2012
    Messaggi
    4

    [C] Problema sulla distanza massima tra i nodi di un grafo

    Il problema da risolvere è il seguente.

    DISTANZA MASSIMA TRA NODI DI UN GRAFO:

    Ricordiamo che in un grafo orientato, dati due nodi s e v, si dice che v è raggiungibile da s se esiste un cammino da s a v e, in questo caso, la distanza di v da s è la lunghezza del cammino più corto da s a v:

    a - progettare un algoritmo per risolvere il seguente problema:

    dato un grafo orientato G di n nodi e m lati, e un nodo s di G, determinare l'insieme dei nodi di G raggiungibili da s che si trovano a distanza massima da s

    b - Valutare in funzione di n e m il tempo di calcolo dell'algoritmo nel caso peggiore


    La parte b) sulla valutazione del tempo l'ho già eseguita, e ho già il codice

    codice:
     #include <stdio.h>
    #include <stdlib.h>
    #include <conio.h>
    
    #define TRUE 1
    #define FALSE 0
    
    typedef short int Bool;
    
    //------GRAFO----------
    typedef struct vert
    {
    	int vertice;
       struct vert *next;
    }Vert;
    typedef Vert* pVert;
    pVert *Grafo;
    Bool *Visitato;
    int CreaGrafoOrientato();
    void Distanze(int n);
    int AmpiezzaModificata(int v,int buf[]);
    //---------------------
    
    //-----------CODA--------------
    typedef struct ele
    {
    	int vertice;
    	struct ele *next;
    }Ele;
    typedef Ele* pEle;
    void AddCoda(pEle *davanti,pEle* dietro,int item);
    int DelCoda(pEle *davanti,pEle* dietro);
    //-----------------------------
                                  //FUNZIONI AUSILIARIE
    void FreeMem(int n);       //libera la memoria delle liste di adiacenza
    pVert Inserisci(pVert t); //inserisce un lato orientato
    void *myalloc(int n);
    int Menu();
    main()
    {
       int n=0,choice;
       do
       {
          choice=Menu();
          if(choice=='1'||choice=='2'||choice=='3')
       		switch(choice)
          	{
             	case '1': //crea
                	clrscr();
                   if(n)	FreeMem(n);
                	n=CreaGrafoOrientato();
                   Visitato=(Bool*)myalloc(n*sizeof(Bool));
                   printf("\nPremi un tasto.");
                   getch();
                   break;
               	case '2': //Nodi a distanza massima per ogni nodo
                	clrscr();
                   if(n)	Distanze(n);
                   else printf("Crea il grafo prima!!!");
                   printf("\nPremi un tasto.");
                   getch();
                	break;
               	default: //termina
                	clrscr();
                	printf("Arrivederci!!");
             }
       }while(choice!='3');
       if(n)	FreeMem(n);
       free(Grafo);
    	fflush(stdin);
       getchar();
    }
    int Menu()
    {
    	//stampa il menu'
    	clrscr();
       printf("\n\t\t\tMENU");
      	printf("\n\n\t\t(1)Crea il grafo orientato\n\n");
      	printf("\t\t(2)Nodi a distanza massima\n\n");
       printf("\t\t(3)Termina\n");
       return getch();
    }
    void *myalloc(int n)
    {
    	void *p=malloc(n);
       if(!p)
       {
       	printf("\nErrore malloc!!");
          fflush(stdin);
       	getchar();
       }
       return p;
    }
    
    pVert Inserisci(pVert list,int i)
    {
    	//inserisce un vertice nella lista di adiacenza di un'altro se esso non è già presente
    	pVert temp,prev,t;
       prev=t=list;
       while(t&&t->vertice!=i)//cerca il vertice memorizzando il precedente
       {
       	prev=t;
          t=t->next;
       }
       if(!t) //non c'era quindi possiamo inserire
       {
       	temp=(pVert)myalloc(sizeof(Vert));
          temp->next=NULL;temp->vertice=i;
          if(!list)	list=temp;//la lista era vuota
          else prev->next=temp;//c'era almeno un elemento
       }
       return list;
    }
    int CreaGrafoOrientato(void)
    {
    	//E' uguale a quella usata per creare i lati nei grafi non orintati dell'eserc precedente
       //con la differenza che i lati sono orientati quindi la funzione inserisci viene
       //chiamata una sola volta (per inserire il secondo vertice nella lista del primo)
    	int a,b,n,i;
    	do
       {
    		printf("Introduci il numero di vertici del grafo (minimo uno),verranno "
    			"creati tutti i vertici con etichetta da zero al numero che hai specificato - 1:\n");
          scanf("%d",&n);
       }while(n<1);
       Grafo=(pVert *)myalloc(n*sizeof(pVert));
       for(i=0;i<n;i++) Grafo[i]=NULL;
       printf("\nOra introduci i lati del grafo come coppie  ordinate di vertici (prima il vertice di partenza dell'arco)\nPremi un tasto");
       getch();
       clrscr();
       while(1)
       {
       	clrscr();
    		printf("Introduci due interi separati da uno spazio"
                 "(uno dei valori uguale a -1 termina):\n");
          scanf("%d %d",&a,&b);
          if(a==-1||b==-1)	break;  //si vuole smettere di inserire lati
          else if(a<0||a>n-1||b<0||b>n-1)//una coppia deve essere di vertici validi
          {
          	printf("Uno o entrambi i vertici della coppia non appartengono al grafo!\n"
                    "Premi un tasto");
             continue;
          }
          Grafo[a]=Inserisci(Grafo[a],b);//crea un lato orientato
       }                                          
       return n;
    }
    
    void Distanze(int n)
    {
    	//per ogni vertice stampa i vertici a distanza massima.Le distanze dei vertici da quello
       //di partenza (ruolo svolto a tutno da tutti i vertici) sono memorizzate in 'buf' dalla
       //funzione ampiezza modificata che rende anche il valore della distanza massima
    
    	int i,j,maxdist; //maxdist riceve il valore corrispondente alla distanza massima
       int *buf=(int*)myalloc(n*sizeof(int));//viene riempito con le distanze
    	for(i=0;i<n;i++)
       	{
             for(j=0;j<n;j++) {Visitato[j]=FALSE;buf[j]=-1;}//reinizializzazione dei vettori di supporto
             maxdist=AmpiezzaModificata(i,buf);
       		if(maxdist) printf("Nodi a distanza massima(cioe' %d) da %d :\n",maxdist,i);
             else printf("Nessun vertice e' raggiungibile da %d",i);
             for(j=0;j<n;j++) if(buf[j]==maxdist)	printf("%d ",j);//stampa i vertici dell'ultimo livello
             printf("\n\n");
       	}
    }
    
    int AmpiezzaModificata(int v,int buf[])
    {
    	/*Effettua una visita in ampiezza ma senza stampare nulla, soltanto classificando i nodi
         visitati per distanza da v e memorizzando tali distanze in buf.la distanza massima+1
         rimane memorizzata nella variabile livello alla fine della visita.
         La divisione dei nodi per livello è realizzata dal ciclo while più interno.
         Il primo livello è costiuito dai noi della lista di adiacenza di v,il secondo dai
         nodi delle liste di adiacenza di ognuno di essi non ancora visitati,il terzo dai nodi
         delle liste di adiacenza di questi ultimi non ancora visitati,e così via...
         L'idea è di tenere aggionata una variabile aux che memorizzi l'ultimo vertice del
         livello corrente.La prima volta aux coincide col vertice di partenza,la seconda con
         l'ultimo vertice della sua lista di adiacenza,la terza con l'ultimo vertice della lista
         di adiacenza dell'aux precedente,e così via..
         Nel test del ciclo interno aux viene confrontato con 'v',cioè con l'ultimo vertice
         estratto dalla coda (che non vi si trova più quindi).in altre parole il ciclo while
         interno non fa che ritardare l'incremento di 'livello' a quando dalla coda viene
         estratto aux,quando ciò avviene aux viene aggiornato con 'dietro->vertice',che è proprio
         l'ultimo vertice non visitato della lista di aux (perchè v==aux è già stato estratto e i
         suoi vertici adiacenti già accodati).
         Il problema del primo confronto,che deve sempre avere v!=aux (altrimenti non si comincia
         il ciclo) viene risolto dando a v un valore non accettabile per l'immissione dei vertici
         del grafo quando lo si crea,cioè -1.
         OSSERVAZIONE:'livello' viene incrementato una volta in più perchè l'algoritmo non
         può sapere a priori di trovarsi all'ultimo livello,cioè che per l'ultimo aux estrarrà
         dalla coda solo vertici con liste di adiacenza già visitate.
       */
    	pEle davanti,dietro;
       int aux,livello=0;
       pVert w;
       davanti=dietro=NULL;
       Visitato[v]=TRUE;
       AddCoda(&davanti,&dietro,v);
       v=-1;
       while(davanti)//finchè la coda non è vuota
       {
          aux=dietro->vertice;//ultimo vertice del livello
          livello++;
         	while(v!=aux)//finchè non hai estratto l'ultimo vertice del livello
          {
          	v=DelCoda(&davanti,&dietro);
          	for(w=Grafo[v];w;w=w->next)
          		if(!Visitato[w->vertice])
             	{
                   buf[w->vertice]=livello;// memorizza il livello attuale
                	Visitato[w->vertice]=TRUE;//contrassegna come visitato
                	AddCoda(&davanti,&dietro,w->vertice);//accoda
             	}
       	}
       }
       return livello-1;//perchè livello viene necessariamente incrementato una volta in più
    }
    void FreeMem(int n)
    {
    	//libera la memoria di tutte le liste di adiacenza
    	pVert temp,t;int i;
       for(i=0;i<n;i++)
       {
       	t=Grafo[i];
       	while(t)
       	{
       		temp=t;
          	t=t->next;
          	free(temp);
       	}
          Grafo[i]=NULL;
       }
    }
    void AddCoda(pEle *davanti,pEle* dietro,int item)
    {
    	//Aggiunge a una coda implementata con una lista concatenata
       //la coda con questa implementazione non ha limiti di spazio (tutta la memoria al limite)
    	pEle p=(pEle)myalloc(sizeof(Ele));
       p->next=NULL;
       p->vertice=item;
       if(!*davanti) *davanti=p; //la coda era vuota
       else (*dietro)->next=p;//c'era almeno un elemento
       (*dietro)=p; //si aggiorna sempre dietro
    }
    int DelCoda(pEle *davanti,pEle* dietro)
    {
    	//cancella da una coda implementata con una lista concatenata
    	int item;pEle temp;
    	if(!*davanti)	return -1; //coda vuota
       item=(*davanti)->vertice;
       temp=(*davanti);
       *davanti=(*davanti)->next;//cancellazione in testa
       free(temp);
       if(!*davanti) *dietro=NULL;//non è strettamente necessario perchè l'inserimento
                                  //aggiorna sempre *dietro senza controllarlo
       return item;
    }

    Il problema è che mi da un errore di conflict types sulla funzione pVert Inserisci e non riesco a capire il perchè

    se qualcuno mi può essere d'aiuto gliene sarei grato

  2. #2
    Il problema è che la dichiari così:
    codice:
    pVert Inserisci(pVert t); //inserisce un lato orientato
    e la definisci così:
    codice:
    pVert Inserisci(pVert list,int i)
    ovvero, dichiarazione e definizione hanno una lista di parametri diverse; correggi il prototipo.
    Amaro C++, il gusto pieno dell'undefined behavior.

  3. #3
    Utente di HTML.it
    Registrato dal
    Sep 2012
    Messaggi
    4
    ok ora però mi da undefined reference to 'clrscr' per ogni volta che è inserito

    ma non dovrebbe essere presente in conio.h??

  4. #4
    Originariamente inviato da Pazz84
    ok ora però mi da undefined reference to 'clrscr' per ogni volta che è inserito

    ma non dovrebbe essere presente in conio.h??
    conio.h non è un header standard, e così pure tutte le sue funzioni... se non erro era presente in Turbo C++ o roba del genere, ma non esiste su praticamente ogni compilatore normale rilasciato negli ultimi 15 anni.
    Amaro C++, il gusto pieno dell'undefined behavior.

  5. #5
    Utente di HTML.it
    Registrato dal
    Sep 2012
    Messaggi
    4
    Ok grazie dell'aiuto
    Ho risolto usando al posto di clrscr() system("cls");

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.