Une solution est possible seulement en raison de la différence entre 1 mo et 1 million d'octets. Il y a environ 2 à la puissance 8093729.5 différentes façons de choisir 1 millions de 8 chiffres, avec des doublons autorisés et de l'ordre sans importance, donc une machine avec seulement 1 million d'octets de RAM n'a pas assez de membres pour représenter toutes les possibilités. Mais 1M (moins de 2k pour le protocole TCP/IP) est 1022*1024*8 = 8372224 bits, une solution est possible.
La partie 1, la solution initiale
Cette approche a besoin d'un peu plus de 1M, je vais l'améliorer pour s'adapter à 1M plus tard.
Je vais ranger un compact liste ordonnée de nombres dans l'intervalle de 0 à 99999999 comme une séquence de sous-listes de 7 bits. La première sous-liste détient des chiffres de 0 à 127, le deuxième sous-liste détient les numéros de 128 à 255, etc. 100000000/128 est exactement 781250, donc 781250 ces sous-listes seront nécessaires.
Chaque sous-liste se compose de 2 bits de sous-en-tête suivi par un sous-corps. Le sous-corps prend 7 bits par sous-liste d'entrée. Les sous-listes sont tous concaténées ensemble, et le format permet de dire d'où une sous-liste se termine et commence la suivante. Le total de l'espace de stockage requis pour une liste est entièrement rempli 2*781250 + 7*1000000 = 8562500 bits, ce qui est sur 1.021 M-octets.
Les 4 sous-liste valeurs d'en-tête sont:
00 Vide sous-liste, rien ne suit.
01 Singleton, il n'y a qu'une seule entrée dans la sous-liste et et 7 bits de la retenir.
10 La sous-liste détient au moins 2 numéros distincts. Les entrées sont stockés dans l'ordre décroissant, sauf que la dernière entrée est inférieure ou égale à la première. Cela permet à la fin de la sous-liste à être identifiés. Par exemple, les numéros de 2,4,6 est stockée en tant que (4,6,2). Les numéros de 2,2,3,4,4 est stockée en tant que (2,3,4,4,2).
11 La sous-liste de 2 ou plus de répétitions d'un seul numéro. Les 7 bits de donner le nombre. Puis viennent zéro ou plus de 7 bits entrées dont la valeur est 1, suivi par un 7-bit avec la valeur 0. La longueur de la sous-corps détermine le nombre de répétitions. Par exemple, les numéros de 12,12 est stockée en tant que (12,0), les numéros de 12,12,12 est stockée en tant que (12,1,0), 12,12,12,12 serait (12,1,1,0) et ainsi de suite.
J'ai commencer avec une liste vide, lire un tas de chiffres et de les stocker sous forme de 32 bits par exemple, trier les nouveaux numéros en place (à l'aide de heapsort, sans doute), puis de les fusionner en un nouveau compact liste triée. Répéter jusqu'à ce qu'il n'y a pas plus de nombres à lire, puis à pied le compact liste une fois de plus pour générer la sortie.
La ligne ci-dessous représente la mémoire, juste avant le début de la liste de l'opération de fusion. Les "O"sont la région qui détiennent le tri nombres entiers de 32 bits. Le "X"de la région qui détiennent le vieux compact liste. Le "=" signes sont l'extension de la salle pour le compact liste, 7 bits pour chaque entier dans les "O". Le "Z"sont d'autres aléatoire frais généraux.
ZZZOOOOOOOOOOOOOOOOOOOOOOOOOO==========XXXXXXXXXXXXXXXXXXXXXXXXXX
La fusion de la routine commence à lire à l'extrême gauche "O" et à l'extrême gauche "X", et commence à écrire à l'extrême gauche "=". L'écriture pointeur ne pas attraper le compact liste de pointeur de lecture jusqu'à ce que tous les nouveaux entiers sont fusionnées, parce que les deux pointeurs d'avance 2 bits pour chaque sous-liste et 7 bits pour chaque entrée dans la vieille compact liste, et il y a suffisamment d'espace supplémentaire pour les 7 bits les inscriptions pour les nouveaux numéros.
Partie 2, s'entasser dans 1M
Pour Serrer la solution ci-dessus dans 1M, j'ai besoin de faire la compacte la forme d'une liste un peu plus compact. Je vais me débarrasser de l'un des sous-types, de sorte qu'il n'y aura que 3 différents types de sous-liste valeurs d'en-tête. Alors je peux utiliser "00", "01" et "1" comme le sous-en-tête de valeurs et d'enregistrer quelques morceaux. Les sous-types sont:
Un Vide sous-liste, rien ne suit.
B Singleton, il n'y a qu'une seule entrée dans la sous-liste et et 7 bits de la retenir.
C La sous-liste détient au moins 2 numéros distincts. Les entrées sont stockés dans l'ordre décroissant, sauf que la dernière entrée est inférieure ou égale à la première. Cela permet à la fin de la sous-liste à être identifiés. Par exemple, les numéros de 2,4,6 est stockée en tant que (4,6,2). Les numéros de 2,2,3,4,4 est stockée en tant que (2,3,4,4,2).
D La sous-liste se compose de 2 ou plus de répétitions d'un seul numéro.
Mes 3 sous-en-tête de valeurs de "A", "B" et "C", j'ai donc besoin d'un moyen de représenter la D-type des sous-listes.
Supposons que j'ai la C-type de sous-en-tête suivi par 3 entrées, telles que "C[17][101][58]". Cela ne peut pas être de la partie valide de type C sous-liste, comme décrit ci-dessus, depuis la troisième entrée est inférieure à la seconde, mais plus que le premier. Je peux utiliser ce type de construction pour représenter un type D sous-liste. En peu de termes, n'importe où j'ai "C{00?????}{1??????}{01?????}" est impossible de type C sous-liste. Je vais l'utiliser pour représenter une sous-liste composée de 3 ou plus de répétitions d'un seul numéro. Les deux premiers 7 bits des mots de coder le nombre (le "N" bits ci-dessous) et sont suivis par zéro ou plus {0100001} mots suivis d'un {0100000} mot.
For example, 3 repetitions: "C{00NNNNN}{1NN0000}{0100000}", 4 repetitions: "C{00NNNNN}{1NN0000}{0100001}{0100000}", and so on.
Cela ne laisse listes tenir exactement 2 répétitions d'un seul numéro. Je vais représenter ceux avec un autre impossible C-type de sous-motif: "C{0??????}{11?????}{10?????}". Il y a beaucoup de place pour les 7 bits du nombre dans les 2 premiers mots, mais ce modèle est plus longue que la sous-liste qu'il représente, et qui rend les choses un peu plus complexes. Les cinq points d'interrogation à la fin peut être considéré comme ne faisant pas partie du modèle, j'ai donc: "C{0NNNNNN}{11N????}10" comme mon patron, avec le nombre d'être répété stockées dans le "N". C'est 2 bits trop longtemps.
Je vais devoir emprunter 2 bits et les payer de retour à partir de la 4 les bits non utilisés dans ce modèle. Lors de la lecture, sur rencontrer "C{0NNNNNN}{11N00AB}10", sortie 2 instances du nombre dans le "N"s, de remplacer le "10" à la fin avec les bits A et B, et de rembobiner le pointeur de lecture par 2 bits. Destructeur de lectures sont ok pour cet algorithme, puisque chaque compact liste se passe qu'une fois.
Lors de l'écriture d'une sous-liste de 2 répétitions d'un seul numéro, écrire "C{0NNNNNN}11N00" et emprunté bits compteur à 2. À chaque écriture où le capital emprunté bits compteur est non-nul, il est décrémenté pour chaque bit écrite et "10" est écrit lorsque le compteur atteint zéro. Donc, la prochaine 2 bits écrits vont dans les fentes A et B, puis le "10" laché sur la fin.
Avec 3 sous-en-tête de valeurs représentées par "00", "01" et "1", je peux assigner "1" pour les plus populaires de sous-type. J'aurai besoin d'une petite table pour les sous-liste valeurs d'en-tête de sous-types, et j'aurai besoin d'un événement de compteur pour chaque sous-type, de sorte que je sais quel est le meilleur sous-en-tête de la cartographie.
Le pire des cas d'une représentation minimale d'un entièrement rempli compact liste se produit lorsque tous les sous-types sont également populaires. Dans ce cas, je vous enregistrer 1 bit pour tous les 3 sous-en-têtes, de sorte que la taille de la liste est 2*781250 + 7*1000000 - 781250/3 = 8302083.3 bits. L'arrondi d'un maximum de 32 bits limite de mot, c'est 8302112 bits, ou 1037764 octets.
1M moins le 2k pour le protocole TCP/IP de l'état et des tampons est 1022*1024 = 1046528 octets, me laissant 8764 octets pour jouer avec.
Mais quel est le processus de modification de la sous-liste de l'en-tête de la cartographie ? Dans la mémoire de la carte ci-dessous, "Z" est aléatoire, les frais généraux, les "=" est l'espace libre, "X" est la compacte de la liste.
ZZZ=====XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Démarrer la lecture à l'extrême gauche "X" et de commencer à écrire à le plus à gauche "=" et le travail à droite. Quand c'est fait, le compact liste sera un peu plus courte et il sera au mauvais bout de la mémoire:
ZZZXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX=======
Alors je vais avoir besoin d'un shunt vers la droite:
ZZZ=======XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Dans la tête de la cartographie des processus de changement, jusqu'à 1/3 de la sous-liste des en-têtes passera de 1 bit 2 bits. Dans le pire des cas, ils seront tous à la tête de la liste, donc je vais avoir besoin d'au moins 781250/3 bits de stockage gratuit avant de commencer, ce qui me ramène à la mémoire des exigences de la précédente version de la compacte de la liste :(
Pour contourner cela, je vais partager le 781250 des sous-listes en 10 sous-groupes de 78125 chacune des sous-listes. Chaque groupe dispose de son propre sous-en-tête de la cartographie. En utilisant les lettres A à J pour les groupes:
ZZZ=====AAAAAABBCCCCDDDDDEEEFFFGGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ
Chaque sous-groupe se rétrécit ou reste la même au cours d'une sous-liste d'en-tête de la cartographie du changement:
ZZZ=====AAAAAABBCCCCDDDDDEEEFFFGGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAA=====BBCCCCDDDDDEEEFFFGGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABB=====CCCCDDDDDEEEFFFGGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABBCCC======DDDDDEEEFFFGGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABBCCCDDDDD======EEEFFFGGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABBCCCDDDDDEEE======FFFGGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABBCCCDDDDDEEEFFF======GGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABBCCCDDDDDEEEFFFGGGGGGGGGG=======HHIJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABBCCCDDDDDEEEFFFGGGGGGGGGGHH=======IJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABBCCCDDDDDEEEFFFGGGGGGGGGGHHI=======JJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABBCCCDDDDDEEEFFFGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ=======
ZZZ=======AAAAAABBCCCDDDDDEEEFFFGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ
Le pire des cas élargissement temporaire d'un sous-groupe lors d'une cartographie de modification est 78125/3 = 26042 bits, en vertu de la 4k. Si je puis me permettre 4k en plus de la 1037764 octets pour un entièrement rempli compact liste, qui me laisse 8764 - 4096 = 4668 octets pour le "Z"dans la carte mémoire.
Qui devrait être beaucoup pour les 10 sous-en-tête de tables de correspondance, 30 sous-en-tête de l'apparition des comtes et de l'autre quelques compteurs, des pointeurs et des petits tampons je vais avoir besoin, et l'espace que j'ai utilisé sans s'en apercevoir, comme espace de pile pour l'appel de fonction de l'adresse de retour et des variables locales.
La partie 3, combien de temps cela prendrait-il à courir ?
Avec un vide compact liste 1-liste des bits d'en-tête sera utilisé pour un vide sous-liste, et la taille de départ de la liste sera 781250 bits. Dans le pire des cas, la liste s'accroît de 8 bits pour chaque numéro est ajouté, donc 32 + 8 = 40 bits d'espace libre sont nécessaires pour chacun des nombres de 32 bits pour être placé au sommet de la liste de la mémoire tampon, puis triées et regroupées. Dans le pire des cas, la modification de la sous-liste d'en-tête les résultats de la cartographie dans l'utilisation de l'espace 2*781250 + 7*entrées - 781250/3 bits.
Avec une politique de changer les sous-en-tête de la cartographie après chaque cinquième de fusion une fois il y a au moins 800000 numéros dans la liste, un pire cas d'exécution impliquerait un total d'environ 30M de compact liste de lecture et d'écriture de l'activité.
Source:
http://nick.cleaton.net/ramsortsol.html