Comment fonctionne une liste de sauts?

14

Pour un devoir, j'ai besoin de comprendre comment fonctionne une liste de sauts .

Je programme depuis un peu plus de 2 ans maintenant (je sais que ce n'est pas si long en réalité), et je n'ai même jamais entendu parler d'une liste à sauter.

J'ai parcouru tous les guides que je peux trouver, et je comprends encore à peine comment ils fonctionnent. J'ai même cherché Code Review pour un exemple d'implémentation et trouvé un seul examen; et ce n'est même pas une implémentation complète. J'ai regardé l'exemple d'implémentation fourni par le cours, et c'est absolument atroce. Entre le manque de méthodes appropriées et les noms de variables à une seule lettre, je n'ai aucune idée de comment cela fonctionne.

Comment fonctionne une liste de sauts? La connaissance d'une liste de sauts est-elle nécessaire pour comprendre des structures de données plus avancées?

Carcigenicate
la source
1
Les conseils en éducation sont explicitement hors sujet . Étant donné qu'il s'agit de structures de données et non d'éducation, j'ai modifié votre question pour supprimer ces parties. Je recommande également de lire le lien Wikipédia dans lequel j'ai modifié et de mettre à jour votre question avec des détails plus précis sur ce que vous ne comprenez toujours pas.
@Snowman Merci. J'ai seulement ajouté cela pour éviter les commentaires comme "demandez à votre professeur". Je garderai cela à l'esprit pour la prochaine fois. Et vous avez ajouté une modification qui change la question. À la fin, je ne demande pas aux gens d'expliquer comment ils fonctionnent car je suppose que c'est hors sujet (même si je ne serais pas contre une bonne explication). Je veux juste savoir à quel point ils sont importants à apprendre.
Carcigenicate
1
@Carcigenicate expliquant comment ils fonctionnent est en fait plus sur le sujet que de demander si vous les verrez dans le monde réel. Nous ne pouvons que deviner ce que vous ferez et les différents domaines. Demander si nous les voyons dans le monde réel nous interroge pour "oui, je les vois et les utilise" ou "non, je n'en ai jamais entendu parler" - ce qui ne donne pas de bonnes réponses utiles à d'autres personnes à lire.

Réponses:

29

Autrefois, dans la classe des structures de données, nous avons appris comment fonctionnaient les arbres AVL . J'aurais eu ça dans une de mes classes, mais l'instructeur a dit "vous ne l'utiliserez jamais réellement" et nous a plutôt fait apprendre 2-3 arbres et arbres b * à la place. C'étaient des jours où la mémoire était serrée et les processus étaient enfilés individuellement. Vous n'avez pas utilisé de deque lorsqu'une liste liée individuellement fonctionnerait aussi bien.

La liste de sauts est beaucoup plus courante aujourd'hui, avec plus de mémoire disponible et d'accès concurrentiel étant un problème (vous n'avez pas besoin de verrouiller beaucoup du tout lorsque vous agissez en tant qu'écrivain dans une liste de sauts - par rapport à tout avec une arborescence AVL).

Franchement, c'est ma structure de données préférée maintenant en ce sens que je peux facilement raisonner sur la façon dont cela fonctionne en dessous et où il sera avantageux ou désavantageux d'utiliser.

Vous n'aurez pas besoin d'en écrire une à partir de zéro (à moins que vous ne la receviez comme une question d'entrevue - mais alors vous êtes tout aussi susceptible de mettre en œuvre une arborescence AVL).

Vous êtes allez avoir besoin de comprendre pourquoi vous souhaitez sélectionner un ConcurrentSkipListMapen Java plutôt qu'un HashMapou TreeMapou l' une des autres implémentations de carte.


Pour comprendre comment cela fonctionne, vous devez comprendre le fonctionnement d'un arbre binaire. Attendez, permettez-moi de modifier cela. Vous devez comprendre le fonctionnement d'un arbre binaire équilibré . Sans équilibrer un arbre binaire, vous n'obtenez aucun avantage réel avec sa recherche.

Disons que nous avons cet arbre:

Un arbre binaire

Et nous y insérons un «8». Maintenant, nous avons:

Un arbre binaire déséquilibré

Et ce n'est pas équilibré. Donc, nous allons faire la magie de l'équilibrer via une implémentation ...

arbre équilibré

Et vous avez à nouveau un arbre équilibré. Mais c'était beaucoup de magie, j'ai agité ma main.

Prenons une liste à sauter.

liste de saut idéale

Celui-ci se trouve être idéalisé. Peu le sont, mais cela montre la nature équilibrée des arbres binaires que l'idéal skiplist se rapproche.

Maintenant, nous voulons insérer un 6 là-dedans. Cela l'insère un peu comme une liste chaînée. Cependant, nous commençons par le haut et descendons. Les premiers points à 5. Est-ce que 6> 5? Oui. D'accord, le sommet pointe à la fin maintenant, alors nous descendons la pile (nous sommes sur le 5). Le suivant est 7. Is 6> 7? Nan. On descend donc d'un niveau et on est au niveau de base donc on insère 6 à droite du 5.

Nous lançons une pièce - des têtes que nous construisons, des queues que nous restons. Tails. Il n'y a plus rien à faire.

sauter la liste après une insertion

Permet d'insérer ce 8 maintenant. 8> 5? oui. 8> 7? Oui. Et maintenant, nous sommes à nouveau au niveau inférieur après avoir suivi les flèches et la pile autour et nous testons 8> 11? Nan. Nous insérons donc le 8 à droite du 7.

Nous lançons une pièce - des têtes que nous construisons, des queues que nous restons. Tails. Il n'y a plus rien à faire.

sauter la liste après une autre insertion

Dans l'arbre équilibré, nous aurions tous travaillé sur le fait que l'arbre ne soit pas équilibré maintenant. Mais ce n'est pas un arbre - c'est une liste à sauter. Nous approchons un arbre équilibré.

Insérons maintenant un 10. J'éviterai toutes les comparaisons.

Nous lançons une pièce - des têtes que nous construisons, des queues que nous restons. Têtes! Et retournez-le à nouveau, têtes à nouveau! Retournez-le à nouveau, ok, il y a une queue. Deux niveaux au-dessus de la liste chaînée de base.

sauter la liste après un nouvel encart

L'avantage ici est que maintenant, si nous allons insérer un 12, nous pouvons passer de 5 à 10 sans faire toutes ces autres comparaisons. Nous pouvons les ignorer avec la liste de sauts. Et nous n'avons pas à nous soucier de l'arbre équilibré - la nature probabiliste de l'empilement le fait pour nous.

Pourquoi est-ce si utile? Parce que lors de l'insertion du 10, je peux le faire en verrouillant l'écriture sur les pointeurs 5 et 7 et 8 plutôt que sur la structure entière. Et pendant que je fais cela, les lecteurs peuvent toujours parcourir la liste de sauts sans avoir un état incohérent. Pour une utilisation simultanée, il est plus rapide de ne pas avoir à verrouiller. Pour itérer sur la couche inférieure, c'est plus rapide qu'un arbre (les joies des algorithmes BFS et DFS pour la navigation dans les arbres - vous n'avez pas à vous en soucier).

Le rencontrerez-vous? Vous le verrez probablement utilisé par endroits. Et vous saurez alors pourquoi l'auteur a choisi cette implémentation plutôt que a TreeMapou HashMappour la structure.

Une grande partie de cela a été empruntée à mon article de blog: La liste à sauter


la source
Je vous remercie. Ce n'est même pas l'implémentation générale que je ne comprends pas; J'obtiens leur ressemblance avec les BST. J'ai essayé de réfléchir à la façon de l'implémenter, et l'idée de gérer tous les pointeurs / références m'a constamment dérouté. Je me suis peut-être trop frustré. Merci. Je vais essayer de le récupérer demain en utilisant votre réponse comme point de départ.
Carcigenicate
2
@Carcigenicate, vous pouvez également trouver l'article original qui les présente utiles - Skip Lists: A Probabilistic Alternative to Balanced Trees . C'est un article assez compréhensible par rapport à la plupart des articles académiques qui peuvent aller bien au-delà de la tête des gens. Le tableau 2 explique pourquoi vous les verrez en cours d'utilisation. Ce facteur de temps pour l'insertion ou la suppression est une complexité supplémentaire des autres solutions.
2
Une liste chaînée n'est "qu'un arbre dégénéré très déséquilibré". Une liste de sauts est en quelque sorte l'ajout partiel d'une sorte de structure arborescente en haut d'une liste. Personnellement, je suis un grand fan des structures de données persistantes, et les arbres semblent être plus faciles à raisonner dans ce contexte particulier. Je ne pense pas que ce soit une coïncidence si Clojure, Scala et al. semblent converger vers une sorte d'essais de hachage de style Bagwell comme structure de données de base. (Phil Bagwell a même été impliqué dans la refonte du cadre des collections de Scala pour Scala 2.8.) Les listes à sauter sont quand même bien.
Jörg W Mittag
C'est la meilleure explication du fonctionnement d'une liste de sauts que j'ai jamais lue.
génial