Le problème de recherche Entrée: n clefs distinctes k 1, k 2, …, k n et un ensemble T de n...

Post on 04-Apr-2015

105 views 3 download

Transcript of Le problème de recherche Entrée: n clefs distinctes k 1, k 2, …, k n et un ensemble T de n...

Le problème de rechercheEntrée: n clefs distinctes k1, k2, …, kn et un

ensemble T de n enregistrements de la forme (k1, I1), (k2, I2), …, (kn, In)

où Ij est l’information associée à la clef kj pour 1 <= j <= n.

Problème: Pour une clef K, trouver l’enregistrement (kj, Ij) dans T tel que

kj = K.

Recherche: algorithme pour trouver un enregistrement à partir d’une clef kj = K.

Succès vs. Échec

Succès: Un enregistrement avec clef kj = K est trouvé.

Échec: Aucun enregistrement avec clef

kj = K n’est trouvé (sans doute qu’un tel enregistrement n’existe pas).

Les différentes approches

1. Méthodes séquentielle (listes, tableaux).

2. Adressage dispersé (hashing)

3. Méthodes d’indexation par arbres.

Recherche dans un tableau ordonné

Recherche séquentielle

Recherche dychotomique

Méthode du dictionnaire

Listes ordonnées par fréquence d’accès

Listes ordonnées par la fréquence (espérée) d’accès.

Exécuter une recherche séquentielle

Coût d’accès à l’enregistrement 1: 1Coût d’accès à l’enregistrement 2: 2

Coût d’accès moyen:

....21 21 nn npppC

Exemple(1)

(1) Tous les enregistrements ont la même fréquence d’accès.

