Sunteți pe pagina 1din 7

1. S se adauge n fiierul arbore_binar.

h prototipuri de funcii ale cror implementare se va


gsi n fiierul arbore_binar.c i care realizeaz urmtoarele aciuni:
obinerea versiunii n oglind a arborelui;
afiarea nodurilor de pe un nivel dat din arbore;
numrarea nodurilor din arbore;
numrarea nodurilor din arbore cu un singur descendent;
afiarea celui de-al k-lea element din traversarea inordine a arborelui.
2. S se creeze un fiier antet digraf.h care conine definiia unui tip de date pentru reprezentarea
unui digraf i urmtoarele prototipuri de funcii:
// citeste datele dintr-un fisier al carui nume este dat ca parametru
void creeaza(Digraf *, char *);
// pentru un nod dat, calculeaza gradul interior
int grad_int(Digraf, int);
// pentru un nod dat, calculeaza gradul exterior
int grad_ext(Digraf, int);
// determina daca digraful dat la intrare este tare conex
int este_tare_conex(Digraf);
3. Se consider un graf G. Scriei un program care verific n timp O(N+M) dac graful G este
arbore. Aici N i M reprezint, respectiv, numrul de vrfuri i numrul de muchii din graful G.
Problema 1
/* adaugarile problemei doi */
static inline void swap(
Node * first,
Node * second)
{
Node tmp;
tmp = *first;
*first = *second;
*second = tmp;
}
void tree_mirror(Node node)
{
/**
* Pentru a crea oglinditul este
* suficient sa interschimbam fiecare
* din cei doi fii pentru fiecare nod,
* fie acestia si nuli.
*/
if (!node) // nu avem ce procesa
return;
/* radacina ramane in pozitie
doar schimbam adresele */
swap(&node->left, &node->right);
tree_mirror(node->left);
tree_mirror(node->right);

}
void tree_lvl(Node node, int lvl, int crt)
{
if (!node || crt > lvl)
return;
/* suntem pe nivelul corespunzator sau
unul mai mic si avem noduri de afisat */
if (lvl == crt)
printf("%c ", node->key);
tree_lvl(node->left, lvl, crt + 1);
tree_lvl(node->right, lvl, crt + 1);
}
int tree_cnt1(Node node)
{
if (!node)
return 0;
return 1 + tree_cnt1(node->left) +
tree_cnt1(node->right);
}
int tree_cnt2(Node node)
{
if (!node)
return 0;
// verificam cati descendenti are
int cnt = 0; // initial nu-l numaram
int des = (node->left ? 1 : 0) +
(node->right ? 1 : 0);
if (des == 1) // un descendent
cnt = 1; // deci numaram
return cnt + tree_cnt2(node->left) +
tree_cnt2(node->right);
}
void tree_kelem(Node node, const int k,
char * const chr, int firstTime)
{
static int cnt = 0;
if (firstTime)
cnt = 0;
if (!node || cnt == k)
return;
tree_kelem(node->left, k, chr, 0);
++cnt;
if (cnt == k)
*chr = node->key;
tree_kelem(node->right, k, chr, 0);
}
Problema 2

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "digraf.h"
void creeaza(Digraf * digraf, char * fname)
{
FILE * fin = fopen(fname, "r");
if (!fin) {
fprintf(stderr, "Eroare: fisierul \
nu a putut fi deschis\n");
exit(EXIT_FAILURE);
}
// citim numarul de varfuri
fscanf(fin, "%d", &digraf->nodes);
// citim numarul de arce
fscanf(fin, "%d", &digraf->edges);
/* acum pentru fiecare arc citim
perechile de noduri */
int ** l; // lista de adiacenta
l = (int **)malloc((digraf->nodes + 1) *\
sizeof(int *));
for (int i = 1; i <= digraf->nodes; ++i) {
l[i] = (int*)malloc(sizeof(int));
l[i][0] = 0;
/* ^ in primul element retinem mereu
numarul de vecini ai varfului `i` */
}
for (int i = 0; i < digraf->edges; ++i) {
int x, y;
fscanf(fin, "%d %d", &x, &y);
// nodului `x` ii adaugam vecinul `y`
l[x] = (int *)realloc(l[x], sizeof(int) *\
(1 + ++l[x][0]));
l[x][l[x][0]] = y;
}
digraf->list = l; // salvam lista
fclose(fin);
}
int grad_int(Digraf digraf, int node)
{
/**
* Pentru fiecare nod, functia citeste
* fiecare vecin si vede daca coincide
* cu varful `node`, iar daca coincide
* numaram ca intrare.
*/
int grad = 0;
for (int i = 1; i <= digraf.nodes; ++i)
for (int j = 1; j <= digraf.list[i][0]; ++j)
if (digraf.list[i][j] == node) {
++grad;
break;

}
return grad;
}
int grad_ext(Digraf digraf, int node)
{
/**
* Returneaza numarul de vecini
* ai varfului `node`.
*/
return digraf.list[node][0];
}

