Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentes Révision précédente Prochaine révision | Révision précédente | ||
dichotomie [2009/04/20 07:25] tyrtamos |
dichotomie [2009/04/20 09:06] tyrtamos |
||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
====== Recherche rapide par dichotomie dans une liste triée ====== | ====== Recherche rapide par dichotomie dans une liste triée ====== | ||
+ | |||
+ | Dernière modification le 20/4/2009 | ||
===== Principe ===== | ===== Principe ===== | ||
Ligne 245: | Ligne 247: | ||
<code python> | <code python> | ||
import random | import random | ||
+ | import time | ||
- | def creafic(fichier, | + | def creafic(fichier, |
# fabrication de la liste à enregistrer | # fabrication de la liste à enregistrer | ||
- | L = [random.randint(i1, i2) for i in xrange(0, | + | L = [random.randint(I1, I2) for i in xrange(0, |
# tri de la liste | # tri de la liste | ||
Ligne 261: | Ligne 264: | ||
f.write(v + esp[: | f.write(v + esp[: | ||
f.close() | f.close() | ||
+ | |||
+ | fichier = " | ||
+ | lg = 1000000 | ||
+ | lge = 5 | ||
+ | I1 = 1000 | ||
+ | I2 = 9999 | ||
+ | |||
+ | t = time.clock() | ||
+ | creafic(fichier, | ||
+ | t = time.clock()-t | ||
+ | print u" | ||
</ | </ | ||
- | Par exemple, avec creafic(" | + | Par exemple, avec creafic(" |
- | On va maintenant créer une fonction de lecture d'un enregistrement connaissant son indice, ainsi qu'une liste des indices croissants: | + | On va maintenant créer une fonction de lecture d'un enregistrement connaissant son indice, ainsi qu'une liste des indices croissants |
<code python> | <code python> | ||
Ligne 276: | Ligne 290: | ||
</ | </ | ||
- | On a toujours | + | Vous pouvez vérifier |
+ | |||
+ | <code python> | ||
+ | # verification | ||
+ | f = open(fichier, ' | ||
+ | for i in I: | ||
+ | print litdata(i) | ||
+ | |||
+ | f.close() | ||
+ | </ | ||
+ | |||
+ | On va utiliser maintenant les fonctions de recherche précédentes: dichot() pour la recherche dichotomique et seq() pour les recherches séquentielles. | ||
Et voilà le code d' | Et voilà le code d' | ||
<code python> | <code python> | ||
+ | f = open(fichier, | ||
+ | t1 = 0 | ||
+ | t2 = 0 | ||
+ | c = 0 | ||
+ | while True: | ||
+ | try: | ||
+ | c += 1 | ||
+ | x = random.randint(I1-1, | ||
+ | |||
+ | t = time.clock() | ||
+ | r1,i1 = dichot(x, I, key=litdata) | ||
+ | t1 += time.clock()-t | ||
+ | |||
+ | t = time.clock() | ||
+ | r2,i2 = seq(x, I, key=litdata) | ||
+ | t2 += time.clock()-t | ||
+ | |||
+ | print x, [r1, i1], [r2, i2], litdata(i1), | ||
+ | except: | ||
+ | break | ||
+ | f.close() | ||
+ | </ | ||
+ | |||
+ | Ce qui affiche, par exemple: | ||
+ | |||
+ | < | ||
+ | 9097 [0, 900121] [0, 900121] 9097 9097 17305.7813651 0.000167109172573 | ||
+ | 4026 [0, 337762] [0, 337762] 4026 4026 17271.2771325 0.000167086643643 | ||
+ | 5159 [0, 463844] [0, 463844] 5159 5159 17267.2479243 0.000167060928584 | ||
+ | 8676 [0, 853399] [0, 853399] 8676 8676 17356.9558071 0.000167023901043 | ||
+ | </ | ||
+ | |||
+ | Le résultat est époustouflant: | ||
+ | |||
+ | Ça vous suffit comme performance? | ||
+ | |||
+ | NB: je ne connais pas l' | ||
+ | |||
+ | ===== Recherche indexée dans un fichier sur disque ===== | ||
+ | |||
+ | On se propose ici de rechercher des valeurs par dichotomie avec un fichier disque **non trié**, et sans charger ce fichier en mémoire. On va donc créer un fichier d' | ||
+ | |||
+ | On va d' | ||
+ | |||
+ | <code python> | ||
+ | import random | ||
import time | import time | ||
+ | |||
+ | def creafic(fichier, | ||
+ | # fabrication de la liste à enregistrer | ||
+ | L = [random.randint(i1, | ||
+ | |||
+ | # creation du fichier sur disque | ||
+ | f = open(fichier, | ||
+ | esp = ' '*lge | ||
+ | for i in range(0, len(L)): | ||
+ | f.seek(i*lge) | ||
+ | v = " | ||
+ | f.write(v + esp[: | ||
+ | f.close() | ||
fichier = " | fichier = " | ||
lg = 1000000 | lg = 1000000 | ||
lge = 5 | lge = 5 | ||
- | i1 = int(' | + | I1 = 1000 |
- | i2 = int(' | + | I2 = 9999 |
- | print u" | + | |
+ | t = time.clock() | ||
+ | creafic(fichier, lg, lge, I1, I2) | ||
+ | t = time.clock()-t | ||
+ | print u" | ||
+ | </ | ||
+ | |||
+ | La création de ce fichier d'1 million d' | ||
+ | |||
+ | Maintenant, on va créer un fichier d' | ||
+ | |||
+ | <code python> | ||
+ | def litdata(i): | ||
+ | global f, lge | ||
+ | f.seek(i*lge) | ||
+ | return int(f.read(lge).strip()) | ||
- | creafic(fichier, | ||
I = [i for i in xrange(0, | I = [i for i in xrange(0, | ||
- | print u" | + | f = open(fichier, |
+ | t = time.clock() | ||
+ | I.sort(key=litdata) | ||
+ | t = time.clock()-t | ||
+ | f.close() | ||
+ | print u" | ||
+ | </ | ||
+ | La création de ce fichier d' | ||
+ | |||
+ | Si vous voulez le vérifier, vous pouvez afficher les données du disque dans cet ordre comme suit. Mais ne le faites pas pour le fichier de 1000000 de valeurs: cela demandera trop de temps pour l' | ||
+ | |||
+ | <code python> | ||
+ | f = open(fichier, | ||
+ | for i in I: | ||
+ | print litdata(i) | ||
+ | |||
+ | f.close() | ||
+ | </ | ||
+ | |||
+ | On va utiliser maintenant les fonctions de recherche précédentes: | ||
+ | |||
+ | <code python> | ||
f = open(fichier, | f = open(fichier, | ||
t1 = 0 | t1 = 0 | ||
Ligne 301: | Ligne 420: | ||
try: | try: | ||
c += 1 | c += 1 | ||
- | x = random.randint(i1-1, i2+1) | + | x = random.randint(I1-1, I2+1) |
t = time.clock() | t = time.clock() | ||
- | | + | |
t1 += time.clock()-t | t1 += time.clock()-t | ||
t = time.clock() | t = time.clock() | ||
- | | + | |
t2 += time.clock()-t | t2 += time.clock()-t | ||
- | print [r, i], litdata(i), t2/t1, t1/c | + | print x, [r1, i1], [r2, i2], litdata(I[i1]), litdata(I[i2]), t2/t1, t1/c |
except: | except: | ||
break | break | ||
Ligne 317: | Ligne 436: | ||
</ | </ | ||
- | Le résultat est époustouflant: | + | Le code ci-dessus (qu'on arrête avec Ctrl-C) affiche les résultats comme suit: |
- | * On trouve une valeur au hasard parmi un million de valeurs sur disque en 1.7/10000 secondes, et c'est 17000 fois plus rapidement qu' | + | < |
- | + | 8317 [0, 813361] [0, 813361] 8317 8317 17537.9140573 0.000173003674181 | |
- | Ça vous suffit comme performance? | + | 8476 [0, 830810] [0, 830810] 8476 8476 17587.4199338 0.000173009098294 |
- | + | 4398 [0, 377556] [0, 377556] 4398 4398 17571.9584712 0.000172991006654 | |
- | NB1: je ne connais pas l' | + | 5537 [0, 504304] [0, 504304] 5537 5537 17575.2446774 0.000172973807046 |
+ | </ | ||
- | NB2: j'ai pris ici un fichier | + | Ce qui montre une performance quasi identique au test précédent: le passage par une liste d'index n'a donc pas ralenti sensiblement le temps de recherche: la recherche dichotomique sur disque, |
\\ | \\ |