Skip to Content

Laborator de C/C++

Un mic program care lucreaza cu arbori generalizati scris in C++, cu alocarea dinamica a memoriei

in ArboreGen.h este definita clasa ArboreGen, in ArboreGen.cpp sunt implementate metodele clasei
iar in demo1.cpp este dat un exemplu de folosire a clasei de arbore generalizat

ArboreGen.h

#pragma once

#include <string.h>

typedef struct Nod
{
	char *cheia;
	Nod *fiuPrim;
	Nod *frateDrept;
	Nod *tata;

	Nod(Nod *nodTata, char *nume)
	{
		cheia = new char[strlen(nume)+1];
		strcpy(cheia, nume);
		tata = nodTata;
		fiuPrim = frateDrept = NULL;
	}
	~Nod() { delete cheia; }
}Nod, *PNod;




class Nivel
{
private:
	typedef struct ListaNod
	{
		PNod nod;
		ListaNod *nodUrm;

		ListaNod(PNod nodNou)	{	nod = nodNou; nodUrm = NULL;	}
	}ListaNod, *PListaNod;

	PListaNod prim;
	PListaNod ultim;
public:
	Nivel()         {	prim = ultim = NULL;	}
	~Nivel()        {	Sterge();				}
	bool EsteGol()  {	return prim == NULL;	}

	void AdaugaNod(PNod nod);
	void Afiseaza();
	void Sterge();
};

class ArboreGen
{
private:
	PNod radacina;

private:
	//	functii private
	void StergeArbore(PNod rad);
	PNod PointerNod(PNod rad, char *nume);

	PNod Tata(PNod nod)         {	return nod->tata;		}
	PNod PrimulFiu(PNod nod)    {	return nod->fiuPrim;	}
	PNod FrateDrept(PNod nod)   {	return nod->frateDrept;	}
	char* Cheia(PNod nod)       {	return nod->cheia;		}

	void ParcPreordine(PNod nod);
	void ParcInordine(PNod nod);
	void ParcPostordine(PNod nod);

	void ParcNivel(PNod nod, int nivel, Nivel *nivele);
	void DrumIntern(PNod nod, int *lungime);
	void AdancimeNod(PNod nod, int *adancime);

public:
	ArboreGen(void);
	~ArboreGen(void);

public:
	PNod GetNod(char *nume)    {	return PointerNod(radacina, nume);			}
	void Sterge()              {	StergeArbore(radacina); radacina = NULL;	}

	//	parcurgerile
	void AfiseazaPreordine()   {	ParcPreordine(radacina);	}
	void AfiseazaInordine()    {	ParcInordine(radacina);		}
	void AfiseazaPostordine()  {	ParcPostordine(radacina);	}
	void AfiseazaNiveluri();

	int LungimeDrumIntern()    {	int l=0; DrumIntern(radacina, &l); return l;	}

	bool AdaugaRadacina(char *nume);
	bool AdaugaFiu(PNod tata, char *numeFiu);
	bool AdaugaFiu(char *numeTata, char *numeFiu);

	int Adancime(PNod nod);
	int Adancime(char *numeNod);
};

ArboreGen.cpp

#include "ArboreGen.h"
#include <iostream>

using namespace std;

//*********************************************************************
//	class Nivel
//*********************************************************************

void Nivel::AdaugaNod(PNod nod)
{
	PListaNod p = new ListaNod(nod);
	if(ultim)
	{
		ultim->nodUrm = p;
		ultim = p;
	}
	else
	{
		prim = ultim = p;
	}
}

void Nivel::Afiseaza()
{
	PListaNod p = prim;
	while(p)
	{
		cout<<p->nod->cheia<<", ";
		p = p->nodUrm;
	}
}

void Nivel::Sterge()
{
	PListaNod p, q;
	p = prim;
	while(p)
	{
		q = p;
		p = p->nodUrm;
		delete q;
	}
	prim = ultim = NULL;
}

//*********************************************************************
//	class ArboreGen
//*********************************************************************

ArboreGen::ArboreGen(void)
{
	radacina = NULL;
}

ArboreGen::~ArboreGen(void)
{
	Sterge();
}

//	functii private

void ArboreGen::StergeArbore(PNod rad)
{
	if(rad)
	{
		PNod p, q;
		p = rad->fiuPrim;
		while(p)
		{
			q = p;
			p = p->frateDrept;
			StergeArbore(q);
		}
		delete rad;
	}
}

