PRIORITY QUEUE

SharpMao Messages postés 1024 Date d'inscription mardi 4 février 2003 Statut Membre Dernière intervention 7 juin 2010 - 11 mai 2007 à 09:33
cs_Bidou Messages postés 5487 Date d'inscription dimanche 4 août 2002 Statut Membre Dernière intervention 20 juin 2013 - 13 mai 2007 à 11:14
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/42654-priority-queue

cs_Bidou Messages postés 5487 Date d'inscription dimanche 4 août 2002 Statut Membre Dernière intervention 20 juin 2013 61
13 mai 2007 à 11:14
SharpMao> J'ai mis à jour pour que les éléments de même priorités restent dans un ordre FIFO.
cs_Warny Messages postés 473 Date d'inscription mercredi 7 août 2002 Statut Membre Dernière intervention 10 juin 2015
11 mai 2007 à 15:59
Je n'ai pas de classe toute faite, c'est peut-être l'occasion justement.
cs_Bidou Messages postés 5487 Date d'inscription dimanche 4 août 2002 Statut Membre Dernière intervention 20 juin 2013 61
11 mai 2007 à 15:34
Euh j'ai pas trop le temps de regarder en détail pour le moment. Si tu as une classe générique qui s'occupe de ça, je serais curieux de faire quelques teste pour voir la différence entre les deux...
cs_Warny Messages postés 473 Date d'inscription mercredi 7 août 2002 Statut Membre Dernière intervention 10 juin 2015
11 mai 2007 à 15:16
Non, c'est pas la peine, va voir cet excelent article de wikipédia : http://fr.wikipedia.org/wiki/B-Arbre
et notamment le lien de visualisation d'un b-arbre pour te faire une idée. C'est la méthode utilisée pour insérer les élements dans une base de données.
cs_Bidou Messages postés 5487 Date d'inscription dimanche 4 août 2002 Statut Membre Dernière intervention 20 juin 2013 61
11 mai 2007 à 15:03
Autre chose: comment tu fais pour ajouter une Queue dans ta liste de queues?
Tu es obligé de vérifier si elle est existante ou pas, non? Donc tu dois itérer à travers toutes tes queues pour voir si elle existe? même chose quand tu en supprimes une?
cs_Warny Messages postés 473 Date d'inscription mercredi 7 août 2002 Statut Membre Dernière intervention 10 juin 2015
11 mai 2007 à 14:34
C'est pas faux, mais dans les faits j'aurais difficilement plus de 5 à 10 niveaux de priorités.
De plus si je suis dans le cas que tu décris et que je dois vraiment optimiser le classement, j'utiliserai un algorithme B-TREE et je serais toujours plus efficace.
Pour l'instant le seul problème pour lequel je suis obligé d'utiliser un algo de classement, c'est quand je fais de la 3D et que je dois classer des polygones, parce que leur définition utilise plus d'une dimension.
Dans le cas où mes élements n'ont qu'une dimension, je peux les classer. Dans le cas d'une queue à priorité, mon élément de priorité a rarement plus d'une dimension et mon algo, éventuellement classé en arbre, est toujours plus rapide.
cs_Bidou Messages postés 5487 Date d'inscription dimanche 4 août 2002 Statut Membre Dernière intervention 20 juin 2013 61
11 mai 2007 à 14:21
Warny> Imaginons que j'aie 1000 éléments, 500 clefs différentes. Tu as 500 queues à construire (dynamiquement si tu veux...). Le temps que tu construises tes 500 queues en boucles, j'ai déjà eu le temps de traiter quelques centaines de millieurs d'élément... Ma solution n'utilise effectivement qu'une List de taille n.

SharpMao> Oui, tu as raison ;-)
SharpMao Messages postés 1024 Date d'inscription mardi 4 février 2003 Statut Membre Dernière intervention 7 juin 2010 69
11 mai 2007 à 14:16
Hello,

