[C++] ALBERO BINARIO DI RICERCA - VISTA PER LIVELLI

di il
3 risposte

[C++] ALBERO BINARIO DI RICERCA - VISTA PER LIVELLI

Salve,
avrei bisogno di un aiuto per un esercizio che sto facendo.... mi ci sto a spaccare il cervello ma non ci levo le gambe!!!!!

Devo stampare un albero binario per livelli utilizzando una lista a coda.
Nella parte dell'albero con la relativa stampa dei dati non ho avuto grossi problemi e il codice funziona, ci sono errori nella funzione Albero::StampaPerLivello() che chiama le classi Coda e NodoCoda per la creazione e l'uso della coda

La funzione StampaPerLivello crea un oggetto Coda, l'oggetto coda è una lista di oggetti tipo NodoCoda, ogni oggetto NodoCoda punta ad un oggetto Nodo dell'albero

Gli errori resi da Visual Studio sono questi:
errori.JPG
errori.JPG

Questi sotto invece sono i file.

file verifica_albero.cpp

#include<iostream>
using std::cout;
using std::cin;
using std::endl;

#include<vector>
using std::vector;

#include"Albero.h"

int main()
{
	Albero <int> leccio;
	int dato=0;
	vector<int> numeri = { 55,50,65,72,60,37,57,63,79 };
	
	for (unsigned int i = 0; i < numeri.size(); i++) leccio.inserisci(numeri[i]);
	
	leccio.stampa();
	leccio.StampaPerLivello();

	return 0;
}
file Albero.h

#pragma once
#ifndef ALBERO_H
#define ALBERO_H

#include<iostream>
using std::cout;
using std::endl;

#include"nodo.h"
#include"Coda.h"

template<typename TIPO>
class Albero
{
public:
	Albero();
	void inserisci(const TIPO &);
	void stampa();
	void StampaPerLivello();

private:
	void inserisci_nodo(const TIPO &, Nodo<TIPO> **);
	void stampa_albero(const Nodo<TIPO> *);
	Nodo<TIPO> get_nodo(const Nodo<TIPO> *);
	Nodo<TIPO> *radice_ptr;
};

template<typename TIPO>
Albero<TIPO>::Albero()
{
	radice_ptr = 0;
}

template<typename TIPO>
void Albero<TIPO>::inserisci(const TIPO &dato)
{
	inserisci_nodo(dato, &radice_ptr);
}

template<typename TIPO>
void Albero<TIPO>::inserisci_nodo(const TIPO &dato_nuovo, Nodo<TIPO> **nodo_ptr)
{
	if (*nodo_ptr == 0)	//nodo vuoto
	{
		*nodo_ptr = new Nodo<TIPO>(dato_nuovo);		//crea nuovo nodo e gli assegna il dato nuovo
	}
	else //il nodo non è vuoto
	{
		//confronta il valore del dato
		if (dato_nuovo < (*nodo_ptr)->dato)	//il dato è minore
		{
			inserisci_nodo(dato_nuovo, &((*nodo_ptr)->sx_ptr));
		}
		else if(dato_nuovo > (*nodo_ptr)->dato) //il dato è maggiore
		{
			inserisci_nodo(dato_nuovo, &((*nodo_ptr)->dx_ptr));
		}
		else
		{
			cout << "valore doppio ignoratoi" << endl;
		}
	}
}

template<typename TIPO>
void Albero<TIPO>::stampa()
{
	cout << "albero: ";
	stampa_albero(radice_ptr);
	cout << endl;
}


template<typename TIPO>
void Albero<TIPO>::stampa_albero(const Nodo<TIPO> *nodo)
{
	if (nodo != 0)
	{
		cout << nodo->get_dato() << " ";
		stampa_albero(nodo->sx_ptr);
		stampa_albero(nodo->dx_ptr);
	}
}