PNod ArboreGen::PointerNod(PNod rad, char *nume)
{
	PNod p;
	PNod rez;
	if(rad)
	{
		//	e nodul cautat
		if(strcmp(rad->cheia, nume) == 0)
			return rad;
		//	cautam pe nivelul urmator
		p = rad->fiuPrim;
		while(p)
		{
			rez = PointerNod(p, nume);
			if(rez)
				return rez;
			p = p->frateDrept;
		}
	}
	return NULL;
}

bool ArboreGen::AdaugaRadacina(char *nume)
{
	//	verificam daca exista radacina
	if(radacina)
		return false;
	//	adaugam radacina
	//	radacina nu are tata
	radacina = new Nod(NULL, nume);
	return true;
}

bool ArboreGen::AdaugaFiu(PNod tata, char *numeFiu)
{
	//	verificam daca datele sunt valide
	if(!tata || !numeFiu)
		return false;
	//	cream un fiu nou
	PNod fiuNou = new Nod(tata, numeFiu);

	if(tata->fiuPrim)
	{
		//	tatal are cel putin un fiu
		PNod p = tata->fiuPrim;
		//	parcurgem fii sai
		while(p->frateDrept)
			p = p->frateDrept;
		//	am ajuns la ultimul fiu, care nu are frate drept
		//	adaugam frate drept
		p->frateDrept = fiuNou;
	}
	else
	{
		//	acesta e primul fiu
		tata->fiuPrim = fiuNou;
	}
	return true;
}

bool ArboreGen::AdaugaFiu(char *numeTata, char *numeFiu)
{
	PNod tata = GetNod(numeTata);
	return AdaugaFiu(tata, numeFiu);
}

void ArboreGen::ParcPreordine(PNod nod)
{
	if(nod)
	{
		//	parcurgem tatal
		cout<<nod->cheia<<", ";
		//	parcurgem fii
		PNod p = nod->fiuPrim;
		while(p)
		{
			ParcPreordine(p);
			p = p->frateDrept;
		}
	}
}

void ArboreGen::ParcInordine(PNod nod)
{
	if(nod)
	{
		PNod p = nod->fiuPrim;
		if(p)
		{
			//	parcurgem p
			ParcInordine(p);
		}

		//	parcurgem tata
		cout<<nod->cheia<<", ";
		if(p)
		{
			//	parcurgem restul fratilor
			p = p->frateDrept;
			while(p)
			{
				ParcInordine(p);
				p = p->frateDrept;
			}
		}
	}
}

void ArboreGen::ParcPostordine(PNod nod)
{
	if(nod)
	{
		//	parcurgem fii
		PNod p = nod->fiuPrim;
		while(p)
		{
			ParcPostordine(p);
			p = p->frateDrept;
		}
		//	parcurgem tatal
		cout<<nod->cheia<<", ";
	}
}

void ArboreGen::ParcNivel(PNod nod, int nivel, Nivel *nivele)
{
	if(nod)
	{
		//	adaugam nodul curent pe nivelul curent
		nivele[nivel].AdaugaNod(nod);
		PNod p = nod->fiuPrim;
		//	adaugam fii pe nivelul urmator
		while(p)
		{
			ParcNivel(p, nivel+1, nivele);
			p = p->frateDrept;
		}
	}
}

void ArboreGen::AfiseazaNiveluri()
{

	Nivel p[100];	//	aici nu e o implementare prea buna
					//	de prefereat ar fi sa avem o lista cu nivelele
					//	dar sa zicem, modific dupa daca am timp
	ParcNivel(radacina, 1, p);
	int i = 1;
	while(!p[i].EsteGol())
	{
		cout<<"Nivelul "<<i<<": ";
		p[i].Afiseaza();
		cout<<endl;
		i++;
	}
}

void ArboreGen::DrumIntern(PNod nod, int *lungime)
{
	if(nod)
	{
		//	parcurgem fii
		PNod p = nod->fiuPrim;
		while(p)
		{
			DrumIntern(p, lungime);
			p = p->frateDrept;
			(*lungime)++;
		}
	}
}

void ArboreGen::AdancimeNod(PNod nod, int *adancime)
{
	if(nod)
	{
		PNod p = nod;
		while(p)
		{
			(*adancime)++;
			p = p->tata;
		}
	}
}

int ArboreGen::Adancime(PNod nod)
{
	int adancime = 0;
	AdancimeNod(nod, &adancime);
	return adancime;
}

int ArboreGen::Adancime(char *numeNod)
{
	PNod nod = GetNod(numeNod);
	return Adancime(nod);
}

demo1.cpp

#include <iostream>
#include <fstream>