2/)1(/1

nniCn

i

n

Exemple(2)

(2) Fréquence exponentielle

ni

nip

n

i

i

if2/1

11if2/11

{

n

i

in iC

1

.2)2/(

Distribution de Zipf

Applications:– Utilisation des mots dans les langues

naturelles.– Taille des populations des villes.

n

ienin nnnipC

1

log//H

n

in iH

1

/1

nHn ene log1log

ni iHp

1

Règle 80/20

Phénomène courant dans des applications cormerciales:

– 80% des accès vont à 20% des enregistrements.

– La même règle s’applique aux 20% des enregistrements les plus fréquents.

– Etc.

Listes auto-organisées

Listes auto-organisées: La position d’un enregistrement dans la liste peut être modifiée après un accès.

Une heuristique est utilisé pour déterminer comment réordonner la liste.

Heuristique

Ordonner par la fréquence d’accès observée.

1. Lorsqu’un enregistrement est trouvé, le déplacer au début de la liste.

2. Lorsqu’un enregistrement est trouvé, l’échanger avec l’enregistrement précédent.

Exemple: compression de texte

Compression d’un message à transmettre:

Conserver une liste des mots rencontrés (heuristique: déplacer au début).

• Envoyer directement les mots nouveaux.• Envoyer la position dans la liste des mots

déjà rencontrés.

The car on the left hit the car I left.The car on 3 left hit 3 5 I 5.

Recherche dans un ensemble

Lorsque le domaine n’est pas trop grand:

On peut utiliser les opérateurs de bits.

Exemple: Pour trouver les nombre premiers impairs:

0011010100010100 & 0101010101010101

Adressage dispersé (1)Adressage dispersé (hashing): On associe

chaque clef à une position dans une table.

Une fonction de hachage transforme la valeur d’une clef en une position. Nous la dénoterons h.

Une table de hachage est un tableau contenant les enregistrements. Nous la dénoterons par HT.

HT possède M cases indexées de 0 à M-1.

Adressage dispersé (2)

Pour toute valeur de clef K, h(K) = i, 0 <= i < M, tel que HT[i].clef = K.

Répond à la question: “Quel enregistrement, s’il existe, possède la valeur de clef K?”

Bon pour mémoire et disque.

Exemples simples

(1) Stocker n enregistrements (clefs entre 0 et n-1)– Mettre l’enregistrement avec clef i dans la case i.– Fonction de hachage h(K) = K.

(2) Autre exemple:– Stocker 1000 enregistrements (clefs entre 0 et 16383).– On ne peut conserver en mémoire une table de 16384

cases.– On doit trouver une fonction de hachage nous

permettant d’utiliser une plus petite table.

Collisions (1)

Entrée: fonction de hachage h et clefs k1 et k2. est l’indice d’une case dans la table de hachage.

Si h(k1) = = h(k2), alors on dit qu’il y a collision.

Recherche de l’enregistrement avec clef K:1. Calculer l’indice de la table h(K).2. Partant de h(K), trouver l’enregistrement

contenant la clef K en utilisant (si nécessaire) une politique de résolution des collisions.

Collisions (2)

Dans la plupart des applications, les collisions sont inévitables.

– Exemple: Il y a plus de 56% de probabilité qu’au moins deux personnes parmi un groupe de 25 aient la même date d’anniversaire..

Fonctions de hachage (1)

Une fonction de hachage doit retourner une valeur entre 0 et M-1, où M est la taille de la table de hachage.

Une fonction de hachage doit idéalement distribuer les enregistrements uniformément dans la table.

En pratique, l’efficacité dépend de la distribution des enregistrements..

Exemples (1)

int h(int x) { return(x % 16);}

Cette fonction dépend entièrement des derniers 4 bits de la clef.

Méthode des carrés moyens: Mettre la clef au carré et prendre les r bits du millieu. Pour une table de hachage de 2r cases.

Exemples (2)

Pour les mots: Additionner (modulo M) la valeur ASCII des lettres.

int h(char* x) { int i, sum; for (sum=0, i=0; x[i] != '\0'; i++) sum += (int) x[i]; return(sum % M);}

Bon si la somme est grande par rapport à M.

‘A’=65 et ‘Z’=90 pour des mots de 10 caractères, sum est entre 650 et 900.

Exemples (3)

ELF Hash: Executable and Linking Format (ELF), UNIX System V Release 4.

int ELFhash(char* key) { unsigned long h = 0; while(*key) { h = (h << 4) + *key++; unsigned long g = h & 0xF0000000L; if (g) h ^= g >> 24; h &= ~g; } return h % M;}

Adressage ouvert

Comment résoudre les collisions?Adressage ouvert: utilisation de listes.

Meilleur lorsque la table est conservé en mémoire

Adressage par sectionDivise la table en section.

– Exemple: 8 cases/section.

Inclut une section suplémentaire pour les surcharges.

On ajoute les enregistrements à partir de la première case de sa section. Si elle est pleine, on ajoute l’enregitrement dans la section suplémentaire.

Adressage fermé

Tous les enregistrement sont stocker directement dans la table.

Chaque enregistrement i a une case maîson h(ki).

Si un autre enregistrement occupe la case maîson de i’s alors une autre position doit être trouvée.

La nouvelle case dépend de la politique de résolution des conflits.

Les recherche doit utiliser la même politique de résolution des conflits.

Résolution des conflits

Pendant une insertion, le but d’une politique de résolution est de trouver une nouvelle case dans la table.

Séquence de recherche: La série de cases visitées au cours d’une opération insertion/recherche en suivant une politique de résolution des collision.

Soit 0 = h(K). Soit (0, 1, …) la séquence de recherche.

Fonction séquentielle

On suppose l’existence d’une fonction

p(k,i)

qui retourne le i-ième élément de la séquence de recherche.

Insertion

// Insère e dans la table HT

bool hashInsert(const Elem& e){ int home; int pos = home = h(e.clef)); for (int i=1; HT[pos]!=VIDE; i++) { pos=(home + p(e.clef, i) if (e == HT[pos]) return false; } HT[pos] = e; return true;}

Recherche

// Recherche l’enregistrement avec clef K

bool hashSearch(const Key& K, Elem& e){ int home; int pos = home = h(K); for (int i = 1; (K != HT[pos].clef) &&

(HT[pos]!= VIDE); i++) pos = (home + p(K, i)) % M; if (K== HT[pos].clef){ e = HT[pos]; return true; } else return false; }

Séquence linéaire

La fonction séquentielle la plus simple est la suivante:

p(K, i) = i % M

Après la fin, on revient au début.

Pour éviter de boucler à l’infini, une des case de la séquence est toujour VIDE.

ExempleAmas primaire: Les

enregistrement tendent à former des amas.

Chaque case n’a pas la même probabilité de recevoir un nouvel élément

Idée d’amélioration

On incrémente la position par une constante c>1– On doit alors choisir M et c minutieusement.

La séquence de recherche doit pouvoir visiter TOUTES les cases de la table.

– Prendre c relativement premier à M.

Les amas existent toujours– Ex: c=2, h(k1) = 3; h(k2) = 5.– Les séquences pour k1 et k2 sont liées.

Séquence pseudo-aléatoire(1)

La fonction séquentielle idéale choisirait la prochaine case de façon aléatoire.

Cela causerait cependant un problème sérieux (lequel?)

Séquence pseudo-aléatoire(2)

• Choisir une permutation aléatoire des nombres entre 1 et M-1:

r1, r2, …, rM-1

• Toutes les insertions et recherche utilise la même permutation.

Exemple: Table de taille M = 101– r1=2, r2=5, r3=32.– h(k1)=30, h(k2)=28.– Séquence pour k1: 30. 32, 35, 62– Séquence pour k2: 28, 30, 32, 60

Séquence quadratique

Prendre:p(K, i) = i2;

Exemple: M=101– h(k1)=30, h(k2) = 29.– Séquence pour k1 is: 30, 31, 34, 39– Séquence pour k2 is: 29, 30, 33, 38

Amas secondaire

Les séquence pseudo-aléatoires et quadratiques éliminent les amas primaires.

Si h(x)=h(y), alors ils suivent la même séquence. Cela est appelé amas secondaires.

Pour éviter les amas secondaires, on a besoin d’une fonction séquentielle p(K,i) qui utilise ses deux paramètres. position.

Hachage double

p(K,i)=i*h2(K)

Exemple: Table de taille M=101– h(k1)=30, h(k2)=28, h(k3)=30.– h2(k1)=2, h2(k2)=5, h2(k3)=5.– Séquence pour k1: 30, 32, 34, 36– Séquence pour k2: 28, 33, 38, 43– Séquence pour k3: 30, 35, 40, 45

Enlever un enregistrement

• Ne doit pas nuire aux recherches futures.

• On ne veut pas rendre une position inutilisable.

Marqueur (1)

Utilisation d’un marqueur.

N’arrête pas une recherche mais indique qu’une case est vide.

Marqueur (2)

Ajoute à la longueur des séquences de recherches.

Solutions:1. Réorganisation locale2. Refaire la table de façon périodique.