template<typename TIPO>
Nodo<TIPO> Albero<TIPO>::get_nodo(const Nodo<TIPO> *nodo)
{
	return nodo.get_dato();
}

template<typename TIPO>
inline void Albero<TIPO>::StampaPerLivello()
{
	Coda <NodoCoda<TIPO>*> lista;
	Nodo<TIPO>* temp = nullptr;

	lista.InserisciCoda(radice_ptr);
	cout << endl;
	while (!lista.CodaVuota())
	{
		temp = lista.PrendiCoda();
		cout << temp->dato << ' ';
		if (temp->sx_ptr != 0) lista.InserisciCoda(temp->sx_ptr);
		if (temp->dx_ptr != 0)lista.InserisciCoda(temp->dx_ptr);
	}
	cout << endl;
}

#endif
file nodo.h
#ifndef NODO_H
#define NODO_H

template<typename TIPO> class Albero;

template<typename TIPO>
class Nodo
{
friend class Albero<TIPO>;
template <typename CN> friend class CodaNodo;
template <typename C> friend class Coda;

public:
	Nodo(const TIPO &);
	TIPO get_dato() const;

private:
	TIPO dato;
	Nodo<TIPO> *sx_ptr;
	Nodo<TIPO> *dx_ptr;
};

template<typename TIPO>
Nodo<TIPO>::Nodo(const TIPO &d)
{
	dato = d;
	sx_ptr = 0;
	dx_ptr = 0;
}

template<typename TIPO>
TIPO  Nodo<TIPO>::get_dato() const
{
	return dato;
}


#endif
file Coda.h
#pragma once
#ifndef CODA_H
#define CODA_H

#include<iostream>
using std::cout;
using std::endl;

#include"NodoCoda.h"

template<typename NODOTIPO>
class Coda
{
public:
	Coda() :
		primoPtr(0),
		ultimoPtr(0) {};
	bool CodaVuota();	//verifica se la coda è vuota
	void InserisciCoda(Nodo<NODOTIPO>&);	//inserisce un nodo alla fine coda
	Nodo<NODOTIPO>* PrendiCoda();	//elimina il primo nodo della coda e restituisce il valore

	void StampaCoda();
private:
	NodoCoda<NODOTIPO>* primoPtr;
	NodoCoda<NODOTIPO>* ultimoPtr;
};




#endif // !CODA_H

template<typename NODOTIPO>
inline bool Coda<NODOTIPO>::CodaVuota()
{
	if (primoPtr == 0 and ultimoPtr == 0) return true;
	else return false;
}

template<typename NODOTIPO>
inline void Coda<NODOTIPO>::InserisciCoda(Nodo<NODOTIPO>& dato)
{
	NodoCoda<NODOTIPO>* nuovo = new NodoCoda<NODOTIPO>(dato); //crea nuovo nodo della coda
	if (primoPtr == 0 and ultimoPtr == 0)
	{
		primoPtr = nuovo;
		ultimoPtr = nuovo;
	}
	else
	{
		nuovo->nextPtr = ultimoPtr;
		ultimoPtr = nuovo;
	}
}

template<class NODOTIPO>
inline Nodo<NODOTIPO>* Coda<NODOTIPO>::PrendiCoda()
{
	NodoCoda<NODOTIPO>* temp = ultimoPtr;
	NODOTIPO* primo = &primoPtr->dato;
	while (temp->nextPtr != primoPtr) temp = temp->nextPtr;	//scorre la coda fino al penultimo elemento

	delete[] primoPtr;	//camcella area di memoria dell'elemento della coda eliminato
	primoPtr = temp;	//re-imposta il primo elemento della coda
	primoPtr->nextPtr = 0;

	return primo;
}

template<class NODOTIPO>
inline void Coda<NODOTIPO>::StampaCoda()
{
	int i = 0;
	NodoCoda<NODOTIPO>* temp = ultimoPtr;
	while (temp != 0)
	{
		i++;
		cout << endl << i << " - ptr: " << temp << "  -  nextPtr: " << temp->nextPtr << endl;
		temp = temp->nextPtr;
	}
}

