Existe-t-il une structure de données de file d'attente prioritaire qui prend en charge les opérations suivantes?
- Insérer (x, p) : ajouter un nouvel enregistrement x avec la priorité p
- StableExtractMin () : Renvoie et supprime l'enregistrement avec une priorité minimale, rompant les liens par ordre d'insertion .
Ainsi, après Insert (a, 1), Insert (b, 2), Insert (c, 1), Insert (d, 2), une séquence de StableExtractMin retournerait a, puis c, puis b, puis d.
Évidemment, on pourrait utiliser n'importe quelle structure de données de file d'attente prioritaire en stockant la paire comme priorité réelle, mais je suis intéressé par les structures de données qui ne stockent pas explicitement les temps d'insertion (ou l'ordre d'insertion), par analogie avec un tri stable .
De manière équivalente (?): Existe-t-il une version stable de heapsort qui ne nécessite pas d' espace supplémentaire ?
ds.data-structures
Jeffε
la source
la source
Réponses:
La méthode Bently-Saxe donne une file d'attente prioritaire stable assez naturelle.
Stockez vos données dans une séquence de tableaux triés . a une taille . Chaque tableau maintient également un compteur . Les entrées de tableau contiennent des données.A i 2 i c i A i [ c i ] , … , A i [ 2 i - 1 ]UNE0, … , Ak UNEje 2je cje UNEje[ cje] , … , Aje[ 2je- 1 ]
Pour chaque , tous les éléments de ont été ajoutés plus récemment que ceux de et au sein de chaque éléments sont classés par valeur, les liens étant rompus en plaçant les éléments plus anciens devant les éléments plus récents. Notez que cela signifie que nous pouvons fusionner et et conserver cet ordre. (En cas d'égalité lors de la fusion, prenez l'élément de .)A i A i + 1 A i A i A i + 1 A i + 1je UNEje UNEi + 1 UNEje UNEje UNEi + 1 UNEi + 1
Pour insérer une valeur , recherchez le plus petit tel que contienne 0 élément, fusionnez et , stockez-le dans et définissez manière appropriée.i A i A 0 , … , A i - 1 x A i c 0 , … , c iX je UNEje UNE0, … , Ai - 1 X UNEje c0, … , Cje
Pour extraire le min, trouver le plus grand indice tel que le premier élément dans soit minimum sur tout et incrémenter .A i [ c i ] i c ije UNEje[ cje] je cje
Par l'argument standard, cela donne temps amorti par opération et est stable en raison de l'ordre décrit ci-dessus.O ( logn )
Pour une séquence de insertions et extractions, cela utilise n entrées de tableau (ne conservez pas de tableaux vides) plus O ( log n ) mots de données de comptabilité. Cela ne répond pas à la version de Mihai de la question, mais cela montre que la contrainte stable ne nécessite pas beaucoup d'espace au-dessus. En particulier, cela montre qu'il n'y a pas de borne inférieure Ω ( n ) sur l'espace supplémentaire nécessaire.n n O ( logn ) Ω ( n )
Mise à jour: Rolf Fagerberg souligne que si nous pouvons stocker des valeurs nulles (non-données), alors toute cette structure de données peut être compressée dans un tableau de taille , où n est le nombre d'insertions jusqu'à présent.n n
Tout d'abord, notez que nous pouvons regrouper les dans un tableau dans cet ordre (avec A k en premier, suivi de A k - 1 s'il n'est pas vide, etc.). La structure de ceci est complètement codée par la représentation binaire de n , le nombre d'éléments insérés jusqu'à présent. Si la représentation binaire de n a un 1 à la position i , alors A i occupera 2 i emplacement de tableau, sinon il n'occupera aucun emplacement de tableau.Ak,…,A0 Ak Ak−1 n n i Ai 2i
Lors de l'insertion, et la longueur de notre tableau, augmentez de 1 et nous pouvons fusionner A 0 , … , A i plus le nouvel élément en utilisant des algorithmes de fusion stables en place existants.n A0,…,Ai
Maintenant, où nous utilisons des valeurs nulles, c'est pour se débarrasser des compteurs . Dans A i , nous stockons la première valeur, suivie de c i valeurs nulles, suivie des 2 i - c i - 1 valeurs restantes . Lors d'une extraction-min, on peut toujours trouver la valeur à extraire en temps O ( log n ) en examinant A 0 [ 0 ] , … , A k [ 0 ] . Lorsque nous trouvons cette valeur dans A i [ 0ci Ai ci 2i−ci−1 O(logn) A0[0],…,Ak[0] nous définissons A i [ 0 ] sur null puis effectuons une recherche binaire sur A i pour trouver la première valeur non nulle A i [ c i ] et permutons A i [ 0 ] et A i [ c i ] .Ai[0] Ai[0] Ai Ai[ci] Ai[0] Ai[ci]
Le résultat final: la structure entière peut être implémentée avec un tableau dont la longueur est incrémentée à chaque insertion et un compteur, , qui compte le nombre d'insertions.n
la source
Je ne sais pas quelles sont vos contraintes; les éléments suivants sont-ils admissibles? Stockez les données dans un tableau, que nous interprétons comme un arbre binaire implicite (comme un tas binaire), mais avec les éléments de données au niveau inférieur de l'arbre plutôt qu'à ses nœuds internes. Chaque nœud interne de l'arbre stocke la plus petite des valeurs copiées de ses deux enfants; en cas d'égalité, copiez l'enfant de gauche.
Pour trouver le minimum, regardez la racine de l'arbre.
Pour supprimer un élément, marquez-le comme supprimé (suppression paresseuse) et propagez l'arborescence (chaque nœud sur le chemin d'accès à la racine qui contenait une copie de l'élément supprimé doit être remplacé par une copie de son autre enfant). Conservez un décompte des éléments supprimés et si jamais il devient trop grand une fraction de tous les éléments, puis reconstruisez la structure en préservant l'ordre des éléments au niveau inférieur - la reconstruction prend du temps linéaire, donc cette partie n'ajoute qu'un temps amorti constant à la complexité de l'opération.
Pour insérer un élément, ajoutez-le à la position libre suivante sur la ligne inférieure de l'arborescence et mettez à jour le chemin d'accès à la racine. Ou, si la ligne du bas devient pleine, doublez la taille de l'arborescence (à nouveau avec un argument d'amortissement; notez que cette partie n'est pas différente de la nécessité de reconstruire lorsqu'un tas binaire standard dépasse son tableau).
Ce n'est pas une réponse à la version plus stricte de la question de Mihai, car elle utilise deux fois plus de mémoire qu'une véritable structure de données implicite, même si nous ignorons le coût d'espace de gestion des suppressions paresseusement.
la source
Est-ce une interprétation valide de votre problème:
Vous devez stocker N clés dans un tableau de A [1..N] sans informations auxiliaires telles que vous pouvez prendre en charge: * insérer la clé * supprimer min, qui sélectionne l'élément inséré le plus tôt s'il existe plusieurs minima
Cela semble assez difficile, étant donné que la plupart des structures de données implicites jouent le rôle de codage des bits dans l'ordre local de certains éléments. Ici, si plusieurs gars sont égaux, leur ordre doit être préservé, donc de telles astuces ne sont pas possibles.
Intéressant.
la source
Réponse courte: vous ne pouvez pas.
Réponse légèrement plus longue:
Réponse très longue avec des pseudo-mathématiques floues inexactes:
Remarque: la toute fin de la deuxième partie est sommaire, comme mentionné. Si un mathématicien pouvait fournir une meilleure version, je lui en serais reconnaissant.
Maintenant, combien de bits d'informations chaque «cellule» de mémoire nous fournit-elle?
Ainsi, pour stocker toutes nos informations, nous avons deux possibilités:
Évidemment, pour éviter le gaspillage, nous utiliserons la première solution.
Maintenant pour les opérations. Je suppose que vous souhaitez avoir:
L'algorithme vraiment vraiment général se présente comme suit:
L'algorithme d'insertion a généralement juste besoin de mettre à jour une partie de ces informations, je ne pense pas que cela coûtera plus cher (en termes de mémoire) de le faire fonctionner rapidement.
la source
Si vous implémentez votre file d'attente prioritaire en tant qu'arbre binaire équilibré (un choix populaire), il vous suffit de vous assurer que lorsque vous ajoutez un élément à l'arborescence, il est inséré à gauche de tous les éléments de priorité égale.
De cette façon, l'ordre d'insertion est codé dans la structure de l'arbre lui-même.
la source
Je ne pense pas que ce soit possible
cas concret:
tas minimum avec tous les x> 1
heapifying donnera finalement quelque chose comme un choix
maintenant lequel 1 se propager à root?
la source