static void dfs(int ** list, int start,


int * seen)
{
// vizitam varful curent
seen[start] = 1;
/* vizitam toti vecinii nevizitati ai
nodului curent */
for (int i = 1; i <= list[start][0]; ++i) {
int node = list[start][i];
if (seen[node]) // daca l-am vizitat deja
continue; // verificam urmatorul vecin
// vizitam varful `node`
dfs(list, node, seen);
}
}
int este_tare_conex(Digraf digraf)
{
/**
* Pentru oricare doua noduri `u` si `v`
* se verifica daca exista drum de la unul
* la celalalt si invers.
*
* Mai simplu, pentru fiecare varf se face o
* explorare in adancime si se viziteaza cat
* mai multe varfuri, de fiecare data verificandu-se
* cate vizite unice s-au facut si pentru tare
* conexitate trebuie ca numarul de vizite sa
* coincida intotdeauna cu numarul de varfuri.
*/
size_t size = sizeof(int) * (digraf.nodes + 1);
int * seen = (int *)malloc(size);
for (int i = 1; i <= digraf.nodes; ++i) {
// reinitializam `seen`
memset(seen, 0, size);
// exploram in adancime
dfs(digraf.list, i, seen);
// numaram cate noduri am reusit a vizita
int cnt = 0;
for (int j = 1; j <= digraf.nodes; ++j)

if (seen[j])
++cnt;
if (cnt != digraf.nodes) {
free(seen);
return 0; // nu este tare conex
}
}
free(seen);
return 1; // este tare conex
}
Problema 3
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "graph.h"
// definitiile prototipurilor private
static void dfs(int **, int, int *);
void graph_create(Graph * graph, char * fname)
{
FILE * fin = fopen(fname, "r");
if (!fin) {
fprintf(stderr, "Eroare: fisierul \
nu a putut fi deschis\n");
exit(EXIT_FAILURE);
}
// citim numarul de varfuri
fscanf(fin, "%d", &graph->nodes);
// citim numarul de arce
fscanf(fin, "%d", &graph->edges);
/* acum pentru fiecare arc citim
perechile de noduri */
int ** l; // lista de adiacenta
l = (int **)malloc((graph->nodes + 1) *\
sizeof(int *));
for (int i = 1; i <= graph->nodes; ++i) {
l[i] = (int*)malloc(sizeof(int));
l[i][0] = 0;
/* ^ in primul element retinem mereu
numarul de vecini ai varfului `i` */
}
for (int i = 0; i < graph->edges; ++i) {
/* spre deosebire de graful orientat
in graful neorientat `y` este vecinul
lui `x`, dar si invers */
int x, y;
fscanf(fin, "%d %d", &x, &y);
// nodului `x` ii adaugam vecinul `y`
l[x] = (int *)realloc(l[x], sizeof(int) *\

(1 + ++l[x][0]));
l[x][l[x][0]] = y;
// acelasi lucru si pentru `y`
l[y] = (int *)realloc(l[y], sizeof(int) *\
(1 + ++l[y][0]));
l[y][l[y][0]] = x;
}
graph->list = l; // salvam lista
fclose(fin);
}
void graph_destroy(Graph * graph)
{
for (int i = 1; i <= graph->nodes; ++i)
free(graph->list[i]);
free(graph->list);
graph->nodes = 0;
graph->edges = 0;
}
int graph_is_tree(const Graph graph)
{
/**
* Functia verifica daca graful dat ca parametru
* este un arbore.
* Pentru a pastra lucrurile simple si ca executia
* algoritmului sa ia un timp liniar, ajunge sa
* verificam daca graful are N-1 muchii (unde N
* este numarul de noduri) si sa parcurgem graful
* pana vizitam toate nodurile posibile.
*
* Daca graful are mai putine muchii, atunci nu
* are cum sa fie conex, deci nu poate fi arbore.
* Daca graful are mai multe noduri, atunci cu
* siguranta contine cicluri (si poate fi conex
* sau nu), dar arborele trebuie sa fie aciclic.
*
* Daca nodurile sunt in regula, urmeaza sa le
* vizitam O(M). Daca am reusit sa le vizitam
* pe toate O(N) atunci inseamna ca avem un graf
* neorientat conex aciclic, adica un arbore,
* complexitatea finala fiind O(N+M).
*/
if (graph.nodes - 1 != graph.edges)
return 0;
size_t size = sizeof(int) * (graph.nodes + 1);
int * seen = (int *)malloc(size);
memset(seen, 0, size);
dfs(graph.list, 1, seen);
for (int i = 1; i <= graph.nodes; ++i)
if (!seen[i]) {
// opa, un nod nu a fost vizitat :)

free(seen);
return 0;
}
free(seen);
return 1; // este arbore
}
static void dfs(int ** list, int node, int * seen)
{
seen[node] = 1;
for (int i = 1; i <= list[node][0]; ++i)
if (!seen[list[node][i]])
dfs(list, list[node][i], seen);
}

S-ar putea să vă placă și