file NodoCoda.h
#pragma once

#include"Nodo.h"



template<typename NODOTIPO>
class NodoCoda
{
	template<typename C> friend class Coda;

public:
	NodoCoda(const Nodo<NODOTIPO>& d) :
		dato(d),
		nextPtr(0) {};


private:
	Nodo<NODOTIPO>* dato;
	NodoCoda<NODOTIPO>* nextPtr;
};

3 Risposte

  • Re: [C++] ALBERO BINARIO DI RICERCA - VISTA PER LIVELLI

    Non sono riuscito a risolvere (dovrei vederlo tutto), però nella funzione StampaPerLivello ho notato che:
    Coda <NodoCoda<TIPO>*> lista;
    Penso andrebbe cambiato in:
    Coda <TIPO> lista;
    Dal momento che Lista fa già uso di NodoCoda, gli serve solo il TIPO del dato dell'albero.

    La funzione InserisciCoda non vuole puntatori come argomento, ma tu gli passi solo puntatori. A questo punto o cambi la funzione, o il modo di chiamarla.

    Infine, penso che il dato di NodoCoda andrebbe inizializzato così
    dato(&d)
    visto che è un puntatore, vuole un indirizzo.
  • Re: [C++] ALBERO BINARIO DI RICERCA - VISTA PER LIVELLI

    Intanto grazie della risposta....
    con i tuoi suggerimenti sono riuscito ad eliminare gli errori di compilazione ed a far girare il programma... ora devo applicarli all'esercizio completo, questa parte che ho messo l'ho snlellita parecchio per rendere il codici piu leggibile, in ogni modo grazie 1000

    Ho ragionato anche su quello che hai scritto, e ho capito gli errori che avevo fatto... unico consiglio dato che, è ok, ma non ho capito è questo:
    Infine, penso che il dato di NodoCoda andrebbe inizializzato così
    dato(&d)
    la domanda è: se il costruttore NodoCoda(Nodo<NODOTIPO>& d)della classe riceve un riferimento ad un oggetto nodo che mette nella variabile d, quando poi vado ad inizializzare il puntatore al Nodo e gli passo la variabile d, gli sto passando un riferimento di memoria che mi pare compatibile con un puntatore e quindi non necessiterebbe del &. Però se non lo metto in compilazione mi da proprio un errore. Quale errore di concetto faccio????
  • Re: [C++] ALBERO BINARIO DI RICERCA - VISTA PER LIVELLI

    xsandrox ha scritto:


    Infine, penso che il dato di NodoCoda andrebbe inizializzato così
    dato(&d)
    la domanda è: se il costruttore NodoCoda(Nodo<NODOTIPO>& d)della classe riceve un riferimento ad un oggetto nodo che mette nella variabile d, quando poi vado ad inizializzare il puntatore al Nodo e gli passo la variabile d, gli sto passando un riferimento di memoria che mi pare compatibile con un puntatore e quindi non necessiterebbe del &. Però se non lo metto in compilazione mi da proprio un errore. Quale errore di concetto faccio????
    Il riferimento non va usato come un puntatore, che è un motivo per cui si preferisce a quest'ultimo. Una volta inizializzato, dal punto di vista sintattico è come usare la variabile, quindi se vuoi il suo indirizzo (che sarà quello della variabile originale) devi usare di nuovo la &. Poi a livello di assembly può nascondere un puntatore o essere ottimizzato in altro modo.

    Puoi usare l'istruzione using per ridefinire i nomi dei tipi nel caso di complicassero a causa dei template. Si può fare nel contesto di una sola funzione, o anche in quello della classe come privato o pubblico. Es:
    
    public:
    using tipo = tipoTemplate<tipo2<T>>;
Devi accedere o registrarti per scrivere nel forum
3 risposte