Pour les SortedList, tu as raison.
Par contre, corrige-moi si je me trompe, mais cette méthode ne donne pas de queue FIFO avec des éléments de même priorité.
cs_Warny Messages postés 473 Date d'inscription mercredi 7 août 2002 Statut Membre Dernière intervention 10 juin 2015
11 mai 2007 à 14:07
Mon principe est de faire une queue par niveau de priorité :
Queue[0]
Queue[1]
Queue[2]
Queue[3]
Queue[4]
...
Eventuellement créées dynamiquement (c'est pas la peine de créer 65535 queues si tu a ce nombre de niveaux de priorités) et détruites dynamiquement quand elles sont vides.
Si tu as un niveau de priorité 4 à mettre, tu le mets dans la liste 4 soit O(1)
Tu ne peux lire dans la liste 4 que si les listes précédente sont vides. Si c'est le cas ta complexité est... O(1). Tu prends toujours le premier élement de la première liste.
Y a pas plus efficace.
La question est pourquoi trier quand on peut classer ?
cs_Bidou Messages postés 5487 Date d'inscription dimanche 4 août 2002 Statut Membre Dernière intervention 20 juin 2013 61
11 mai 2007 à 13:37
Je ne comprend pas trop où tu veux en venir. La solution que je propose pour implémenter une PriorityQueue n'est pas révolutionnaire, c'est la méthode qui est recommandé (car la plus rapide). Je n'ai pas inventé l'algorithme HeapSort...

Si tu insères sans trié, tu insères en O(1) mais il te faut O(n) pour faire sortir l'élément
IN : O(1)
OUT: O(n)

Si tu insères trié, tu insères en O(n) mais il te faut O(1) pour faire sortir l'élément
IN : O(n)
OUT: O(1)

Si tu utilises un Heap, tu insères en O(log n) et tu fais sortir l'élément en O(log n) également
IN : O(log n)
OUT: O(log n)


Il est évident que la dernière solution est de loin la meilleure, car même si tu insères (respectivement sort) en O(1) tu vas sortir (respectivement insérer) en O(n). C'est à dire que tu sera un tout petit peu meilleur avec ton O(1) mais largement largué ensuite par ton O(n) (plus n sera élevé, plus tu seras largué)

Exemple avec 1000 éléments:

Ma solution:
IN : ~O(10)
OUT: ~O(10)

la tienne:

IN : O(1) respectivement O(1000)
OUT: O(1000) respectivement O(1)

T'es un tout petit peu meilleur avec O(1) par rapport à O(10), mais clairement très loin derrière pour O(1000) comparé à un O(10).
Je ne sais pas si tu me suis ???
cs_Warny Messages postés 473 Date d'inscription mercredi 7 août 2002 Statut Membre Dernière intervention 10 juin 2015
11 mai 2007 à 13:21
je compte O(n) avec n étant le nombre d'élément que j'insère dans ma queue. Si je ne m'interresse qu'à 1 élement je suis en O(1) (je ne peux pas faire mieux).
De la même façon, en moyenne en insertion pour 1 élement tu est en O(log(n)) ou n est le nombre d'éléments déjà présents dans ta queue. Si tu dois classer l'ensemble des éléments que tu insère, il faut compter au moins une fois chaque élément O(n) que tu classes O(log(n)). Soit au total O(n*log(n)).
Pour récapituler :
+ pour 1 élement :
- tri-insertion : O(log(n))
- classement-arbre : O(1)
+ pour n élements :
- tri-insertion : O(n*log(n))
- classement-arbre : O(n)
cs_Bidou Messages postés 5487 Date d'inscription dimanche 4 août 2002 Statut Membre Dernière intervention 20 juin 2013 61
11 mai 2007 à 13:02
Le but est justement de ne pas tout comparer pour être plus rapide! Puisque les éléments sont triés dans un arbre binaire (et trié selon l'implémentation du CompareTo) on obtient une insertion triée (enqueue) en O(log n) et une supression (dequeue) en O(log n) également car on ne doit justement pas parcourir tous les éléments de l'arbre !

Tu peux faire une recherche sur le net, tu verras qu'effectivement je ne te raconte pas de bêtise et qu'un enqueue et dequeue se font bien en O(log n) si on implémente un Heap (ce qui est, encore une fois, bien plus rapide que ton O(n) que tu proposes...)
cs_Warny Messages postés 473 Date d'inscription mercredi 7 août 2002 Statut Membre Dernière intervention 10 juin 2015
11 mai 2007 à 12:14
tu te trompe de calcul. O(log(n)) signifie que tu ne compare pas tous les élements.
Comme tu fais un tri à bulle, tu compares tous les élements à l'ensemble des autres, ce qui te fait une complexité en O(n^2)
La méthode de tri la plus rapide est le tri-fusion qui approche le O(n*log(n)) - c'est une moyenne -
La méthode de classement (et plus de tri) la plus rapide et l'arbre de classement qui permet de ranger un élement dans un arbre en fonction de sa valeur et sa complexité est en O(n) et plus précisement x*n ou x est la longueur de la valeur à classer. C'est ce que j'utilise pour répondre à ce problème.
cs_Bidou Messages postés 5487 Date d'inscription dimanche 4 août 2002 Statut Membre Dernière intervention 20 juin 2013 61
11 mai 2007 à 12:07
Supposons que tu aies raisons... (j'ai pas vérifié mais je te fais confiance).
Mon arbre binaire est toujours beaucoup beaucoup plus rapide avec O(log n) que ton O(n)... (en fait, incomparablement plus rapide pour des listes avec beaucoup d'éléments).
cs_Warny Messages postés 473 Date d'inscription mercredi 7 août 2002 Statut Membre Dernière intervention 10 juin 2015
11 mai 2007 à 12:04
Non, la complexité obtenu est en O(n). En fait, tu ne fais pas de classement.
Si un document en priorité 1 doit passer forcement avant un document en priorité 2, tu mets ton document dans la file d'attente de priorité 1 et tu lis cette file en premier. Quand elle est vide tu lis la file de priorité 2 et ainsi de suite.
L'écriture se fait toujours à la fin de la file et la lecture se fait toujours au début. Je ne classe donc jamais les élements.
cs_Bidou Messages postés 5487 Date d'inscription dimanche 4 août 2002 Statut Membre Dernière intervention 20 juin 2013 61
11 mai 2007 à 11:58
SharpMao> Une SortedList est un dictionary trié, ce qui ne m'arrange pas trop pour ma liste générique (il faudrait forcé de dérivé d'une interface pour qu'on soit sûr que l'object contient par exemple une property Key). De plus, comme c'est un dictionary, il n'accepte pas les doublons (alors qu'une Priority queue, peut avoir des éléments avec une clef identique).

Pour finir, si on utilise le tris automatique de la SortedList, on se retrouve certainement (pas vérifié) avec une complexité de l'ordre de O(n^2) voire O(n log n) alors que mon implémentation avec un arbre binaire (un heap en fait) travail en O(log n) ce qui est bien meilleur (on tend presque à avoir un temps constant pour une grosse quantité d'éléments).

Warny> En utilisant ta manière, non seulement on a une place utilisée en mémoire beaucoup plus grande, mais en plus on a une complexité à coucher dehors (au moins O(n^2) je dirais au premier abord).

J'espère ne pas m'être trompé dans mes calculs, mais ça devrait être correct.
cs_Warny Messages postés 473 Date d'inscription mercredi 7 août 2002 Statut Membre Dernière intervention 10 juin 2015
11 mai 2007 à 10:31
Je pense que tu t'embête beaucoup à classer tes élements.
Une priorityqueue est avant tout une liste de queue dont certaines doivent être traités avant les autres.
Tu peux dont faire une liste de queue et revoyer le premier élement de la première queue non vide.
SharpMao Messages postés 1024 Date d'inscription mardi 4 février 2003 Statut Membre Dernière intervention 7 juin 2010 69
11 mai 2007 à 09:33
Intéressant, mais pourquoi ne pas avoir utilisé une SortedList au lieu de la list. De cette manière, tu évites le tri manuel.