Je ne vois pas pourquoi la récursivité serait encore nécessaire avec un tableau ordonné (ou alors j'ai vraiment zappé quelque chose). La récursivité avait pour but de remonter l'arbre de dépendance pour recalculer les ancêtres avant les descendant.
Le but du tableau ordonnée est justement d'effectuer ce classement de dépendance avant. Il suffit donc de parcourir le tableau dans le bon ordre et de calculer les éléments les uns après les autres. Une simple boucle suffit.
Dans tout les cas, le tableau ordonné avec des numéros ne me semble pas la solution la plus adaptée. Le fait de passer par une numérotation reste problématique si l'on a plusieurs éléments modifiés avant de lancer le calcul, cela risque d’engendrer la renumérotation les lignes.
En partant de l'exemple suivant :
Si l'on modifie le composant 1, cela engendre le recalcul d'article 2, on a donc dans notre tableau numéroté
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 article 1 - composant 1 - composant 2 article 2 - composant 1 - composant 3 composant 3 - composant 4Admettons que dans le même traitement, on modifie aussi composant 3, du coup lors de l'ajout de composant 3, il va falloir le glisser entre la ligne 1 et la ligne 2, d'ou renumérotation.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 1 - composant 1 2 - article 2
Voici un bout de code qui me semble être correct (pas vraiment testé à fond) et fort possible qu'il y ai plus simple. Cette version est relativement complexe vu que j'ai voulu gérer le fait que plusieurs éléments puissent être modifiés avant que le traitement ne soit lancé.
et pour tester ce bout de code :
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
60
61
62
63
64
65
66
67
68
69 stElementATraiter est une structure element est un cElement dynamique doitEtreCalculé est un booléen FIN cElement est une Classe nomElement est une chaîne composants est un tableau associatif de cElement dynamique parents est un tableau associatif de cElement dynamique GLOBAL listeDesElements est un tableau associatif de cElement dynamique elementATraiter est un tableau associatif de stElementATraiter ordreTraitement est un tableau de chaîne FIN PROCEDURE Constructeur(nom est une chaîne) listeDesElements[nom] = objet nomElement = nom PROCEDURE Destructeur() PROCEDURE _ajouteComposant(element est un cElement dynamique) composants[element.nomElement] = element element.parents[nomElement] = objet PROCEDURE GLOBAL _initTraitement() TableauSupprimeTout(elementATraiter) TableauSupprimeTout(ordreTraitement) PROCEDURE GLOBAL _ajouteElementModifie(unElement est un cElement dynamique, chemin est une chaîne = "", bDoitEtreCalculer est un booléen = Vrai) unComposant est un cElement dynamique unParent est un cElement dynamique POUR TOUT unComposant DE unElement.composants SI Position(chemin, "/" + unComposant.nomElement) = 0 ALORS _ajouteElementModifie(unComposant, chemin, Faux) FIN FIN _ajouteATraiter(unElement, bDoitEtreCalculer) SI bDoitEtreCalculer ALORS POUR TOUT unParent DE unElement.parents _ajouteElementModifie(unParent, "/" + unElement.nomElement + chemin) FIN FIN PROCEDURE GLOBAL PRIVÉ _ajouteATraiter(unElement est un cElement, bDoitEtreCalculer est un booléen) SI elementATraiter[unElement.nomElement]..Occurrence = 0 ALORS TableauAjoute(ordreTraitement, unelement.nomElement) unElementAtraiter est un stElementATraiter unElementAtraiter.element = unelement unElementAtraiter.doitEtreCalculé = bDoitEtreCalculer elementATraiter[unElement.nomElement] = unElementAtraiter SINON SI bDoitEtreCalculer ALORS elementATraiter[unElement.nomElement].doitEtreCalculé = bDoitEtreCalculer FIN FIN PROCEDURE GLOBAL _afficheCalculAEffectuer() POUR TOUT unNomElement DE ordreTraitement SI elementATraiter[unNomElement].doitEtreCalculé ALORS Trace(elementATraiter[unNomElement].element.nomelement) FIN FINle résultat sera
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 article1 est un cElement("article1") article2 est un cElement("article2") composant1 est un cElement("composant1") composant2 est un cElement("composant2") composant3 est un cElement("composant3") composant4 est un cElement("composant4") article1._ajouteComposant(composant1) article1._ajouteComposant(composant2) article2._ajouteComposant(composant1) article2._ajouteComposant(composant3) composant3._ajouteComposant(composant4) cElement._initTraitement() cElement._ajouteElementModifie(composant4) cElement._ajouteElementModifie(composant1) cElement._afficheCalculAEffectuer()Sur la fin de l'exemple, on utilise _initTraitement pour réinitialiser avant de lancer un nouveau traitement, _ajouteElementModifie pour ajouter un élément qui a été modifié et _afficheCalculAEffectuer pour afficher les traitements à effectuer.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 composant4 composant3 composant1 article2 article1
Le principe général est de mémoriser les dépendances lors de l'ajout des éléments et ensuite de parcourir ces dépendances pour construire l'arbre de résolution. Cette version par contre plante lamentablement si l'on a défini un ensemble d’éléments qui contient une référence circulaire.
N'hésitez pas à faire des tests et me dire si ça correspond et si ça fonctionne.
Partager