IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PHP & Base de données Discussion :

Recherche de chemins dans une table [MySQL]


Sujet :

PHP & Base de données

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 26
    Points : 11
    Points
    11
    Par défaut Recherche de chemins dans une table
    Bonjour, j'ai un problème pour réaliser une fonction qui me permette de rechercher un chemin dans ma base de données.
    Par exemple prennons une table qui contient 3 champs, dans le 1er champs se trouve un ID, dans le 2nd un nom,de ville par exemple, et dans le 3éme un autre nom de ville, une ligne correspond à ville 1 est relier à ville2.

    ex du contennu de la table :

    | ID | nom 1 | nom 2 |
    | 1 | AAA | BBB |
    | 2 | CCC | AAA |
    | 3 | BBB | DDD |
    | 4 | AAA | YYY |
    | 5 | EEE | YYY |
    | 6 | DDD | EEE |

    Si l'utilisateur demande par exemple les chemins pour relier AAA à YYY, le progrmme devra donner comme reponse :
    1 - AAA | BBB
    1 - BBB | DDD
    1 - DDD | EEE
    1 - EEE | YYY
    2 - AAA | YYY

    Je n'ai aucun pb pour afficher ce genre de réponse.
    Pour engendrer cette réponse je parcours la table à la recherche de la ville de depart, ensuite si je la trouve je mets le nom dans un tableau à 2 dimensions(chaque ligne correspond à un chemin possible entre 2 villes), et je reparts de la 2éme ville(devient la nouvelle ville de depart), ainsi de suite jusqu'à temps de trouver le nom de la ville finale.
    Mon problème est que le programme s'arrète si jamais il rentre (dans l'exemple) dans la 2éme ligne, il affichera :
    1 - AAA | CCC
    Je ne trouve pas comment faire pour revenir en arrière et repartir par un autre chemin (je pense qu'il faut utiliser un arbre n-aire mais je ne sais pas comment l'écrire!)

  2. #2
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 26
    Points : 11
    Points
    11
    Par défaut
    Ou si quelqun à une proposition d'algo sa pourrait pas mal m'aider !

  3. #3
    Rédacteur
    Avatar de marcha
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2003
    Messages
    1 571
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 571
    Points : 2 351
    Points
    2 351
    Par défaut
    Salut,

    J'ai pas compris si tu avais besoin de tous les chemins possibles
    ou du chemin le plus court.

    Je me suis amusé à faire tous les chemins possibles

    La première partie de mon code construit une liste de relations bidirectionnelles.

    J'espère que ça peut t'aider, et que tu pourra adapter cette idée
    avec ta db.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    <?
    $relations[] = "AAA|BBB";
    $relations[] = "CCC|AAA";
    $relations[] = "BBB|DDD";
    $relations[] = "AAA|YYY";
    $relations[] = "EEE|YYY";
    $relations[] = "DDD|EEE";
     
    foreach($relations as $relation) {
    	list($ville1, $ville2) = explode('|', $relation);
    	$links[$ville1][] = $ville2;
    	$links[$ville2][] = $ville1;	
    } 
     
    print_r($links); // liste des relations
     
    function findPath($from, $to, $n, $stack=array()) {
    	global $paths, $links;
    	if(!$stack) $paths = array(); // init le tableau des résultats
    	$stack[] = $from;
    	foreach($links[$from] as $ville) {
    		if($ville==$stack[0]) continue; // boucle
    		if($ville==$to) $paths[] = array_merge($stack, $to);
    		else if($n>0 && !in_array($ville, $stack)) findPath($ville, $to, $n-1, $stack);
    	}
    }
     
    $max_path = count($links);
    // chemina de 'AAA' à 'DDD'
    findPath('AAA', 'DDD', $max_path);
    print_r($paths);
     
    // chemina de 'CCC' à 'BBB'
    findPath('CCC', 'BBB', $max_path);
    print_r($paths);
     
     
     
    ?>
    Si ton code fait plus d'une ligne, c'est que tu as mal choisi ton langage !

  4. #4
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 26
    Points : 11
    Points
    11
    Par défaut
    En fait, j'ai besoin de tous les chemins, donc ce que tu as fais est bon, par contre je ne comprend pas tous ce que fait ta fonction pourrais tu la commenter un peut plus stp?( se n'était pas la peine de decouper la chaine par le caractère | , c'était juste pour dessiner la table, mais merci quand même )

  5. #5
    Rédacteur

    Avatar de Yogui
    Homme Profil pro
    Directeur technique
    Inscrit en
    Février 2004
    Messages
    13 721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Février 2004
    Messages : 13 721
    Points : 29 985
    Points
    29 985
    Par défaut
    Salut

    J'ai une suggestion concernant le schéma de ta table. Je ne sais pas si ce n'est qu'une table d'exemple mais, d'habitude, l'intérêt d'avoir un identifiant dans une table est de permettre de l'utiliser justement pour ce que tu as fait (l'utiliser dans une autre table).
    Mais bon, ça reste une idée directrice globale car cela implique l'utilisation du concept de FOREIGN KEY, qui est une contrainte mieux utilisée pour une autre table que celle de laquelle on parle.

  6. #6
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 26
    Points : 11
    Points
    11
    Par défaut
    En fait tous ce trouve dans cette table (il n'y en a qu'une), et je la simplifie pour obtenir 10 fois moins de lignes, je n'ai donc pas besoin d'utiliser de clefs etrangères pour cette recherche !
    Mais je voulais savoir en fait tu utilises :
    $links[$ville][] pour mettre dans links toutes les villes qui sont reliées à ville?
    $stack pour mettre un chemin?
    $paths pour mettre les chemins possibles?

  7. #7
    Rédacteur
    Avatar de marcha
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2003
    Messages
    1 571
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 571
    Points : 2 351
    Points
    2 351
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    <?
    $relations[] = "AAA|BBB";
    $relations[] = "CCC|AAA";
    $relations[] = "BBB|DDD";
    $relations[] = "AAA|YYY";
    $relations[] = "EEE|YYY";
    $relations[] = "DDD|EEE";
     
    // ici je parcours les relations pour établir une liste de connexion par ville
    // vers les autres, c'est à dire, pour savoir facilement à quelles ville est
    // reliée une ville. Par exemple $links['AAA'] contient la liste des villes
    // accèssible depuis AAA
    foreach($relations as $relation) {
       list($ville1, $ville2) = explode('|', $relation);
       $links[$ville1][] = $ville2;
       $links[$ville2][] = $ville1;   
    }
     
    print_r($links); // liste des relations
     
    // cette fonction s'appelle recursivement, la tableau $links (expliqué 
    // plus haut) facilite les choses
    // $paths est un tableau qui est complèté chaque fois qu'un chemin est
    // trouvé. c'est le réultat.
    function findPath($from, $to, $n, $stack=array()) {
       global $paths, $links;
       if(!$stack) $paths = array(); // init le tableau des résultats
       $stack[] = $from;
       // parcoure la liste des toutes les connexions depuis la ville $from
       foreach($links[$from] as $ville) {
          // $stack contient toutes les villes traitée dans un chemin possible,
          // si la ville connectée à $from est la ville originale ($from du 
          // premier appel à fintPath), c'est qu'on tourne en rond, il faut sauter
          // cette recherche.
          if($ville==$stack[0]) continue; // boucle
          // si la ville correspond à la destination finale c'est qu'on a trouvé un
          // chemin possible, on places les villes parcourue ($stack) dans le
          // tableau des chemins possibles.
          if($ville==$to) $paths[] = array_merge($stack, $to);
          // sinon, on rappel findPath pour qu'il cherche tous les chemin 
          // possible à partir d'une ville connectée à $from, soit $ville
          // c'est un appel récursif, c'est ce qui est difficile à comprendre si
          // on a pas l'habitute de la recursivité.
          else if($n>0 && !in_array($ville, $stack)) findPath($ville, $to, $n-1, $stack);
       }
    }
     
    $max_path = count($links);
    // chemina de 'AAA' à 'DDD'
    findPath('AAA', 'DDD', $max_path);
    print_r($paths);
     
    // chemina de 'CCC' à 'BBB'
    findPath('CCC', 'BBB', $max_path);
    print_r($paths);
     
     
     
    ?>
    Si ton code fait plus d'une ligne, c'est que tu as mal choisi ton langage !

  8. #8
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 26
    Points : 11
    Points
    11
    Par défaut
    Perso j'utilise :
    echo "<pre>";
    print_r($links);
    echo "</pre>";
    pour mieux voir le resultat (tout petit detaille) mais sinon sa marche super bien , je ne sais pas pourquoi j'ai utilisé de l'iteratif à la place du recursif , je voulais faire trop compliqué, ce n'était pas du tout comme sa que je voyais la solution !
    Encore merci et bravo

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [pl-sql] Recherche de doublons dans une table
    Par tommey dans le forum Oracle
    Réponses: 1
    Dernier message: 08/11/2006, 22h53
  2. Réponses: 7
    Dernier message: 21/08/2006, 16h27
  3. [MySQL] recherche un mot dans une table
    Par hubidev dans le forum PHP & Base de données
    Réponses: 1
    Dernier message: 17/03/2006, 20h06
  4. recherche Date nulle dans une table
    Par lol_adele dans le forum Bases de données
    Réponses: 6
    Dernier message: 16/04/2004, 14h06
  5. Recherche de donnee dans une table associée
    Par josoft dans le forum Requêtes
    Réponses: 2
    Dernier message: 14/07/2003, 15h22

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo