Pourquoi et quand devrais-je utiliser des structures de données de pile ou de file d'attente au lieu de tableaux/listes? Pouvez-vous s'il vous plaît montrer un exemple pour un état qui sera mieux si vous utiliserez pile ou file d'attente?
Parce qu'ils aident à gérer vos données d'une manière plus particulière que les tableaux et les listes.
La file d'attente est premier entré, premier sorti (FIFO)
La pile est dernier entré, premier sorti (LIFO)
Les tableaux et les listes sont en accès aléatoire. Ils sont très flexibles et facilement corruptibles. SI vous souhaitez gérer vos données en tant que FIFO ou LIFO, il est préférable d’utiliser ces collections déjà implémentées.
Vous avez visité une cafétéria, non? et vu une pile d'assiettes? Lorsqu'une plaque propre est ajoutée à la pile, elle est placée sur le dessus. Lorsqu'une plaque est retirée, elle est retirée par le haut. C'est ce qu'on appelle le dernier entré, premier sorti (LIFO). Une pile d’ordinateurs ressemble à cela, sauf qu’elle contient des nombres et que vous pouvez en créer un dans un tableau ou une liste, si vous le souhaitez. (Si la pile d'assiettes comporte un ressort en dessous, on vous dit de "pousser" une sur le dessus, et lorsque vous en retirez une, vous la "détachez". C'est de là que viennent ces mots.)
À la cafétéria, allez à l’arrière, où on lave la vaisselle. Ils ont un tapis roulant où ils placent des assiettes à laver à une extrémité et ils sortent à l'autre extrémité, dans le même ordre. C'est une file d'attente ou premier entré premier sorti (FIFO). Vous pouvez également créer l'un de ceux-ci à partir d'un tableau ou d'une liste si vous le souhaitez.
À quoi servent-ils? Eh bien, supposons que vous ayez une structure de données arborescente (qui ressemble à un vrai arbre en bois, sauf qu’elle soit à l’envers) et que vous souhaitiez écrire un programme pour la parcourir complètement afin d’imprimer toutes les feuilles.
Une solution consiste à faire une promenade depth-first. Vous commencez par le tronc et allez à la première branche, puis à la première branche de cette branche, et ainsi de suite, jusqu'à ce que vous arriviez à une feuille et l'imprimiez. Mais comment sauvegardez-vous pour vous rendre à la prochaine branche? Eh bien, chaque fois que vous descendez une branche, vous "envoyez" des informations dans votre pile, et lorsque vous sauvegardez, vous les "affichez" de nouveau, et cela vous indique quelle branche prendre ensuite. C'est ainsi que vous gardez une trace de la branche à faire à chaque point.
Une autre façon est une promenade width-first. À partir du coffre, vous numérotez toutes les branches du coffre et placez ces numéros dans la file d'attente. Ensuite, vous prenez un numéro à l’autre extrémité, allez dans cette branche, et pour chaque branche sortant de it, vous les numérotez à nouveau (consécutivement avec le premier) et les mettez dans la file d’attente. En continuant de le faire, vous visiterez d’abord les branches situées à une branche du tronc. Ensuite, vous visiterez toutes les branches situées à 2 branches du tronc, etc. Finalement, vous arriverez aux feuilles et vous pourrez les imprimer.
Ce sont deux concepts de base en programmation.
Lorsque vous souhaitez appliquer un certain modèle d'utilisation à votre structure de données. Cela signifie que lorsque vous déboguez un problème, vous ne devez pas vous demander si quelqu'un a inséré au hasard un élément au milieu de votre liste, dérangeant certains invariants.
Outre l'application des règles d'utilisation déjà mentionnée, il existe également un problème de performances. Lorsque vous souhaitez supprimer quelque chose du début d'un tableau ou d'une liste (ArrayList), cela prend généralement O(n) temps, mais pour une file d'attente, cela prend O(1). Cela peut faire une énorme différence s'il y a beaucoup d'éléments.
Les tableaux/listes et les piles/files d'attente ne sont pas des concepts mutuellement exclusifs. Enfoncez les piles ou les mises en œuvre de file d'attente que vous trouvez utilisent presque certainement des tableaux ou des listes sous le capot.
Les structures de tableau et de liste fournissent une description de la manière dont les données sont stockées, avec des garanties de la complexité des opérations fondamentales sur les structures.
Les piles et les files d'attente fournissent une description détaillée de la manière dont les éléments sont insérés ou supprimés. FIFO pour les files d'attente, FILO pour les piles.
Par exemple. Si vous implémentez une file d'attente de messages, vous utiliserez une file d'attente. Mais la file d'attente elle-même peut stocker chaque message dans une liste. "Pousser" un message en ajoutant au début de la liste, "popping" un message prenant à la fin de la liste.
C'est une question d'intention. Les piles et les files d'attente sont souvent implémentées à l'aide de tableaux et de listes, mais l'ajout et la suppression d'éléments sont définis de manière plus stricte.
La pile et la file d'attente sont des moyens plus avancés de gérer une collection que le tableau lui-même, qui n'établit aucun ordre dans le comportement des éléments à l'intérieur de la collection.
La pile (LIFO - dernier entré, premier sorti) et une file d'attente (FIFO - premier entré, premier sorti) établissent et ordonnent dans lesquels vos éléments sont insérés et supprimés d'une collection.
Vous pouvez utiliser un tableau ou une liste liée en tant que structure de stockage pour implémenter le modèle de pile ou de file d'attente. Ou encore, créez avec ces structures de base des modèles plus complexes tels que des arbres binaires ou des files d'attente prioritaires, ce qui pourrait également apporter un ordre dans l'insertion et la suppression d'éléments, mais également leur tri dans la collection.
Une pile ou une file d'attente est une structure de données logique; il serait implémenté sous les couvertures avec une structure physique (par exemple, liste, tableau, arbre, etc.)
Vous êtes invités à "rouler votre propre" si vous voulez, ou profiter d'une abstraction déjà mise en œuvre.
Je pense que pile et file d'attente sont des concepts d'accès à la mémoire qui sont utilisés en fonction de la demande de l'application. D'autre part, tableau et listes sont deux techniques d'accès en mémoire et sont utilisées pour implémenter les concepts de pile (LIFO) et de file d'attente (FIFO).
Il existe des algorithmes plus faciles à conceptualiser, écrire et lire avec des piles plutôt qu'avec des tableaux. Cela rend le code plus propre avec moins de logique de contrôle et d'itérateurs puisque ceux-ci sont présupposés par la structure de données elle-même.
Par exemple, vous pouvez éviter un appel "inversé" redondant sur un tableau dans lequel vous avez poussé les éléments que vous souhaitez afficher en ordre inverse, si vous avez utilisé une pile.
La question est ambiguë, car vous pouvez représenter le type de données abstrait d’une pile ou d’une file d’attente à l’aide d’un tableau ou d’une structure de données liée.
La différence entre une implémentation de liste liée d'une pile ou d'une file d'attente et une implémentation de tableau a le même compromis de base que n'importe quel tableau par rapport à une structure de données dynamique.
Une file d'attente/pile liée possède des insertions/suppressions flexibles et à grande vitesse avec une implémentation raisonnable, mais nécessite plus de stockage qu'un tableau. Les insertions/suppressions sont peu coûteuses aux extrémités d'un tableau jusqu'à ce que vous manquiez d'espace; une implémentation de matrice d'une file d'attente ou d'une pile nécessitera plus de travail de redimensionnement, car vous auriez besoin de copier l'original dans une structure plus grande (ou échouer avec une erreur de débordement).