#include "ArboreGen.h"

using namespace std;

int const BUF_SIZE = 512;
char* numeFisier = "arbore.txt";



bool Citeste(char *numeFisier, ArboreGen *pArbore)
{

	ifstream fin;
	char fiu[BUF_SIZE+1];
	char tata[BUF_SIZE+1];
	int i, nrFii;

	try
	{
		fin.open(numeFisier, ios::in);
		//	citim radacina
		fin.getline(tata, BUF_SIZE);
		pArbore->Sterge();
		pArbore->AdaugaRadacina(tata);

		//	nr de fii ai radacinei
		if(fin>>nrFii)
		{
			fin.get();
			for(i=0; i<nrFii; i++)
			{
				fin.getline(fiu, BUF_SIZE);
				pArbore->AdaugaFiu(tata, fiu);
			}

			while(fin.getline(tata, BUF_SIZE))
			{
				if(strlen(tata) == 0)
					continue;
				fin>>nrFii;
				fin.get();
				for(i=0; i<nrFii; i++)
				{
					fin.getline(fiu, BUF_SIZE);
					pArbore->AdaugaFiu(tata, fiu);
				}
			}
		}
	}
	catch(ifstream::failure e)
	{
		cout<<"Eroare la citirea din fisier!\n";
		return false;
	}
	fin.close();

	return true;
}

int main()
{
	ArboreGen arbore;

	int nrFii;
	char nume[BUF_SIZE], nume1[BUF_SIZE], nume2[BUF_SIZE];
	PNod n1, n2, p, n;
	char opt;

	do
	{
		//	afiseaza meniu
		cout<<" Meniu\n V - Arbore vid\n C - Citeste din fisier arborele\n N - Vizualizeaza arborele pe niveluri\n T - Afiseaza cheile in cele 3 parcurgeri\n P - Afiseaza lungimea drumului intern\n R - Verifica stramos-descendent\n I - Info cheie\n Optiunea:";

		cin>>opt;
		//	efectueaza operatiunea
		switch(opt)
		{
		case 'v':
			arbore.Sterge();
			cout<<"Arborele a fost sters\n";
			break;
		case 'c':
			if(Citeste(numeFisier, &arbore))
				cout<<"Arborele a fost citit\n";
			break;
		case 'n':
			cout<<"Arborele pe niveluri:\n";
			arbore.AfiseazaNiveluri();
			cout<<endl;
			break;
		case 'p':
			cout<<"Lungimea drumului intern: "<<arbore.LungimeDrumIntern()<<endl;
			break;
		case 't':
			cout<<"Preordine   : ";
			arbore.AfiseazaPreordine();
			cout<<"\nInordine  : ";
			arbore.AfiseazaInordine();
			cout<<"\nPostordine: ";
			arbore.AfiseazaPostordine();
			break;
		case 'i':
			//	citim nodul
			nrFii = 0;
			cout<<"nume nod: ";
			cin>>nume;
			n = arbore.GetNod(nume);
			if(!n) break;
			//	afisare info
			if(n->tata)
				cout<<"cheie tata: "<<n->tata->cheia<<endl;
			else
				cout<<" nu are tata!\n";
			p = n->fiuPrim;
			if(p)
			{
				cout<<"cheile fiilor: ";
				while(p)
				{
					cout<<p->cheia<<", ";
					p = p->frateDrept;
					nrFii++;
				}
				cout<<endl;
			}
			else
				cout<<" nu are fii!\n";
			p = n->frateDrept;
			if(p)
			{
				cout<<"cheile fratilor: ";
				while(p)
				{
					cout<<p->cheia<<", ";
					p = p->frateDrept;
				}
				cout<<endl;
			}
			else
				cout<<" nu are frati!\n";
			cout<<"nr fii: "<<nrFii<<endl;
			cout<<"adancime: "<<arbore.Adancime(n);
			break;
		case 'r':
			cout<<"nod 1: ";
			cin>>nume1;
			cout<<"nod 2: ";
			cin>>nume2;
			n1 = arbore.GetNod(nume1);
			n2 = arbore.GetNod(nume2);
			if(n1==NULL || n2==NULL) break;
			if(n1->tata == n2)
				cout<<nume1<<" este fiul "<<nume2<<endl;
			else if(n2->tata == n1)
				cout<<nume2<<" este fiul "<<nume1<<endl;
			else
				cout<<"intre noduri nu exista nici o relatie\n";
			break;
		}
		cout<<endl;
	}
	while(opt != 'x');

	return 0;
}