From e9a008de043988e0521d3df71f6f321c7ad6a821 Mon Sep 17 00:00:00 2001 From: Nicolas Floquet Date: Tue, 2 Mar 2021 17:03:12 +0100 Subject: [PATCH 1/6] =?UTF-8?q?2=20mars=20-=20Tout=20d=C3=A9but=20graphe?= =?UTF-8?q?=20fichier=20test=20=C3=A0=20continuer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagerank/src/test_base.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 pagerank/src/test_base.py diff --git a/pagerank/src/test_base.py b/pagerank/src/test_base.py new file mode 100644 index 0000000..efa5826 --- /dev/null +++ b/pagerank/src/test_base.py @@ -0,0 +1,27 @@ +from scipy import sparse +from numpy.random import rand + +print("On crée une matrice creuse de taille 10x10, elle est initialement vide \nAffichons la") + +A = sparse.lil_matrix((10, 10)) + +print(A) +print("Rien ne s'est passé, car j'ai affiché une matrice creuse vide\n\ +Vide donc elle n'a que des 0\n\ +Donc rien ne s'est affiché\n\ +Pour rappel les 0 d'une matrice creuse ne sont pas stockés") + +A[0, :5] = rand(5) #5 coefficients +print("Des colonnes 0 à 4 à la ligne 0, on a ajouté des valeurs au hasard") + +print(A) + +A[1, 5:7] = A[0, :2] #2 nouveaux +print("Des colonnes 5 à 7 à la ligne 1, on a ajouté des valeurs au hasard") + +print(A) + +A.setdiag(rand(10)) #9 autres +print("On ajoute des nouvelles valeurs sur toutes la diagonale avec la fonction setdiag") + +print(A) # affichage type:'creux' 26 coefficients sur 100 non nuls -- GitLab From 56d653542890f526566a40c0e47fbc7e75467748 Mon Sep 17 00:00:00 2001 From: Nicolas Floquet Date: Mon, 8 Mar 2021 22:07:19 +0100 Subject: [PATCH 2/6] Pratiquement rien 08_03_21 --- pagerank/src/Fonctions_PageRank.py | 10 ++++++++++ pagerank/src/PageRank.py | 10 ++++++++++ pagerank/test/test_base.py | 27 +++++++++++++++++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 pagerank/src/Fonctions_PageRank.py create mode 100644 pagerank/src/PageRank.py create mode 100644 pagerank/test/test_base.py diff --git a/pagerank/src/Fonctions_PageRank.py b/pagerank/src/Fonctions_PageRank.py new file mode 100644 index 0000000..f1e56a3 --- /dev/null +++ b/pagerank/src/Fonctions_PageRank.py @@ -0,0 +1,10 @@ +from scipy import sparse +from numpy.random import rand + + +def add_sommet(pagerank, URL): + #this.list_url[this.list_url.length] = url + +def add_arete(pagerank, i, j): + pagerank[i, j] = 1 + diff --git a/pagerank/src/PageRank.py b/pagerank/src/PageRank.py new file mode 100644 index 0000000..34dd495 --- /dev/null +++ b/pagerank/src/PageRank.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +class PageRank : + """Classe pour le pagerank : + -Graphe les liens (arêtes) entre les différentes URLs (sommets) + -liste_url une liste des différentes URLs (chaîne de char)""" + + def __init__(self, graphe, liste_url) : + """Constructeur PageRank""" + self.graphe = graphe + self.liste_url = liste_url diff --git a/pagerank/test/test_base.py b/pagerank/test/test_base.py new file mode 100644 index 0000000..efa5826 --- /dev/null +++ b/pagerank/test/test_base.py @@ -0,0 +1,27 @@ +from scipy import sparse +from numpy.random import rand + +print("On crée une matrice creuse de taille 10x10, elle est initialement vide \nAffichons la") + +A = sparse.lil_matrix((10, 10)) + +print(A) +print("Rien ne s'est passé, car j'ai affiché une matrice creuse vide\n\ +Vide donc elle n'a que des 0\n\ +Donc rien ne s'est affiché\n\ +Pour rappel les 0 d'une matrice creuse ne sont pas stockés") + +A[0, :5] = rand(5) #5 coefficients +print("Des colonnes 0 à 4 à la ligne 0, on a ajouté des valeurs au hasard") + +print(A) + +A[1, 5:7] = A[0, :2] #2 nouveaux +print("Des colonnes 5 à 7 à la ligne 1, on a ajouté des valeurs au hasard") + +print(A) + +A.setdiag(rand(10)) #9 autres +print("On ajoute des nouvelles valeurs sur toutes la diagonale avec la fonction setdiag") + +print(A) # affichage type:'creux' 26 coefficients sur 100 non nuls -- GitLab From 1e74f8c0b3a979b641555ec0f607f5e3773b896e Mon Sep 17 00:00:00 2001 From: Nicolas Floquet Date: Mon, 15 Mar 2021 22:05:19 +0100 Subject: [PATCH 3/6] FLOQUET_NICOLAS_Graphe_v02_C --- pagerank/src/Fonctions_PageRank.py | 10 - pagerank/src/PageRank.py | 10 - pagerank/src/graphe.c | 301 +++++++++++++++++++++++++++++ pagerank/src/graphe.h | 97 ++++++++++ pagerank/src/test_base.py | 27 --- 5 files changed, 398 insertions(+), 47 deletions(-) delete mode 100644 pagerank/src/Fonctions_PageRank.py delete mode 100644 pagerank/src/PageRank.py create mode 100644 pagerank/src/graphe.c create mode 100644 pagerank/src/graphe.h delete mode 100644 pagerank/src/test_base.py diff --git a/pagerank/src/Fonctions_PageRank.py b/pagerank/src/Fonctions_PageRank.py deleted file mode 100644 index f1e56a3..0000000 --- a/pagerank/src/Fonctions_PageRank.py +++ /dev/null @@ -1,10 +0,0 @@ -from scipy import sparse -from numpy.random import rand - - -def add_sommet(pagerank, URL): - #this.list_url[this.list_url.length] = url - -def add_arete(pagerank, i, j): - pagerank[i, j] = 1 - diff --git a/pagerank/src/PageRank.py b/pagerank/src/PageRank.py deleted file mode 100644 index 34dd495..0000000 --- a/pagerank/src/PageRank.py +++ /dev/null @@ -1,10 +0,0 @@ -# -*- coding: utf-8 -*- -class PageRank : - """Classe pour le pagerank : - -Graphe les liens (arêtes) entre les différentes URLs (sommets) - -liste_url une liste des différentes URLs (chaîne de char)""" - - def __init__(self, graphe, liste_url) : - """Constructeur PageRank""" - self.graphe = graphe - self.liste_url = liste_url diff --git a/pagerank/src/graphe.c b/pagerank/src/graphe.c new file mode 100644 index 0000000..8d752bc --- /dev/null +++ b/pagerank/src/graphe.c @@ -0,0 +1,301 @@ +#include +#include +#include "graphe.h" + + + +/** Fonction qui crée un graphe vide qui sera stocké à l'adresse g déjà allouée + * @param g un pointeur vers un graphe alloué en mémoire + * @param n le nombre strictement positif de cases des tableaux du graphe + * @requires n > 0 + * @return 0 si le graphe a été créé et -1 si n <= 0 et -2 s'il y a eu une erreur d'allocation + * O(n) + */ +int creer_graphe(graphe* g, int n) +{ + int i; + if(n <= 0) + { + printf("Erreur paramètre creer_graphe, n <= 0"); + return -1; + } + if(!(g->ligne = (int*) malloc(sizeof(int) * n))) + { + printf("Erreur allocation creer_graphe, g->ligne"); + return -2; + } + if(!(g->col = (int*) malloc(sizeof(int) * n))) + { + printf("Erreur allocation creer_graphe, g->col"); + free(g->ligne); + return -2; + } + g->max = n; + g->premierVide = 0; + for(i = 0; i < n; i++) + { + //printf("%d\n", i); + g->ligne[i] = -1; + g->col[i] = -1; + } + return 0; +} + + + +/** Libère la mémoire allouée dans un graphe, mais pas le graphe lui même (le pointeur donné en paramètre reste à libérer + * @param g un pointeur vers un graphe alloué en mémoire + */ +void graphe_detruire(graphe* g) +{ + if(g) + { + free(g->ligne); + free(g->col); + } +} + +/** Renvoie la taille maximale actuelle des tableaux du graphe g + * @param g un pointeur vers un graphe alloué en mémoire + * @return g->max un entier + * O(1) + */ +int get_max(graphe* g) +{ + return g->max; +} + + +/** Renvoie l'indice du premier (-1 -1) dans le graphe + * @param g un pointeur vers un graphe alloué en mémoire + * @return g->premierVide un entier + * O(1) + */ +int get_premier_vide(graphe* g) +{ + return g->premierVide; +} + + +/** Renvoie le plus grand indice des sommets du graphe + * @param g un pointeur vers un graphe alloué en mémoire + * @return un entier + * O(n) + */ +int get_plus_grand_sommet(graphe* g) +{ + int i, tmp, res = -1; + if(g) + { + for(i = 0; i < get_max(g); i++) + { + tmp = max(g->ligne[i], g->col[i]); + if(tmp > res) + { + res = tmp; + } + } + } + return res; +} + + +/** Ajoute une arête entre les sommets i et j du graphe + * @param g un pointeur vers un graphe alloué en mémoire + * @param i un des sommets de l'arête + * @param j un des sommets de l'arête + */ +void ajouter_arete(graphe *g, int i, int j) +{ + if(g) + { + if(get_premier_vide(g) == get_max(g)) + { + g->max *= 2; + g->ligne = realloc(g->ligne, g->max * sizeof(int)); + g->col = realloc(g->col, g->max * sizeof(int)); + for(int i = get_premier_vide(g); i < get_max(g); i++) + { + g->ligne[i] = -1; + g->col[i] = -1; + } + } + g->ligne[get_premier_vide(g)] = i; + g->col[get_premier_vide(g)] = j; + g->premierVide++; + } + //printf("ajouter_arete dans un graphe vide\n"); +} + + +/** Supprime une arête entre les sommets i et j du graphe (ou j et i) + * @param g un pointeur vers un graphe alloué en mémoire + * @param i un des sommets de l'arête + * @param j un des sommets de l'arête + * O(n) + */ +void supprimer_arete(graphe *g, int i, int j) +{ + if(g) + { + int cpt, flag = 0; + for(cpt = 0; cpt < get_premier_vide(g); cpt++) + { + if(flag) + { //On a trouvé l'arête et on l'a enlevée, donc maintenant il suffit de décaler le reste d'une case à gauche + g->ligne[cpt] = g->ligne[cpt+1]; + g->col[cpt] = g->col[cpt+1]; + } + else + { + if((g->ligne[cpt] == i && g->col[cpt] == j) || (g->ligne[cpt] == j && g->col[cpt] == i)) + { + flag = 1; + g->ligne[cpt] = g->ligne[cpt+1]; + g->col[cpt] = g->col[cpt+1]; + } + } + } + if(flag) + { + g->premierVide--; + } + } + //printf("ajouter_arete dans un graphe vide\n"); +} + + +/** Retire un sommet du graphe, assure qu'aucun sommet n'a d'arête allant vers ce dernier et qu'aucune arête ne part de celui ci. + * Puis les sommets supérieurs sont renommés, ex : si x = 5, 6->5, 7->6 etc + * @param g un pointeur vers un graphe alloué en mémoire + * @param x le sommet à retirer + * O(n) + */ +void retirer_sommet(graphe* g, int x) +{ + if(g) + { + int n = get_plus_grand_sommet(g), i; + if(x >= 0 && x < n) + { + int nbCasesVides = 0, *casesVides = (int*) calloc(sizeof(int), get_max(g)); + if(!casesVides) + { + printf("Erreur allocation retirer_sommet (tableau casesVides)\n"); + return; + } + for(i=0; i < get_max(g); i++) + { + casesVides[i]--; + } + for(i=0; i < get_max(g); i++) + { + if(g->ligne[i] == x || g->col[i] == x) + { //Une arête part de x, ou arrive en x, on retire le sommet donc tout part + g->ligne[i] = -1; + g->col[i] = -1; + casesVides[nbCasesVides++] = i; + } + else + { // Rien n'est supprimé, mais les indices des sommets > x sont décrémentés + if(g->ligne[i] > x) + { + g->ligne[i]--; + } + if(g->col[i] > x) + { + g->col[i]--; + } + } + } + g->premierVide -= nbCasesVides; + //Maintenant on a aucune trace du sommet x, mais plein de (-1 -1) où il était (ATTENTION ON PEUT ENCORE VOIR DES SOMMETS X, MAIS CE SONT LES ANCIENS SOMMETS X+1, CECI N'EST PAS UN BUG, NE PAS DÉBUGGER) + //Il faut retasser tout ça + + for(i = get_max(g) - 1; i >= 0 && nbCasesVides; i--) + { + if(g->ligne[i] != -1) + { //Pas une case vide, donc on peut l'échanger avec une case vide + g->ligne[casesVides[nbCasesVides-1]] = g->ligne[i]; + g->col[casesVides[nbCasesVides-1]] = g->col[i]; + nbCasesVides--; + g->ligne[i] = -1; + g->col[i] = -1; + } + } + free(casesVides); + } + //printf("retirer_sommet hors limites [0; n-1]\n"); + } + //printf("retirer_sommet dans un graphe vide\n"); +} + + +void graphe_afficher(graphe* g) +{ + if(g) + { + printf("Graphe à %d arêtes\n", get_premier_vide(g)); + int lim = get_plus_grand_sommet(g)+1, i, v, w; + int* matrice = (int*) calloc(sizeof(int), lim * lim); + if(!matrice) + { + printf("Erreur allocation graphe_afficher \n"); + return; + } + for(i = 0; i < g->premierVide; i++) + { + matrice[g->ligne[i] * lim + g->col[i]]++; + matrice[g->col[i] * lim + g->ligne[i]]++; + } + /* matrice d'adjacence faite */ + /* ligne indices colonnes */ + printf("\t\t"); + for (w = 0 ; w < lim ; w++) + { + printf("%d\t", w); + } + printf("\n"); + + printf("\t\t"); + for (w = 0 ; w < lim ; w++) + { + printf("_\t"); + } + printf("\n"); + + /* lignes de la matrice */ + for (v = 0 ; v < lim ; v++) + { + printf("%d\t|\t", v); + for (w = 0 ; w < lim ; w++) + { + printf("%d\t", matrice[v * lim + w]); + } + printf("|\n"); + } + printf("\t\t"); + for (w = 0 ; w < lim ; w++) + { + printf("_\t"); + } + printf("\n"); + free(matrice); + } + else + { + printf("Erreur graphe_afficher Le graphe est NULL\n"); + } +} + + +/** Renvoie le maximum entre 2 entiers + * @param x un entier + * @param y un entier + * @return un entier, le plus grand des 2 paramètres + * O(1) + */ +int max(int x, int y) +{ + return (x > y) ? x : y; +} diff --git a/pagerank/src/graphe.h b/pagerank/src/graphe.h new file mode 100644 index 0000000..d94e477 --- /dev/null +++ b/pagerank/src/graphe.h @@ -0,0 +1,97 @@ +#ifndef GRAPHE_H +#define GRAPHE_H + + +struct s_graphe { + int max; // Longueur de chacun des tableaux + int premierVide; // Indice du premier (-1 -1) + int *ligne; // Indices i {-1 si non défini, entre 0 et n-1 sinon} + int *col; // Indices j {-1 si non défini, entre 0 et n-1 sinon} +}; +typedef struct s_graphe graphe; + +/** Fonction qui crée un graphe vide qui sera stocké à l'adresse g déjà allouée + * @param g un pointeur vers un graphe alloué en mémoire + * @param n le nombre strictement positif de cases des tableaux du graphe + * @requires n > 0 + * @return 0 si le graphe a été créé et -1 si n <= 0 et -2 s'il y a eu une erreur d'allocation + * O(n) + */ +int creer_graphe(graphe* g, int n); + + +/** Libère la mémoire allouée dans un graphe, mais pas le graphe lui même (le pointeur donné en paramètre reste à libérer + * @param g un pointeur vers un graphe alloué en mémoire + * O(n); + */ +void graphe_detruire(graphe* g); + + +/** Renvoie la taille maximale actuelle des tableaux du graphe g + * @param g un pointeur vers un graphe alloué en mémoire + * @return g->max un entier + * O(1) + */ +int get_max(graphe* g); + + +/** Renvoie l'indice du premier (-1 -1) dans le graphe + * @param g un pointeur vers un graphe alloué en mémoire + * @return g->premierVide un entier + * O(1) + */ +int get_premier_vide(graphe* g); + + +/** Renvoie le plus grand indice des sommets du graphe + * @param g un pointeur vers un graphe alloué en mémoire + * @return un entier + * O(n) + */ +int get_plus_grand_sommet(graphe* g); + + +/** Ajoute une arête entre les sommets i et j du graphe + * @param g un pointeur vers un graphe alloué en mémoire + * @param i un des sommets de l'arête + * @param j un des sommets de l'arête + * O(1) + */ +void ajouter_arete(graphe *g, int i, int j); + + +/** Supprime une arête entre les sommets i et j du graphe + * @param g un pointeur vers un graphe alloué en mémoire + * @param i un des sommets de l'arête + * @param j un des sommets de l'arête + * O(n) + */ +void supprimer_arete(graphe *g, int i, int j); + + +/** Retire un sommet du graphe, assure qu'aucun sommet n'a d'arête allant vers ce dernier et qu'aucune arête ne part de celui ci. + * Puis les sommets supérieurs sont renommés, ex : si x = 5, 6->5, 7->6 etc + * @param g un pointeur vers un graphe alloué en mémoire + * @param x le sommet à retirer + * O(n) + */ +void retirer_sommet(graphe* g, int x); + + +void graphe_afficher(graphe* g); + + +/** Renvoie le maximum entre 2 entiers + * @param x un entier + * @param y un entier + * @return un entier, le plus grand des 2 paramètres + * O(1) + */ +int max(int x, int y); + + +//afficher tableaux +//2 sommets sont-ils connectés? (valeur > 0) + + +#endif diff --git a/pagerank/src/test_base.py b/pagerank/src/test_base.py deleted file mode 100644 index efa5826..0000000 --- a/pagerank/src/test_base.py +++ /dev/null @@ -1,27 +0,0 @@ -from scipy import sparse -from numpy.random import rand - -print("On crée une matrice creuse de taille 10x10, elle est initialement vide \nAffichons la") - -A = sparse.lil_matrix((10, 10)) - -print(A) -print("Rien ne s'est passé, car j'ai affiché une matrice creuse vide\n\ -Vide donc elle n'a que des 0\n\ -Donc rien ne s'est affiché\n\ -Pour rappel les 0 d'une matrice creuse ne sont pas stockés") - -A[0, :5] = rand(5) #5 coefficients -print("Des colonnes 0 à 4 à la ligne 0, on a ajouté des valeurs au hasard") - -print(A) - -A[1, 5:7] = A[0, :2] #2 nouveaux -print("Des colonnes 5 à 7 à la ligne 1, on a ajouté des valeurs au hasard") - -print(A) - -A.setdiag(rand(10)) #9 autres -print("On ajoute des nouvelles valeurs sur toutes la diagonale avec la fonction setdiag") - -print(A) # affichage type:'creux' 26 coefficients sur 100 non nuls -- GitLab From a1f26453360e871da94668e5db39ec5203b9e2d5 Mon Sep 17 00:00:00 2001 From: Nicolas Floquet Date: Mon, 15 Mar 2021 22:07:17 +0100 Subject: [PATCH 4/6] FLOQUET_NICOLAS_Graphe_v03_avec_test_graphe --- pagerank/test/Makefile | 12 ++++++++++++ pagerank/test/test-graphe.c | 39 +++++++++++++++++++++++++++++++++++++ pagerank/test/test_base.py | 27 ------------------------- 3 files changed, 51 insertions(+), 27 deletions(-) create mode 100644 pagerank/test/Makefile create mode 100644 pagerank/test/test-graphe.c delete mode 100644 pagerank/test/test_base.py diff --git a/pagerank/test/Makefile b/pagerank/test/Makefile new file mode 100644 index 0000000..2abbb88 --- /dev/null +++ b/pagerank/test/Makefile @@ -0,0 +1,12 @@ +CC= gcc +CXXFLAGS= -Wall --pedantic -O3 + +CPP_O_FILE = test-graphe.o +LIB = -lm + + +all: $(CPP_O_FILE) + $(CC) $(CXXFLAGS) -o test-graphe.exe test-graphe.c ../src/graphe.c $(LIB) + +clean: + rm -rf *.o *.exe diff --git a/pagerank/test/test-graphe.c b/pagerank/test/test-graphe.c new file mode 100644 index 0000000..9377a34 --- /dev/null +++ b/pagerank/test/test-graphe.c @@ -0,0 +1,39 @@ +#include +#include +#include "../src/graphe.h" + +#define NB_SOMMETS 7 + +int main() +{ + graphe g; + creer_graphe(&g, NB_SOMMETS); + ajouter_arete(&g, 0, 1); + ajouter_arete(&g, 0, 9); + ajouter_arete(&g, 1, 3); + ajouter_arete(&g, 1, 2); + ajouter_arete(&g, 1, 4); + ajouter_arete(&g, 2, 4); + ajouter_arete(&g, 3, 4); + ajouter_arete(&g, 3, 5); + ajouter_arete(&g, 4, 5); + ajouter_arete(&g, 4, 6); + ajouter_arete(&g, 5, 6); + + graphe_afficher(&g); + + printf("Retirons le sommet 4 (un nouveau sommet 4 prendra sa place\n"); + + retirer_sommet(&g, 4); + + printf("Retirons les arêtes 4-5, 1-3, et 5-4 (déjà retirée)\n"); + supprimer_arete(&g, 4, 5); + graphe_afficher(&g); + supprimer_arete(&g, 1, 3); + graphe_afficher(&g); + supprimer_arete(&g, 5, 4); + graphe_afficher(&g); + + graphe_detruire(&g); + return EXIT_SUCCESS; +} diff --git a/pagerank/test/test_base.py b/pagerank/test/test_base.py deleted file mode 100644 index efa5826..0000000 --- a/pagerank/test/test_base.py +++ /dev/null @@ -1,27 +0,0 @@ -from scipy import sparse -from numpy.random import rand - -print("On crée une matrice creuse de taille 10x10, elle est initialement vide \nAffichons la") - -A = sparse.lil_matrix((10, 10)) - -print(A) -print("Rien ne s'est passé, car j'ai affiché une matrice creuse vide\n\ -Vide donc elle n'a que des 0\n\ -Donc rien ne s'est affiché\n\ -Pour rappel les 0 d'une matrice creuse ne sont pas stockés") - -A[0, :5] = rand(5) #5 coefficients -print("Des colonnes 0 à 4 à la ligne 0, on a ajouté des valeurs au hasard") - -print(A) - -A[1, 5:7] = A[0, :2] #2 nouveaux -print("Des colonnes 5 à 7 à la ligne 1, on a ajouté des valeurs au hasard") - -print(A) - -A.setdiag(rand(10)) #9 autres -print("On ajoute des nouvelles valeurs sur toutes la diagonale avec la fonction setdiag") - -print(A) # affichage type:'creux' 26 coefficients sur 100 non nuls -- GitLab From 3541ccdf382ae86b74d6ba3a80658d00edc6d86e Mon Sep 17 00:00:00 2001 From: Nicolas Floquet Date: Fri, 19 Mar 2021 22:00:22 +0100 Subject: [PATCH 5/6] =?UTF-8?q?Graphe=20et=20Liste=5FURL=20suite=20PageRan?= =?UTF-8?q?k=20d=C3=A9but?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagerank/src/graphe.c | 196 +++++++++++++++++++++++++++----- pagerank/src/graphe.h | 66 +++++++++-- pagerank/src/liste_url.c | 216 ++++++++++++++++++++++++++++++++++++ pagerank/src/liste_url.h | 95 ++++++++++++++++ pagerank/src/pagerank.c | 153 +++++++++++++++++++++++++ pagerank/src/pagerank.h | 72 ++++++++++++ pagerank/test/Makefile | 3 +- pagerank/test/test-graphe.c | 49 +++++--- pagerank/test/test-liste.c | 29 +++++ 9 files changed, 825 insertions(+), 54 deletions(-) create mode 100644 pagerank/src/liste_url.c create mode 100644 pagerank/src/liste_url.h create mode 100644 pagerank/src/pagerank.c create mode 100644 pagerank/src/pagerank.h create mode 100644 pagerank/test/test-liste.c diff --git a/pagerank/src/graphe.c b/pagerank/src/graphe.c index 8d752bc..b01e43f 100644 --- a/pagerank/src/graphe.c +++ b/pagerank/src/graphe.c @@ -16,17 +16,17 @@ int creer_graphe(graphe* g, int n) int i; if(n <= 0) { - printf("Erreur paramètre creer_graphe, n <= 0"); + printf("Erreur paramètre creer_graphe, n <= 0\n"); return -1; } if(!(g->ligne = (int*) malloc(sizeof(int) * n))) { - printf("Erreur allocation creer_graphe, g->ligne"); + printf("Erreur allocation creer_graphe, g->ligne\n"); return -2; } if(!(g->col = (int*) malloc(sizeof(int) * n))) { - printf("Erreur allocation creer_graphe, g->col"); + printf("Erreur allocation creer_graphe, g->col\n"); free(g->ligne); return -2; } @@ -55,12 +55,13 @@ void graphe_detruire(graphe* g) } } + /** Renvoie la taille maximale actuelle des tableaux du graphe g * @param g un pointeur vers un graphe alloué en mémoire * @return g->max un entier * O(1) */ -int get_max(graphe* g) +int graphe_get_max(graphe* g) { return g->max; } @@ -71,23 +72,58 @@ int get_max(graphe* g) * @return g->premierVide un entier * O(1) */ -int get_premier_vide(graphe* g) +int graphe_get_premier_vide(graphe* g) { return g->premierVide; } +/** Indique si un sommet est dans le graphe + * @param g un pointeur vers un graphe alloué en mémoire + * @param u un entier, le sommet dont on veut savoir s'il est dans le graphe + * @return 1 si le sommet est dans le graphe et 0 sinon + * O(n) + */ +int graphe_contains(graphe* g, int u) +{ + return (graphe_find(g, u) != -1); +} + + +/** Donne l'indice de la première occurence d'un sommet dans le graphe + * @param g un pointeur vers un graphe alloué en mémoire + * @param u un entier, le sommet dont on veut connaître l'indice dans le graphe + * @return l'indice de le sommet si il est dans le graphe et -1 sinon + * O(n) + */ +int graphe_find(graphe* g, int u) +{ + if(g && u >= 0 && u <= graphe_get_plus_grand_sommet(g)) + { + int i; + for(i = 0; i < graphe_get_premier_vide(g); i++) + { + if(g->ligne[i] == u || g->col[i] == u) + { + return i; + } + } + } + return -1; +} + + /** Renvoie le plus grand indice des sommets du graphe * @param g un pointeur vers un graphe alloué en mémoire * @return un entier * O(n) */ -int get_plus_grand_sommet(graphe* g) +int graphe_get_plus_grand_sommet(graphe* g) { int i, tmp, res = -1; if(g) { - for(i = 0; i < get_max(g); i++) + for(i = 0; i < graphe_get_max(g); i++) { tmp = max(g->ligne[i], g->col[i]); if(tmp > res) @@ -105,26 +141,26 @@ int get_plus_grand_sommet(graphe* g) * @param i un des sommets de l'arête * @param j un des sommets de l'arête */ -void ajouter_arete(graphe *g, int i, int j) +void graphe_ajouter_arete(graphe* g, int i, int j) { if(g) { - if(get_premier_vide(g) == get_max(g)) + if(graphe_get_premier_vide(g) == graphe_get_max(g)) { g->max *= 2; g->ligne = realloc(g->ligne, g->max * sizeof(int)); g->col = realloc(g->col, g->max * sizeof(int)); - for(int i = get_premier_vide(g); i < get_max(g); i++) + for(int i = graphe_get_premier_vide(g); i < graphe_get_max(g); i++) { g->ligne[i] = -1; g->col[i] = -1; } } - g->ligne[get_premier_vide(g)] = i; - g->col[get_premier_vide(g)] = j; + g->ligne[graphe_get_premier_vide(g)] = i; + g->col[graphe_get_premier_vide(g)] = j; g->premierVide++; } - //printf("ajouter_arete dans un graphe vide\n"); + //printf("graphe_ajouter_arete dans un graphe vide\n"); } @@ -134,12 +170,12 @@ void ajouter_arete(graphe *g, int i, int j) * @param j un des sommets de l'arête * O(n) */ -void supprimer_arete(graphe *g, int i, int j) +void graphe_supprimer_arete(graphe* g, int i, int j) { if(g) { int cpt, flag = 0; - for(cpt = 0; cpt < get_premier_vide(g); cpt++) + for(cpt = 0; cpt < graphe_get_premier_vide(g); cpt++) { if(flag) { //On a trouvé l'arête et on l'a enlevée, donc maintenant il suffit de décaler le reste d'une case à gauche @@ -161,7 +197,7 @@ void supprimer_arete(graphe *g, int i, int j) g->premierVide--; } } - //printf("ajouter_arete dans un graphe vide\n"); + //printf("graphe_supprimer_arete dans un graphe vide\n"); } @@ -171,24 +207,24 @@ void supprimer_arete(graphe *g, int i, int j) * @param x le sommet à retirer * O(n) */ -void retirer_sommet(graphe* g, int x) +void graphe_retirer_sommet(graphe* g, int x) { if(g) { - int n = get_plus_grand_sommet(g), i; + int n = graphe_get_plus_grand_sommet(g), i; if(x >= 0 && x < n) { - int nbCasesVides = 0, *casesVides = (int*) calloc(sizeof(int), get_max(g)); + int nbCasesVides = 0, *casesVides = (int*) calloc(sizeof(int), graphe_get_max(g)); if(!casesVides) { - printf("Erreur allocation retirer_sommet (tableau casesVides)\n"); + printf("Erreur allocation graphe_retirer_sommet (tableau casesVides)\n"); return; } - for(i=0; i < get_max(g); i++) + for(i=0; i < graphe_get_max(g); i++) { casesVides[i]--; } - for(i=0; i < get_max(g); i++) + for(i=0; i < graphe_get_max(g); i++) { if(g->ligne[i] == x || g->col[i] == x) { //Une arête part de x, ou arrive en x, on retire le sommet donc tout part @@ -212,7 +248,7 @@ void retirer_sommet(graphe* g, int x) //Maintenant on a aucune trace du sommet x, mais plein de (-1 -1) où il était (ATTENTION ON PEUT ENCORE VOIR DES SOMMETS X, MAIS CE SONT LES ANCIENS SOMMETS X+1, CECI N'EST PAS UN BUG, NE PAS DÉBUGGER) //Il faut retasser tout ça - for(i = get_max(g) - 1; i >= 0 && nbCasesVides; i--) + for(i = graphe_get_max(g) - 1; i >= 0 && nbCasesVides; i--) { if(g->ligne[i] != -1) { //Pas une case vide, donc on peut l'échanger avec une case vide @@ -225,18 +261,82 @@ void retirer_sommet(graphe* g, int x) } free(casesVides); } - //printf("retirer_sommet hors limites [0; n-1]\n"); + //printf("graphe_retirer_sommet hors limites [0; n-1]\n"); + } + //printf("graphe_retirer_sommet dans un graphe vide\n"); +} + + +/** Indique si 2 sommets sont adjacents ou non, s'il existe une arête les reliant + * @param g un pointeur vers un graphe alloué en mémoire + * @param u un des sommets de l'arête + * @param v un des sommets de l'arête + * @return 1 si les sommets sont adjacents et 0 sinon + * O(n) + */ +int graphe_voisins(graphe* g, int u, int v) +{ + if(g) + { + int max = graphe_get_plus_grand_sommet(g); + if(u >= 0 && v >= 0 && u <= max && v <= max) + { + int i; + for(i = 0; i < graphe_get_premier_vide(g); i++) + { + if(g->ligne[i] == u && g->col[i] == v) + { + return 1; + } + if(g->ligne[i] == v && g->col[i] == u) + { + return 1; + } + } + } + } + return 0; +} + + +/** Indique si 1 sommet est successeur d'un autre ou non + * @param g un pointeur vers un graphe alloué en mémoire + * @param u un des sommets de l'arête + * @param v un des sommets de l'arête + * @return 1 si v est un successeur de u et 0 sinon + * O(n) + */ +int graphe_est_succ(graphe* g, int u, int v) +{ + if(g) + { + int max = graphe_get_plus_grand_sommet(g); + if(u >= 0 && v >= 0 && u <= max && v <= max) + { + int i; + for(i = 0; i < graphe_get_premier_vide(g); i++) + { + if(g->ligne[i] == u && g->col[i] == v) + { + return 1; + } + } + } } - //printf("retirer_sommet dans un graphe vide\n"); + return 0; } +/** Affiche le graphe sous la forme d'une matrice d'adjacence + * @param g un pointeur vers un graphe alloué en mémoire + * O(n) + */ void graphe_afficher(graphe* g) { if(g) { - printf("Graphe à %d arêtes\n", get_premier_vide(g)); - int lim = get_plus_grand_sommet(g)+1, i, v, w; + printf("Graphe à %d arêtes\n", graphe_get_premier_vide(g)); + int lim = graphe_get_plus_grand_sommet(g)+1, i, v, w; int* matrice = (int*) calloc(sizeof(int), lim * lim); if(!matrice) { @@ -289,6 +389,48 @@ void graphe_afficher(graphe* g) } +/** Affiche le graphe sous la forme des 2 tableaux le composant + * @param g un pointeur vers un graphe alloué en mémoire + * O(n) + */ +void graphe_afficher_tableaux(graphe* g) +{ + int i; + printf("\n======================"); + printf("\nIndices\t\t"); + for (i = 0; i < graphe_get_max(g); i++) + { + printf("| %2d ", i); + } + printf("\n\nlignes :\t"); + for (i = 0; i < graphe_get_max(g); i++) + { + if(i < graphe_get_premier_vide(g)) + { + printf("| %2d ", g->ligne[i]); + } + else + { //Il ne devrait y avoir que des (-1) + printf("| (%d) ", g->ligne[i]); + } + } + printf("\ncolonnes :\t"); + for (i = 0; i < graphe_get_max(g); i++) + { + if(i < graphe_get_premier_vide(g)) + { + printf("| %2d ", g->col[i]); + } + else + { //Il ne devrait y avoir que des (-1) + printf("| (%d) ", g->col[i]); + } + } + printf("\n======================"); + printf("\n\n"); +} + + /** Renvoie le maximum entre 2 entiers * @param x un entier * @param y un entier diff --git a/pagerank/src/graphe.h b/pagerank/src/graphe.h index d94e477..ee77415 100644 --- a/pagerank/src/graphe.h +++ b/pagerank/src/graphe.h @@ -32,7 +32,7 @@ void graphe_detruire(graphe* g); * @return g->max un entier * O(1) */ -int get_max(graphe* g); +int graphe_get_max(graphe* g); /** Renvoie l'indice du premier (-1 -1) dans le graphe @@ -40,7 +40,25 @@ int get_max(graphe* g); * @return g->premierVide un entier * O(1) */ -int get_premier_vide(graphe* g); +int graphe_get_premier_vide(graphe* g); + + +/** Indique si un sommet est dans le graphe + * @param g un pointeur vers un graphe alloué en mémoire + * @param u un entier, le sommet dont on veut savoir s'il est dans le graphe + * @return 1 si le sommet est dans le graphe et 0 sinon + * O(n) + */ +int graphe_contains(graphe* g, int u); + + +/** Donne l'indice de la première occurence d'un sommet dans le graphe + * @param g un pointeur vers un graphe alloué en mémoire + * @param u un entier, le sommet dont on veut connaître l'indice dans le graphe + * @return l'indice de le sommet si il est dans le graphe et -1 sinon + * O(n) + */ +int graphe_find(graphe* g, int u); /** Renvoie le plus grand indice des sommets du graphe @@ -48,7 +66,7 @@ int get_premier_vide(graphe* g); * @return un entier * O(n) */ -int get_plus_grand_sommet(graphe* g); +int graphe_get_plus_grand_sommet(graphe* g); /** Ajoute une arête entre les sommets i et j du graphe @@ -57,7 +75,7 @@ int get_plus_grand_sommet(graphe* g); * @param j un des sommets de l'arête * O(1) */ -void ajouter_arete(graphe *g, int i, int j); +void graphe_ajouter_arete(graphe* g, int i, int j); /** Supprime une arête entre les sommets i et j du graphe @@ -66,7 +84,7 @@ void ajouter_arete(graphe *g, int i, int j); * @param j un des sommets de l'arête * O(n) */ -void supprimer_arete(graphe *g, int i, int j); +void graphe_supprimer_arete(graphe* g, int i, int j); /** Retire un sommet du graphe, assure qu'aucun sommet n'a d'arête allant vers ce dernier et qu'aucune arête ne part de celui ci. @@ -75,12 +93,43 @@ void supprimer_arete(graphe *g, int i, int j); * @param x le sommet à retirer * O(n) */ -void retirer_sommet(graphe* g, int x); +void graphe_retirer_sommet(graphe* g, int x); + + +/** Indique si 2 sommets sont adjacents ou non, s'il existe une arête les reliant + * @param g un pointeur vers un graphe alloué en mémoire + * @param u un des sommets de l'arête + * @param v un des sommets de l'arête + * @return 1 si les sommets sont adjacents et 0 sinon + * O(n) + */ +int graphe_voisins(graphe* g, int u, int v); +/** Indique si 1 sommet est successeur d'un autre ou non + * @param g un pointeur vers un graphe alloué en mémoire + * @param u un des sommets de l'arête + * @param v un des sommets de l'arête + * @return 1 si v est un successeur de u et 0 sinon + * O(n) + */ +int graphe_est_succ(graphe* g, int u, int v); + + +/** Affiche le graphe sous la forme d'une matrice d'adjacence + * @param g un pointeur vers un graphe alloué en mémoire + * O(n) + */ void graphe_afficher(graphe* g); +/** Affiche le graphe sous la forme des 2 tableaux le composant + * @param g un pointeur vers un graphe alloué en mémoire + * O(n) + */ +void graphe_afficher_tableaux(graphe* g); + + /** Renvoie le maximum entre 2 entiers * @param x un entier * @param y un entier @@ -89,9 +138,4 @@ void graphe_afficher(graphe* g); */ int max(int x, int y); - -//afficher tableaux -//2 sommets sont-ils connectés? (valeur > 0) - - #endif diff --git a/pagerank/src/liste_url.c b/pagerank/src/liste_url.c new file mode 100644 index 0000000..dbf7df7 --- /dev/null +++ b/pagerank/src/liste_url.c @@ -0,0 +1,216 @@ +#include +#include +#include +#include "liste_url.h" + + +/** Fonction qui crée une liste d'url qui est stockée à l'adresse donnée en argument, déjà allouée, la liste aura déjà n cases pour stocker des URLs (c'est un tableau dynamique, sa taille pourra être amenée à augmenter) + * @param l une liste d'url allouée en mémoire + * @param n un entier strictement positif, la taille de la liste + * @return 0 si la liste a été créée et -1 si n <= 0 et -2 s'il y a eu une erreur d'allocation + * O(n) + */ +int creer_liste(liste_url* l, int n) +{ + if(n <= 0) + { + printf("Erreur paramètre creer_liste, n <= 0\n"); + return -1; + } + if(!(l->urls = (char**) calloc(sizeof(char*), n))) + { + printf("Erreur allocation creer_liste, l->urls\n"); + return -2; + } + l->max = n; + l->premierNULL = 0; + return 0; +} + + +/** Renvoie la taille maximale actuelle de la liste l + * @param l un pointeur vers une liste allouée en mémoire + * @return g->max un entier + * O(1) + */ +int liste_get_max(liste_url* l) +{ + return l->max; +} + + +/** Renvoie l'indice du premier NULL dans le liste + * @param l un pointeur vers une liste allouée en mémoire + * @return l->premierNULL un entier + * O(1) + */ +int liste_get_premier_NULL(liste_url* l) +{ + return l->premierNULL; +} + + +/** Indique si une url est dans la liste + * @param l un pointeur vers une liste allouée en mémoire + * @param s une chaîne, l'URL dont on veut savoir si elle est dans la liste + * @return 1 si l'URL est dans la liste et 0 sinon + * O(n) + */ +int liste_contains(liste_url* l, char* s) +{ + return (liste_find(l, s) != -1); +} + + +/** Donne l'indice d'une url est dans la liste + * @param l un pointeur vers une liste allouée en mémoire + * @param s une chaîne, l'URL dont on veut connaître l'indice dans la liste + * @return l'indice de l'URL si elle est dans la liste et -1 sinon + * O(n) + */ +int liste_find(liste_url* l, char* s) +{ + if(l && s) + { + int i; + for(i = 0; i < liste_get_premier_NULL(l); i++) + { + if(!strcmp(s, liste_get_i(l, i))) + { + return i; + } + } + } + return -1; +} + + +/** Renvoie l'url à l'indice i dans la liste + * @param l un pointeur vers une liste allouée en mémoire + * @param i un entier + * @return l->urls[i] un entier si 0 <= i < liste_get_max(l), NULL sinon + * O(1) + */ +char* liste_get_i(liste_url* l, int i) +{ + if(0 <= i && i < liste_get_max(l)) + { + return l->urls[i]; + } + return NULL; +} + + +/** Ajoute une url à la première case vide dans la liste + * @param l un pointeur vers une liste allouée en mémoire + * @param s une chaîne, l'URL à ajouter + * O(1) + */ +void liste_add(liste_url* l, char* s) +{ + if(l) + { + if(liste_get_premier_NULL(l) == liste_get_max(l)) + { //Réallocation si nécessaire, complexité amortie en temps linéaire + l->max *= 2; + char** nouvelleListe = (char**) calloc(sizeof(char*), liste_get_max(l)); + + for (int i = 0; i < liste_get_premier_NULL(l); i++) + { + nouvelleListe[i] = (char*) malloc(sizeof(char) * (strlen(l->urls[i]) + 1)); + strcpy(nouvelleListe[i], l->urls[i]); + free(l->urls[i]); + } + nouvelleListe[l->premierNULL] = (char*) calloc(sizeof(char), strlen(s)+1); + strcpy(nouvelleListe[l->premierNULL++], s); + free(l->urls); + l->urls = nouvelleListe; + return; + } + l->urls[l->premierNULL] = (char*) calloc(sizeof(char), strlen(s)+1); + strcpy(l->urls[l->premierNULL++], s); + } +} + + +/** Retire une url de la liste + * @param l un pointeur vers une liste allouée en mémoire + * @param s une chaîne, l'URL à retirer + * O(n) + */ +void liste_remove(liste_url* l, char* s) +{ + if(l && s) + { + int i, trouve = 0; + for(i = 0; i < liste_get_premier_NULL(l); i++) + { + if(!trouve && (!strcmp(s, liste_get_i(l, i)))) + { + free(liste_get_i(l, i)); + l->urls[i] = l->urls[i+1]; + trouve = 1; + } + else if(trouve) + { + if(i+1 < liste_get_max(l)) + { + l->urls[i] = l->urls[i+1]; + } + else + { + l->urls[i] = NULL; + } + } + } + l->premierNULL--; + } +} + + +/** Libère la mémoire allouée dans une liste et toutes les chaînes contenues dedans + * @param l une liste d'url allouée en mémoire + * O(n) + */ +void liste_detruire(liste_url* l) +{ + if(l) + { + int i; + for(i = 0; i < liste_get_premier_NULL(l); i++) + { + free(l->urls[i]); + l->urls[i] = NULL; + } + free(l->urls); + } +} + + +/** Affiche la liste d'URLs + * @param l un pointeur vers une liste allouée en mémoire + * O(n) + */ +void liste_afficher(liste_url* l) +{ + if(l) + { + int i, n = liste_get_max(l); + printf("i\t|\tURLs:\n"); + for(i = 0; i < n; i++) + { + if(i < liste_get_premier_NULL(l)) + { + printf("%d \t|\t\"%s\"\n", i, liste_get_i(l, i)); + } + else + { + printf("%d \t|\tNULL\n", i); + } + } + } + else + { + printf("La liste est NULL\n"); + } +} diff --git a/pagerank/src/liste_url.h b/pagerank/src/liste_url.h new file mode 100644 index 0000000..b18dd53 --- /dev/null +++ b/pagerank/src/liste_url.h @@ -0,0 +1,95 @@ +#ifndef LISTE_URL_H +#define LISTE_URL_H + + +struct s_liste_url { + int max; // Longueur de la liste allouée + int premierNULL; // Indice de la première chaîne NULL + char** urls; // Les urls de la liste +}; +typedef struct s_liste_url liste_url; + + +/** Fonction qui crée une liste d'url qui est stockée à l'adresse donnée en argument, déjà allouée, la liste aura déjà n cases pour stocker des URLs (c'est un tableau dynamique, sa taille pourra être amenée à augmenter) + * @param l une liste d'url allouée en mémoire + * @param n un entier strictement positif, la taille de la liste + * @return 0 si la liste a été créée et -1 si n <= 0 et -2 s'il y a eu une erreur d'allocation + * O(n) + */ +int creer_liste(liste_url* l, int n); + + +/** Renvoie la taille maximale actuelle de la liste l + * @param l un pointeur vers une liste allouée en mémoire + * @return g->max un entier + * O(1) + */ +int liste_get_max(liste_url* l); + + +/** Renvoie l'indice du premier NULL dans le liste + * @param l un pointeur vers une liste allouée en mémoire + * @return l->premierNULL un entier + * O(1) + */ +int liste_get_premier_NULL(liste_url* l); + + +/** Indique si une url est dans la liste + * @param l un pointeur vers une liste allouée en mémoire + * @param s une chaîne, l'URL dont on veut savoir si elle est dans la liste + * @return 1 si l'URL est dans la liste et 0 sinon + * O(n) + */ +int liste_contains(liste_url* l, char* s); + + +/** Donne l'indice d'une url est dans la liste + * @param l un pointeur vers une liste allouée en mémoire + * @param s une chaîne, l'URL dont on veut connaître l'indice dans la liste + * @return l'indice de l'URL si elle est dans la liste et -1 sinon + * O(n) + */ +int liste_find(liste_url* l, char* s); + + +/** Renvoie l'url à l'indice i dans la liste + * @param l un pointeur vers une liste allouée en mémoire + * @param i un entier + * @return l->urls[i] un entier si 0 <= i < liste_get_max(l), NULL sinon + * O(1) + */ +char* liste_get_i(liste_url* l, int i); + + +/** Ajoute une url à la première case vide dans la liste + * @param l un pointeur vers une liste allouée en mémoire + * @param s une chaîne, l'URL à ajouter + * O(1) + */ +void liste_add(liste_url* l, char* s); + + +/** Retire une url de la liste + * @param l un pointeur vers une liste allouée en mémoire + * @param s une chaîne, l'URL à retirer + * O(n) + */ +void liste_remove(liste_url* l, char* s); + + + +/** Libère la mémoire allouée dans une liste et toutes les chaînes contenues dedans + * @param l une liste d'url allouée en mémoire + * O(n) + */ +void liste_detruire(liste_url* l); + + +/** Affiche la liste d'URLs + * @param l un pointeur vers une liste allouée en mémoire + * O(n) + */ +void liste_afficher(liste_url* l); + +#endif diff --git a/pagerank/src/pagerank.c b/pagerank/src/pagerank.c new file mode 100644 index 0000000..37c8087 --- /dev/null +++ b/pagerank/src/pagerank.c @@ -0,0 +1,153 @@ +#include +#include +#include "pagerank.h" + +/** Fonction qui crée un pagerank pour n URLs qui est stocké à l'adresse donnée en argument, déjà allouée, + * @param p un pagerank alloué en mémoire + * @param n un entier strictement positif, la taille du graphe et de la liste du pagerank + * @return 0 si la liste a été créée et -1 si n <= 0 et -2 s'il y a eu une erreur d'allocation + * O(n) + */ +int creer_pagerank(pagerank* p, int n) +{ + int i; + if(n <= 0) + { + printf("Erreur paramètre creer_pagerank, n <= 0\n"); + return -1; + } + if(!(p->g = (graphe) malloc(sizeof(graphe)))) + { + printf("Erreur allocation creer_pagerank, malloc p->g\n"); + return -2; + } + if(creer_graphe(&p->g, n)) + { + free(p->g); + printf("Erreur allocation creer_pagerank, creer_graphe\n"); + return -2; + } + if(!(p->l = (liste_url) malloc(sizeof(liste_url)))) + { + graphe_detruire(&p->g); + free(p->g); + printf("Erreur allocation creer_pagerank, malloc p->l\n"); + return -2; + } + if(creer_liste(&p->l, n)) + { + graphe_detruire(&p->g); + free(p->g); + free(p->l); + printf("Erreur allocation creer_pagerank, creer_liste\n"); + return -2; + } + return 0; +} + + +/** Libère la mémoire allouée dans un pagerank + * @param p un pagerank alloué en mémoire + * O(n) + */ +void pagerank_detruire(pagerank* p) +{ + if(p) + { + if(p->g) + { + graphe_detruire(p->g); + free(p->g); + p->g = NULL; + } + if(p->l) + { + liste_detruire(p->l); + free(p->l); + p->l = NULL; + } + free(p); + } +} + + +/** Ajoute une URL à la première case vide dans la liste + * @param p un pagerank alloué en mémoire + * @param s une chaîne, l'URL à ajouter + * O(1) + */ +void pagerank_add_URL(pagerank* p, char* s) +{ + if(p && p->l) + { + liste_add(p->l, s); + } +} + + +/** Retire une URL de la liste du pagerank + * @param p un pagerank alloué en mémoire + * @param s une chaîne, l'URL à retirer + * O(n) + */ +void pagerank_remove_URL(pagerank* p, char* s) +{ + if(p && p->l) + { + liste_remove(p->l, s); + } +} + +/** Relie 2 URLs sous la forme d'une arête entre les sommets i et j du graphe du pagerank + * @param p un pagerank alloué en mémoire + * @param i un des sommets de l'arête + * @param j un des sommets de l'arête + * O(n) + */ +void pagerank_relier_URL(pagerank* p, int i, int j) +{ + if(p && p->l && p->g) + { + if(liste_contains(p->l, i) && liste_contains(p->l, j)) + { + graphe_ajouter_arete(p->g, i, j); + } + } +} + + +/** Delie 2 URLs en retirant une arête entre les sommets i et j du graphe du pagerank s'il y en a une + * @param p un pagerank alloué en mémoire + * @param i un des sommets de l'arête + * @param j un des sommets de l'arête + * O(n) + */ +void pagerank_delier_URL(pagerank* p, int i, int j) +{ + if(p && p->l && p->g) + { + if(liste_contains(p->l, i) && liste_contains(p->l, j)) + { + graphe_supprimer_arete(p->g, i, j); + } + } +} + + +/** Retire une URL du pagerank en retirant le sommet de son graphe, et l'URL de sa liste + * @param p un pagerank alloué en mémoire + * @param s une chaîne, l'URL à retirer + * O(n) + */ +void pagerank_retirer_URL(pagerank* p, char* s) +{ + if(p && p->l && p->g) + { + int x = liste_get_i(p->l, s); + if(x != -1) + { + liste_remove(p->l, s); + graphe_retirer_sommet(p->p, x); + } + } +} diff --git a/pagerank/src/pagerank.h b/pagerank/src/pagerank.h new file mode 100644 index 0000000..057123f --- /dev/null +++ b/pagerank/src/pagerank.h @@ -0,0 +1,72 @@ +#ifndef PAGERANK_H +#define PAGERANK_H + +struct s_pagerank { + graphe g; //Le graphe du pagerank + pagerank l; //La liste de toutes les URLs du pagerank +}; +typedef struct s_pagerank pagerank; + + +/** Fonction qui crée un pagerank pour n URLs qui est stocké à l'adresse donnée en argument, déjà allouée, + * @param p un pagerank alloué en mémoire + * @param n un entier strictement positif, la taille du graphe et de la liste du pagerank + * @return 0 si la liste a été créée et -1 si n <= 0 et -2 s'il y a eu une erreur d'allocation + * O(n) + */ +int creer_pagerank(pagerank* p, int n); + + +/** Libère la mémoire allouée dans un pagerank + * @param p un pagerank alloué en mémoire + * O(n) + */ +void pagerank_detruire(pagerank* p); + + +/** Ajoute une URL à la première case vide dans la liste + * @param p un pagerank alloué en mémoire + * @param s une chaîne, l'URL à ajouter + * O(1) + */ +void pagerank_add_URL(pagerank* p, char* s); + + +/** Retire une URL de la liste du pagerank + * @param p un pagerank alloué en mémoire + * @param s une chaîne, l'URL à retirer + * O(n) + */ +void pagerank_remove_URL(pagerank* p, char* s); + + +/** Relie 2 URLs sous la forme d'une arête entre les sommets i et j du graphe du pagerank + * @param p un pagerank alloué en mémoire + * @param i un des sommets de l'arête + * @param j un des sommets de l'arête + * O(n) + */ +void pagerank_relier_URL(pagerank* p, int i, int j); + + +/** Delie 2 URLs en retirant une arête entre les sommets i et j du graphe du pagerank s'il y en a une + * @param p un pagerank alloué en mémoire + * @param i un des sommets de l'arête + * @param j un des sommets de l'arête + * O(n) + */ +void pagerank_delier_URL(pagerank* p, int i, int j); + + +/** Retire une URL du pagerank en retirant le sommet de son graphe, et l'URL de sa liste + * @param p un pagerank alloué en mémoire + * @param s une chaîne, l'URL à retirer + * O(n) + */ +void pagerank_retirer_URL(pagerank* p, int x); + + +//int pagerank isValid test indices +// est lié à + +#endif diff --git a/pagerank/test/Makefile b/pagerank/test/Makefile index 2abbb88..905bcc2 100644 --- a/pagerank/test/Makefile +++ b/pagerank/test/Makefile @@ -1,12 +1,13 @@ CC= gcc CXXFLAGS= -Wall --pedantic -O3 -CPP_O_FILE = test-graphe.o +CPP_O_FILE = test-graphe.o test-liste.o LIB = -lm all: $(CPP_O_FILE) $(CC) $(CXXFLAGS) -o test-graphe.exe test-graphe.c ../src/graphe.c $(LIB) + $(CC) $(CXXFLAGS) -o test-liste.exe test-liste.c ../src/liste_url.c $(LIB) clean: rm -rf *.o *.exe diff --git a/pagerank/test/test-graphe.c b/pagerank/test/test-graphe.c index 9377a34..7796804 100644 --- a/pagerank/test/test-graphe.c +++ b/pagerank/test/test-graphe.c @@ -8,32 +8,51 @@ int main() { graphe g; creer_graphe(&g, NB_SOMMETS); - ajouter_arete(&g, 0, 1); - ajouter_arete(&g, 0, 9); - ajouter_arete(&g, 1, 3); - ajouter_arete(&g, 1, 2); - ajouter_arete(&g, 1, 4); - ajouter_arete(&g, 2, 4); - ajouter_arete(&g, 3, 4); - ajouter_arete(&g, 3, 5); - ajouter_arete(&g, 4, 5); - ajouter_arete(&g, 4, 6); - ajouter_arete(&g, 5, 6); + graphe_ajouter_arete(&g, 0, 1); + graphe_afficher_tableaux(&g); + graphe_ajouter_arete(&g, 0, 9); + //graphe_afficher_tableaux(&g); + graphe_ajouter_arete(&g, 1, 3); + //graphe_afficher_tableaux(&g); + graphe_ajouter_arete(&g, 1, 2); + //graphe_afficher_tableaux(&g); + graphe_ajouter_arete(&g, 1, 4); + //graphe_afficher_tableaux(&g); + graphe_ajouter_arete(&g, 2, 4); + //graphe_afficher_tableaux(&g); + graphe_ajouter_arete(&g, 3, 4); + //graphe_afficher_tableaux(&g); + graphe_ajouter_arete(&g, 3, 5); + //graphe_afficher_tableaux(&g); + graphe_ajouter_arete(&g, 4, 5); + //graphe_afficher_tableaux(&g); + graphe_ajouter_arete(&g, 4, 6); + graphe_afficher_tableaux(&g); + graphe_ajouter_arete(&g, 5, 6); + graphe_afficher_tableaux(&g); graphe_afficher(&g); + printf("Le graphe %s le sommet 9, indice : %d\n", (graphe_contains(&g, 9) ? "contient" : "ne contient pas"), graphe_find(&g, 9)); printf("Retirons le sommet 4 (un nouveau sommet 4 prendra sa place\n"); - retirer_sommet(&g, 4); + graphe_retirer_sommet(&g, 4); printf("Retirons les arêtes 4-5, 1-3, et 5-4 (déjà retirée)\n"); - supprimer_arete(&g, 4, 5); + graphe_supprimer_arete(&g, 4, 5); graphe_afficher(&g); - supprimer_arete(&g, 1, 3); + graphe_supprimer_arete(&g, 1, 3); graphe_afficher(&g); - supprimer_arete(&g, 5, 4); + graphe_supprimer_arete(&g, 5, 4); graphe_afficher(&g); + printf("Les sommets 1 et 7 %s\n", (graphe_voisins(&g, 1, 7) ? "sont voisins" : "ne sont pas voisins")); + printf("Ajoutons une arête 1-7\n"); + graphe_ajouter_arete(&g, 1, 7); + printf("Les sommets 1 et 7 %s\n", (graphe_voisins(&g, 1, 7) ? "sont voisins" : "ne sont pas voisins")); + graphe_afficher(&g); + printf("Le graphe %s le sommet 9, indice : %d\n", (graphe_contains(&g, 9) ? "contient" : "ne contient pas"), graphe_find(&g, 9)); + graphe_detruire(&g); return EXIT_SUCCESS; } diff --git a/pagerank/test/test-liste.c b/pagerank/test/test-liste.c new file mode 100644 index 0000000..0db18a1 --- /dev/null +++ b/pagerank/test/test-liste.c @@ -0,0 +1,29 @@ +#include +#include +#include "../src/liste_url.h" + + +int main() +{ + liste_url l; + creer_liste(&l, 1); + liste_add(&l, "www.google.com"); + liste_add(&l, "www.gogol.com"); + liste_add(&l, "file://C:\\Users\\Nicolas\\Homework"); + liste_add(&l, "lipn.univ-paris13.fr/"); + liste_add(&l, "https://lipn.univ-paris13.fr/accueil/presentation/le-laboratoire/"); + + + liste_afficher(&l); + + printf("La liste %s l'URL \"www.google.com\", indice : %d\n", (liste_contains(&l, "www.google.com") ? "contient" : "ne contient pas"), liste_find(&l, "www.google.com")); + + printf("Retirons la première URL, celle de google\n"); + + liste_remove(&l, "www.google.com"); + liste_afficher(&l); + printf("La liste %s l'URL \"www.google.com\", indice : %d\n", (liste_contains(&l, "www.google.com") ? "contient" : "ne contient pas"), liste_find(&l, "www.google.com")); + + liste_detruire(&l); + return EXIT_SUCCESS; +} -- GitLab From 09c4392b69923264a041d9ecbab24dce88776216 Mon Sep 17 00:00:00 2001 From: Nicolas Floquet Date: Mon, 22 Mar 2021 23:13:09 +0100 Subject: [PATCH 6/6] =?UTF-8?q?T=C3=A2che=201=20=C3=A0=20valider=20(pagera?= =?UTF-8?q?nk)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagerank/src/graphe.c | 124 +++++++++++++++++-- pagerank/src/graphe.h | 10 ++ pagerank/src/liste_url.c | 11 +- pagerank/src/liste_url.h | 2 +- pagerank/src/pagerank.c | 225 +++++++++++++++++++++++++++++----- pagerank/src/pagerank.h | 69 ++++++++--- pagerank/test/Makefile | 3 +- pagerank/test/test-graphe.c | 18 +++ pagerank/test/test-liste.c | 2 + pagerank/test/test-pagerank.c | 81 ++++++++++++ 10 files changed, 484 insertions(+), 61 deletions(-) create mode 100644 pagerank/test/test-pagerank.c diff --git a/pagerank/src/graphe.c b/pagerank/src/graphe.c index b01e43f..ae0ae9b 100644 --- a/pagerank/src/graphe.c +++ b/pagerank/src/graphe.c @@ -164,7 +164,7 @@ void graphe_ajouter_arete(graphe* g, int i, int j) } -/** Supprime une arête entre les sommets i et j du graphe (ou j et i) +/** Supprime une arête entre les sommets i et j du graphe * @param g un pointeur vers un graphe alloué en mémoire * @param i un des sommets de l'arête * @param j un des sommets de l'arête @@ -184,7 +184,7 @@ void graphe_supprimer_arete(graphe* g, int i, int j) } else { - if((g->ligne[cpt] == i && g->col[cpt] == j) || (g->ligne[cpt] == j && g->col[cpt] == i)) + if(g->ligne[cpt] == i && g->col[cpt] == j) { flag = 1; g->ligne[cpt] = g->ligne[cpt+1]; @@ -346,36 +346,36 @@ void graphe_afficher(graphe* g) for(i = 0; i < g->premierVide; i++) { matrice[g->ligne[i] * lim + g->col[i]]++; - matrice[g->col[i] * lim + g->ligne[i]]++; + // pas dans les 2 sens matrice[g->col[i] * lim + g->ligne[i]]++; } /* matrice d'adjacence faite */ /* ligne indices colonnes */ printf("\t\t"); - for (w = 0 ; w < lim ; w++) + for(w = 0 ; w < lim ; w++) { printf("%d\t", w); } printf("\n"); printf("\t\t"); - for (w = 0 ; w < lim ; w++) + for(w = 0 ; w < lim ; w++) { printf("_\t"); } printf("\n"); /* lignes de la matrice */ - for (v = 0 ; v < lim ; v++) + for(v = 0 ; v < lim ; v++) { printf("%d\t|\t", v); - for (w = 0 ; w < lim ; w++) + for(w = 0 ; w < lim ; w++) { printf("%d\t", matrice[v * lim + w]); } printf("|\n"); } printf("\t\t"); - for (w = 0 ; w < lim ; w++) + for(w = 0 ; w < lim ; w++) { printf("_\t"); } @@ -398,12 +398,12 @@ void graphe_afficher_tableaux(graphe* g) int i; printf("\n======================"); printf("\nIndices\t\t"); - for (i = 0; i < graphe_get_max(g); i++) + for(i = 0; i < graphe_get_max(g); i++) { printf("| %2d ", i); } printf("\n\nlignes :\t"); - for (i = 0; i < graphe_get_max(g); i++) + for(i = 0; i < graphe_get_max(g); i++) { if(i < graphe_get_premier_vide(g)) { @@ -415,7 +415,7 @@ void graphe_afficher_tableaux(graphe* g) } } printf("\ncolonnes :\t"); - for (i = 0; i < graphe_get_max(g); i++) + for(i = 0; i < graphe_get_max(g); i++) { if(i < graphe_get_premier_vide(g)) { @@ -431,6 +431,108 @@ void graphe_afficher_tableaux(graphe* g) } +/** Convertit un graphe au format DOT dans un fichier + * dot -Tpdf fichier.dot -o fichier.pdf + * @param g un graphe alloué en mémoire + * @param nomFichier, le nom du fichier où l'on veut écrire le graphe + * @return 0 si le graphe a bien été écris au format DOT, + * -1 s'il y a eu une erreur d'ouverture du fichier, et -2 sinon + * O(n) + */ +int graphe_ecrire_dot(graphe* g, char* nomFichier) +{ + if(g) + { + int i, nbSommets = 0, n = graphe_get_premier_vide(g), sommetMax = graphe_get_plus_grand_sommet(g); + if(!n) + { + printf("Erreur premier vide = 0, graphe vide graphe_ecrire_dot\n"); + return -2; + } + /* + On utilise 2 tableaux pour avoir une liste des sommets dans le graphe. + Soit n = graphe_get_premier_vide(g), il y a au max 2n sommets différents + (Si tous les sommets dans le tableau des lignes sont distincts et pointent chacun vers un sommets distinct) + Donc c'est le nombre max de sommets dans le fichier DOT. + + Et les valeurs des sommets sont entre 0 et graphe_get_plus_grand_sommet(g) inclus + */ + + int* flagSommet = (int *) calloc(sizeof(int), sommetMax + 1); + /* + flagSommet[i] = + 0 : sommet pas dans le graphe + 1 : sommet dans le graphe, il faudra l'ajouter dans le fichier dot + Toutes les valeurs entières entre 0 et sommetMax inclus peuvent être dans le graphe + */ + if(!flagSommet) + { + printf("Erreur allocation flagSommet graphe_ecrire_dot\n"); + return -2; + } + int* listeSommets = (int *) calloc(sizeof(int), 2*n); + /* + listeSommets[i] : + -1 : sommet pas dans le graphe + >= 0 : sommet dans le graphe, il faudra l'ajouter dans le fichier dot + Il y a au max 2n sommets différents + */ + if(!listeSommets) + { + printf("Erreur allocation listeSommets graphe_ecrire_dot\n"); + free(flagSommet); + return -2; + } + + for(i = 0; i < 2*n; i++) + { + listeSommets[i]--; //-1 partout + } + FILE *f = fopen(nomFichier, "w"); + if (!f) + { + free(flagSommet); + free(listeSommets); + printf("Erreur ouverture fichier \"%s\"graphe_ecrire_dot\n", nomFichier); + return -1; + } + for(i = 0; i < n; i++) + { + if(!flagSommet[g->ligne[i]]) //g->ligne[i] valait 0, donc le sommet n'était pas découvert + { + flagSommet[g->ligne[i]] = 1; + listeSommets[nbSommets++] = g->ligne[i]; + } + if(!flagSommet[g->col[i]]) //g->col[i] valait 0, donc le sommet n'était pas découvert + { + flagSommet[g->col[i]] = 1; + listeSommets[nbSommets++] = g->col[i]; + } + } + + //Dans flagSommet, on a tous les flags indiquant si un sommet est dans le graphe ou non + //Dans listeSommets on a la liste des sommets distincts + fputs("graph {\n", f); + for(i = 0; i < nbSommets; i++) + { + fprintf(f, "\t%d;\n", listeSommets[i]); + } + fputs("\n", f); + for(i = 0; i < n; i++) + { + fprintf(f, "\t%d -- %d;\n", g->ligne[i], g->col[i]); + } + fputs("}\n", f); + free(flagSommet); + free(listeSommets); + fclose(f); + return 0; + } + printf("Erreur pagerank NULL graphe_ecrire_dot\n"); + return -2; +} + + /** Renvoie le maximum entre 2 entiers * @param x un entier * @param y un entier diff --git a/pagerank/src/graphe.h b/pagerank/src/graphe.h index ee77415..f7adac2 100644 --- a/pagerank/src/graphe.h +++ b/pagerank/src/graphe.h @@ -130,6 +130,16 @@ void graphe_afficher(graphe* g); void graphe_afficher_tableaux(graphe* g); +/** Convertit un graphe au format DOT dans un fichier + * @param g un graphe alloué en mémoire + * @param nomFichier, le nom du fichier où l'on veut écrire le graphe + * @return 0 si le graphe a bien été écris au format DOT, + * -1 s'il y a eu une erreur d'ouverture du fichier, et -2 sinon + * O(n) + */ +int graphe_ecrire_dot(graphe* g, char* nomFichier); + + /** Renvoie le maximum entre 2 entiers * @param x un entier * @param y un entier diff --git a/pagerank/src/liste_url.c b/pagerank/src/liste_url.c index dbf7df7..9f0333c 100644 --- a/pagerank/src/liste_url.c +++ b/pagerank/src/liste_url.c @@ -88,7 +88,7 @@ int liste_find(liste_url* l, char* s) /** Renvoie l'url à l'indice i dans la liste * @param l un pointeur vers une liste allouée en mémoire * @param i un entier - * @return l->urls[i] un entier si 0 <= i < liste_get_max(l), NULL sinon + * @return l->urls[i] une chaîne de caractères si 0 <= i < liste_get_max(l), NULL sinon * O(1) */ char* liste_get_i(liste_url* l, int i) @@ -148,7 +148,14 @@ void liste_remove(liste_url* l, char* s) if(!trouve && (!strcmp(s, liste_get_i(l, i)))) { free(liste_get_i(l, i)); - l->urls[i] = l->urls[i+1]; + if(i+1 < liste_get_max(l)) + { + l->urls[i] = l->urls[i+1]; + } + else + { + l->urls[i] = NULL; + } trouve = 1; } else if(trouve) diff --git a/pagerank/src/liste_url.h b/pagerank/src/liste_url.h index b18dd53..476bb56 100644 --- a/pagerank/src/liste_url.h +++ b/pagerank/src/liste_url.h @@ -56,7 +56,7 @@ int liste_find(liste_url* l, char* s); /** Renvoie l'url à l'indice i dans la liste * @param l un pointeur vers une liste allouée en mémoire * @param i un entier - * @return l->urls[i] un entier si 0 <= i < liste_get_max(l), NULL sinon + * @return l->urls[i] une chaîne de caractères si 0 <= i < liste_get_max(l), NULL sinon * O(1) */ char* liste_get_i(liste_url* l, int i); diff --git a/pagerank/src/pagerank.c b/pagerank/src/pagerank.c index 37c8087..1e32b66 100644 --- a/pagerank/src/pagerank.c +++ b/pagerank/src/pagerank.c @@ -1,6 +1,8 @@ #include #include #include "pagerank.h" +#include "graphe.h" +#include "liste_url.h" /** Fonction qui crée un pagerank pour n URLs qui est stocké à l'adresse donnée en argument, déjà allouée, * @param p un pagerank alloué en mémoire @@ -10,33 +12,32 @@ */ int creer_pagerank(pagerank* p, int n) { - int i; if(n <= 0) { printf("Erreur paramètre creer_pagerank, n <= 0\n"); return -1; } - if(!(p->g = (graphe) malloc(sizeof(graphe)))) + if(!(p->g = (graphe*) malloc(sizeof(graphe)))) { printf("Erreur allocation creer_pagerank, malloc p->g\n"); return -2; } - if(creer_graphe(&p->g, n)) + if(creer_graphe(p->g, n)) { free(p->g); printf("Erreur allocation creer_pagerank, creer_graphe\n"); return -2; } - if(!(p->l = (liste_url) malloc(sizeof(liste_url)))) + if(!(p->l = (liste_url*) malloc(sizeof(liste_url)))) { - graphe_detruire(&p->g); + graphe_detruire(p->g); free(p->g); printf("Erreur allocation creer_pagerank, malloc p->l\n"); return -2; } - if(creer_liste(&p->l, n)) + if(creer_liste(p->l, n)) { - graphe_detruire(&p->g); + graphe_detruire(p->g); free(p->g); free(p->l); printf("Erreur allocation creer_pagerank, creer_liste\n"); @@ -66,11 +67,41 @@ void pagerank_detruire(pagerank* p) free(p->l); p->l = NULL; } - free(p); } } +/** Donne l'indice d'une url est dans la liste d'un pagerank + * @param p un pagerank alloué en mémoire + * @param s une chaîne, l'URL dont on veut connaître l'indice dans la liste + * @return l'indice de l'URL si elle est dans la liste du pagerank et -1 sinon + * O(n) + */ +int pagerank_find_indice_URL(pagerank* p, char* s) +{ + if(p) + { + return liste_find(p->l, s); + } + return -1; +} + + +/** Renvoie l'url à l'indice i dans la liste d'un pagerank + * @param p un pagerank alloué en mémoire + * @param i un entier + * @return p->l->urls[i] une chaîne de caractères si 0 <= i < liste_get_max(l), NULL sinon + * O(1) + */ +char* pagerank_get_URL_i(pagerank* p, int i) +{ + if(p) + { + return liste_get_i(p->l, i); + } + return NULL; +} + /** Ajoute une URL à la première case vide dans la liste * @param p un pagerank alloué en mémoire * @param s une chaîne, l'URL à ajouter @@ -85,69 +116,201 @@ void pagerank_add_URL(pagerank* p, char* s) } -/** Retire une URL de la liste du pagerank +/** Retire une URL du pagerank en retirant le sommet de son graphe, et l'URL de sa liste * @param p un pagerank alloué en mémoire * @param s une chaîne, l'URL à retirer * O(n) */ void pagerank_remove_URL(pagerank* p, char* s) { - if(p && p->l) + if(p && p->l && p->g) { - liste_remove(p->l, s); + int x = liste_find(p->l, s); + if(x != -1) + { + liste_remove(p->l, s); + graphe_retirer_sommet(p->g, x); + } } } -/** Relie 2 URLs sous la forme d'une arête entre les sommets i et j du graphe du pagerank +/** Relie 2 URLs du pagerank * @param p un pagerank alloué en mémoire - * @param i un des sommets de l'arête - * @param j un des sommets de l'arête + * @param s1 une des URLs du pagerank + * @param s2 une des URLs du pagerank * O(n) */ -void pagerank_relier_URL(pagerank* p, int i, int j) +void pagerank_relier_URL(pagerank* p, char* s1, char* s2) { if(p && p->l && p->g) { - if(liste_contains(p->l, i) && liste_contains(p->l, j)) + printf("ici pour %s et %s\n", s1, s2); + if(liste_contains(p->l, s1) && liste_contains(p->l, s2)) { - graphe_ajouter_arete(p->g, i, j); + printf("la pour %s et %s\n", s1, s2); + graphe_ajouter_arete(p->g, liste_find(p->l, s1), liste_find(p->l, s2)); } } } -/** Delie 2 URLs en retirant une arête entre les sommets i et j du graphe du pagerank s'il y en a une +/** Delie 2 URLs en retirant une arête entre les sommets correspondant du graphe du pagerank s'il y en a une * @param p un pagerank alloué en mémoire - * @param i un des sommets de l'arête - * @param j un des sommets de l'arête + * @param s1 une des URLs du pagerank + * @param s2 une des URLs du pagerank * O(n) */ -void pagerank_delier_URL(pagerank* p, int i, int j) +void pagerank_delier_URL(pagerank* p, char* s1, char* s2) { if(p && p->l && p->g) { - if(liste_contains(p->l, i) && liste_contains(p->l, j)) + if(liste_contains(p->l, s1) && liste_contains(p->l, s2)) { - graphe_supprimer_arete(p->g, i, j); + graphe_supprimer_arete(p->g, liste_find(p->l, s1), liste_find(p->l, s2)); } } } -/** Retire une URL du pagerank en retirant le sommet de son graphe, et l'URL de sa liste +/** Indique si une URL dans le pagerank a un lien vers une autre URL * @param p un pagerank alloué en mémoire - * @param s une chaîne, l'URL à retirer + * @param s1 une chaîne, l'URL où peut être le lien qu'on cherche + * @param s2 une chaîne, l'URL cible + * @return 1 si il y a un lien vers s2 dans la page s1 et 0 sinon * O(n) */ -void pagerank_retirer_URL(pagerank* p, char* s) +int pagerank_link_to(pagerank* p, char* s1, char* s2) { - if(p && p->l && p->g) + if(p && s1 && s2) { - int x = liste_get_i(p->l, s); - if(x != -1) + int indice1 = pagerank_find_indice_URL(p, s1); + int indice2 = pagerank_find_indice_URL(p, s2); + return graphe_est_succ(p->g, indice1, indice2); + } + return 0; +} + + +/** Affiche le pagerank (le graphe et la liste) + * @param p un pagerank alloué en mémoire + * O(n) + */ +void pagerank_afficher(pagerank* p) +{ + if(p) + { + printf("Voici la liste du pagerank:\n\n"); + liste_afficher(p->l); + printf("Voici le graphe du pagerank sous la forme de ces tableaux (matrice creuse):\n\n"); + graphe_afficher_tableaux(p->g); + printf("Voici le graphe du pagerank sous la forme d'une matrice d'adjacence:\n\n"); + graphe_afficher(p->g); + } + else + { + printf("Le pagerank est NULL\n"); + } +} + + +/** Convertit le graphe d'un pagerank au format DOT dans un fichier + * On verra un graphe avec comme sommets les URLs + * dot -Tpdf fichier.dot -o fichier.pdf + * @param p un pagerank alloué en mémoire + * @param nomFichier, le nom du fichier où l'on veut écrire le graphe + * @return 0 si le graphe a bien été écris au format DOT, + * -1 s'il y a eu une erreur d'ouverture du fichier, et -2 sinon + * O(n) + */ +int pagerank_ecrire_dot(pagerank* p, char* nomFichier) +{ + if(p) + { + int i, nbSommets = 0, n = graphe_get_premier_vide(p->g), sommetMax = graphe_get_plus_grand_sommet(p->g); + if(!n) { - liste_remove(p->l, s); - graphe_retirer_sommet(p->p, x); + printf("Erreur premier vide = 0, graphe vide pagerank_ecrire_dot\n"); + return -2; + } + /* + On utilise 2 tableaux pour avoir une liste des sommets dans le graphe. + Soit n = graphe_get_premier_vide(g), il y a au max 2n sommets différents + (Si tous les sommets dans le tableau des lignes sont distincts et pointent chacun vers un sommet distinct) + Donc c'est le nombre max de sommets dans le fichier DOT. + + Et les valeurs des sommets sont entre 0 et graphe_get_plus_grand_sommet(g) inclus + */ + + int* flagSommet = (int *) calloc(sizeof(int), sommetMax + 1); + /* + flagSommet[i] = + 0 : sommet pas dans le graphe + 1 : sommet dans le graphe, il faudra l'ajouter dans le fichier dot + Toutes les valeurs entières entre 0 et sommetMax inclus peuvent être dans le graphe + */ + if(!flagSommet) + { + printf("Erreur allocation flagSommet pagerank_ecrire_dot\n"); + return -2; + } + int* listeSommets = (int *) calloc(sizeof(int), 2*n); + /* + listeSommets[i] : + -1 : sommet pas dans le graphe + >= 0 : sommet dans le graphe, il faudra l'ajouter dans le fichier dot + Il y a au max 2n sommets différents + */ + if(!listeSommets) + { + printf("Erreur allocation listeSommets pagerank_ecrire_dot\n"); + free(flagSommet); + return -2; + } + + for(i = 0; i < 2*n; i++) + { + listeSommets[i]--; //-1 partout + } + FILE *f = fopen(nomFichier, "w"); + if (!f) + { + free(flagSommet); + free(listeSommets); + printf("Erreur ouverture fichier \"%s\"pagerank_ecrire_dot\n", nomFichier); + return -1; + } + for(i = 0; i < n; i++) + { + if(!flagSommet[p->g->ligne[i]]) //g->ligne[i] valait 0, donc le sommet n'était pas découvert + { + flagSommet[p->g->ligne[i]] = 1; + listeSommets[nbSommets++] = p->g->ligne[i]; + } + if(!flagSommet[p->g->col[i]]) //g->col[i] valait 0, donc le sommet n'était pas découvert + { + flagSommet[p->g->col[i]] = 1; + listeSommets[nbSommets++] = p->g->col[i]; + } + } + + //Dans flagSommet, on a tous les flags indiquant si un sommet est dans le graphe ou non + //Dans listeSommets on a la liste des sommets distincts + fputs("graph {\n", f); + for(i = 0; i < nbSommets; i++) + { + fprintf(f, "\t\"%s\";\n", liste_get_i(p->l, listeSommets[i])); + } + fputs("\n", f); + for(i = 0; i < n; i++) + { + fprintf(f, "\t\"%s\" -- \"%s\";\n", liste_get_i(p->l, p->g->ligne[i]), liste_get_i(p->l, p->g->col[i])); } + fputs("}\n", f); + free(flagSommet); + free(listeSommets); + fclose(f); + return 0; } + printf("Erreur pagerank NULL pagerank_ecrire_dot\n"); + return -2; } diff --git a/pagerank/src/pagerank.h b/pagerank/src/pagerank.h index 057123f..c533cd9 100644 --- a/pagerank/src/pagerank.h +++ b/pagerank/src/pagerank.h @@ -1,9 +1,13 @@ #ifndef PAGERANK_H #define PAGERANK_H +#include "graphe.h" +#include "liste_url.h" + + struct s_pagerank { - graphe g; //Le graphe du pagerank - pagerank l; //La liste de toutes les URLs du pagerank + graphe* g; //Le graphe du pagerank + liste_url* l; //La liste de toutes les URLs du pagerank }; typedef struct s_pagerank pagerank; @@ -24,6 +28,24 @@ int creer_pagerank(pagerank* p, int n); void pagerank_detruire(pagerank* p); +/** Donne l'indice d'une url est dans la liste d'un pagerank + * @param p un pagerank alloué en mémoire + * @param s une chaîne, l'URL dont on veut connaître l'indice dans la liste + * @return l'indice de l'URL si elle est dans la liste du pagerank et -1 sinon + * O(n) + */ +int pagerank_find_indice_URL(pagerank* p, char* s); + + +/** Renvoie l'url à l'indice i dans la liste d'un pagerank + * @param p un pagerank alloué en mémoire + * @param i un entier + * @return p->l->urls[i] une chaîne de caractères si 0 <= i < liste_get_max(l), NULL sinon + * O(1) + */ +char* pagerank_get_URL_i(pagerank* p, int i); + + /** Ajoute une URL à la première case vide dans la liste * @param p un pagerank alloué en mémoire * @param s une chaîne, l'URL à ajouter @@ -32,7 +54,7 @@ void pagerank_detruire(pagerank* p); void pagerank_add_URL(pagerank* p, char* s); -/** Retire une URL de la liste du pagerank +/** Retire une URL du pagerank en retirant le sommet de son graphe, et l'URL de sa liste * @param p un pagerank alloué en mémoire * @param s une chaîne, l'URL à retirer * O(n) @@ -40,33 +62,50 @@ void pagerank_add_URL(pagerank* p, char* s); void pagerank_remove_URL(pagerank* p, char* s); -/** Relie 2 URLs sous la forme d'une arête entre les sommets i et j du graphe du pagerank +/** Relie 2 URLs du pagerank * @param p un pagerank alloué en mémoire - * @param i un des sommets de l'arête - * @param j un des sommets de l'arête + * @param s1 une des URLs du pagerank + * @param s2 une des URLs du pagerank * O(n) */ -void pagerank_relier_URL(pagerank* p, int i, int j); +void pagerank_relier_URL(pagerank* p, char* s1, char* s2); -/** Delie 2 URLs en retirant une arête entre les sommets i et j du graphe du pagerank s'il y en a une +/** Delie 2 URLs en retirant une arête entre les sommets correspondant du graphe du pagerank s'il y en a une * @param p un pagerank alloué en mémoire - * @param i un des sommets de l'arête - * @param j un des sommets de l'arête + * @param s1 une des URLs du pagerank + * @param s2 une des URLs du pagerank * O(n) */ -void pagerank_delier_URL(pagerank* p, int i, int j); +void pagerank_delier_URL(pagerank* p, char* s1, char* s2); -/** Retire une URL du pagerank en retirant le sommet de son graphe, et l'URL de sa liste +/** Indique si une URL dans le pagerank a un lien vers une autre URL + * @param p un pagerank alloué en mémoire + * @param s1 une chaîne, l'URL où peut être le lien qu'on cherche + * @param s2 une chaîne, l'URL cible + * @return 1 si il y a un lien vers s2 dans la page s1 et 0 sinon + * O(n) + */ +int pagerank_link_to(pagerank* p, char* s1, char* s2); + + +/** Affiche le pagerank (le graphe et la liste) * @param p un pagerank alloué en mémoire - * @param s une chaîne, l'URL à retirer * O(n) */ -void pagerank_retirer_URL(pagerank* p, int x); +void pagerank_afficher(pagerank* p); + +/** Convertit le graphe d'un pagerank au format DOT dans un fichier + * @param p un pagerank alloué en mémoire + * @param nomFichier, le nom du fichier où l'on veut écrire le graphe + * @return 0 si le graphe a bien été écris au format DOT, + * -1 s'il y a eu une erreur d'ouverture du fichier, et -2 sinon + * O(n) + */ +int pagerank_ecrire_dot(pagerank* p, char* nomFichier); //int pagerank isValid test indices -// est lié à #endif diff --git a/pagerank/test/Makefile b/pagerank/test/Makefile index 905bcc2..4aeb4da 100644 --- a/pagerank/test/Makefile +++ b/pagerank/test/Makefile @@ -1,13 +1,14 @@ CC= gcc CXXFLAGS= -Wall --pedantic -O3 -CPP_O_FILE = test-graphe.o test-liste.o +CPP_O_FILE = test-graphe.o test-liste.o test-pagerank.o LIB = -lm all: $(CPP_O_FILE) $(CC) $(CXXFLAGS) -o test-graphe.exe test-graphe.c ../src/graphe.c $(LIB) $(CC) $(CXXFLAGS) -o test-liste.exe test-liste.c ../src/liste_url.c $(LIB) + $(CC) $(CXXFLAGS) -o test-pagerank.exe test-pagerank.c ../src/pagerank.c ../src/graphe.c ../src/liste_url.c $(LIB) clean: rm -rf *.o *.exe diff --git a/pagerank/test/test-graphe.c b/pagerank/test/test-graphe.c index 7796804..c374bcc 100644 --- a/pagerank/test/test-graphe.c +++ b/pagerank/test/test-graphe.c @@ -2,11 +2,20 @@ #include #include "../src/graphe.h" +/* +dot -Tpdf graphe_1.dot -o graphe_1.pdf +dot -Tpdf graphe_2.dot -o graphe_2.pdf +dot -Tpdf graphe_3.dot -o graphe_3.pdf +*/ + #define NB_SOMMETS 7 int main() { graphe g; + char* fichier1 = "graphe_1.dot"; + char* fichier2 = "graphe_2.dot"; + char* fichier3 = "graphe_3.dot"; creer_graphe(&g, NB_SOMMETS); graphe_ajouter_arete(&g, 0, 1); graphe_afficher_tableaux(&g); @@ -34,10 +43,16 @@ int main() graphe_afficher(&g); printf("Le graphe %s le sommet 9, indice : %d\n", (graphe_contains(&g, 9) ? "contient" : "ne contient pas"), graphe_find(&g, 9)); + printf("On stocke le graphe tel qu'il est après tous les ajouts dans le fichier %s\n", fichier1); + graphe_ecrire_dot(&g, fichier1); + printf("Retirons le sommet 4 (un nouveau sommet 4 prendra sa place\n"); graphe_retirer_sommet(&g, 4); + printf("On stocke le graphe tel qu'il est après la suppression du sommet 4 dans le fichier %s\n", fichier2); + graphe_ecrire_dot(&g, fichier2); + printf("Retirons les arêtes 4-5, 1-3, et 5-4 (déjà retirée)\n"); graphe_supprimer_arete(&g, 4, 5); graphe_afficher(&g); @@ -53,6 +68,9 @@ int main() graphe_afficher(&g); printf("Le graphe %s le sommet 9, indice : %d\n", (graphe_contains(&g, 9) ? "contient" : "ne contient pas"), graphe_find(&g, 9)); + printf("On stocke le graphe tel qu'il est après des retraits et l'ajout du sommet 7 dans le fichier %s\n", fichier3); + graphe_ecrire_dot(&g, fichier3); + graphe_detruire(&g); return EXIT_SUCCESS; } diff --git a/pagerank/test/test-liste.c b/pagerank/test/test-liste.c index 0db18a1..cb735a2 100644 --- a/pagerank/test/test-liste.c +++ b/pagerank/test/test-liste.c @@ -16,6 +16,8 @@ int main() liste_afficher(&l); + printf("La première URL est %s\n", liste_get_i(&l, 0)); + printf("La liste %s l'URL \"www.google.com\", indice : %d\n", (liste_contains(&l, "www.google.com") ? "contient" : "ne contient pas"), liste_find(&l, "www.google.com")); printf("Retirons la première URL, celle de google\n"); diff --git a/pagerank/test/test-pagerank.c b/pagerank/test/test-pagerank.c new file mode 100644 index 0000000..554d996 --- /dev/null +++ b/pagerank/test/test-pagerank.c @@ -0,0 +1,81 @@ +#include +#include +#include "../src/pagerank.h" + +/* +dot -Tpdf pagerank_1.dot -o pagerank_1.pdf +dot -Tpdf pagerank_2.dot -o pagerank_2.pdf +dot -Tpdf pagerank_3.dot -o pagerank_3.pdf +*/ + +int main() +{ + pagerank p; + char* fichier1 = "pagerank_1.dot"; + char* fichier2 = "pagerank_2.dot"; + char* fichier3 = "pagerank_3.dot"; + + char* google = "www.google.com"; + char* fichierNico = "file://C:\\Users\\Nicolas\\Homework"; + char* lipn = "lipn.univ-paris13.fr/"; + char* lipnA3 = "https://lipn.univ-paris13.fr/accueil/equipe/a3/"; + char* lipnAOC = "https://lipn.univ-paris13.fr/accueil/equipe/aoc/"; + char* lipnPresentation = "https://lipn.univ-paris13.fr/accueil/presentation/le-laboratoire/"; + char* youtube = "https://www.youtube.com/"; + char* youtubeHistory = "https://www.youtube.com/feed/history"; + char* youtubeSubs = "https://www.youtube.com/feed/subscriptions"; + char* aRetirer = "/A/retirer"; + + + creer_pagerank(&p, 5); + pagerank_add_URL(&p, google); + pagerank_add_URL(&p, fichierNico); + pagerank_add_URL(&p, lipn); + pagerank_add_URL(&p, lipnA3); + pagerank_add_URL(&p, lipnAOC); + pagerank_add_URL(&p, lipnPresentation); + pagerank_add_URL(&p, youtube); + pagerank_add_URL(&p, youtubeHistory); + pagerank_add_URL(&p, youtubeSubs); + pagerank_add_URL(&p, aRetirer); + + pagerank_afficher(&p); + + printf("La première URL ajoutée est %s\n", pagerank_get_URL_i(&p, 0)); + printf("L'indice de l'URL du LIPN est %d\n", pagerank_find_indice_URL(&p, lipn)); + + pagerank_remove_URL(&p, aRetirer); + + pagerank_afficher(&p); + + pagerank_relier_URL(&p, google, youtube); + pagerank_relier_URL(&p, youtube, youtubeHistory); + pagerank_relier_URL(&p, youtube, youtubeSubs); + pagerank_relier_URL(&p, lipn, lipnA3); + pagerank_relier_URL(&p, lipn, lipnAOC); + pagerank_relier_URL(&p, lipn, lipnPresentation); + pagerank_relier_URL(&p, lipnPresentation, lipnA3); + pagerank_relier_URL(&p, lipnPresentation, lipnAOC); + pagerank_relier_URL(&p, fichierNico, google); + pagerank_afficher(&p); + + pagerank_ecrire_dot(&p, fichier1); + + printf("\"%s\" %s \"%s\"\n", fichierNico, google, ((pagerank_link_to(&p, fichierNico, google)) ? "a un lien vers" : "n'a pas de lien vers")); + + pagerank_delier_URL(&p, fichierNico, google); + + pagerank_ecrire_dot(&p, fichier2); + + printf("\"%s\" %s \"%s\"\n", fichierNico, google, ((pagerank_link_to(&p, fichierNico, google)) ? "a un lien vers" : "n'a pas de lien vers")); + + printf("Retirons maintenant \"%s\" du pagerank\n", google); + + pagerank_remove_URL(&p, google); + + pagerank_ecrire_dot(&p, fichier3); + pagerank_afficher(&p); + + pagerank_detruire(&p); + return EXIT_SUCCESS; +} -- GitLab