Hărți și dicționare#

Dicționarele și hărțile MicroPython folosesc tehnici numite adresare deschisă și sondare liniară. Acest capitol detaliază ambele metode.

Adresarea deschisă#

Adresarea deschisă este folosită pentru a rezolva coliziunile. Coliziunile apar foarte frecvent și se produc atunci când două elemente ajung să aibă același hash, adresând aceeași locație sau același slot. De exemplu, având o configurație de hash ca aceasta:

../../_images/collision.png

Dacă există o cerere de a umple slotul 0 cu 70, deoarece slotul 0 nu este gol, adresarea deschisă găsește următorul slot disponibil din dicționar pentru a servi această cerere. Această căutare secvențială a unei locații alternative se numește sondare. Există mai mulți algoritmi de sondare secvențială, dar MicroPython folosește sondarea liniară, descrisă în secțiunea următoare.

Sondarea liniară#

Sondarea liniară este una dintre metodele de găsire a unei adrese sau a unui slot disponibil într-un dicționar. În MicroPython, este folosită împreună cu adresarea deschisă. Pentru a servi cererea descrisă mai sus, spre deosebire de alți algoritmi de sondare, sondarea liniară presupune un interval fix de 1 între sondări. Cererea va fi deci servită prin plasarea elementului în următorul slot liber, care este slotul 4 în exemplul nostru:

../../_images/linprob.png

Aceleași metode, adică adresarea deschisă și sondarea liniară, sunt folosite pentru a căuta un element într-un dicționar. Să presupunem că dorim să căutăm elementul de date 33. Valoarea hash calculată va fi 2. Examinarea slotului 2 dezvăluie 33. În acest punct, returnăm True. Căutarea lui 70 este destul de diferită, deoarece a existat o coliziune la momentul inserării. Prin urmare, valoarea hash calculată este 0, care în prezent conține 44. În loc să returnăm pur și simplu False, efectuăm o căutare secvențială începând din punctul 1 până când elementul 70 este găsit sau întâlnim un slot liber. Aceasta este modalitatea generală de a efectua căutări în hash-uri:

// not yet found, keep searching in this table
pos = (pos + 1) % set->alloc;

if (pos == start_pos) {
    // search got back to starting position, so index is not in table
    if (lookup_kind & MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) {
        if (avail_slot != NULL) {
            // there was an available slot, so use that
            set->used++;
            *avail_slot = index;
            return index;
        } else {
            // not enough room in table, rehash it
            mp_set_rehash(set);
            // restart the search for the new element
            start_pos = pos = hash % set->alloc;
        }
    }
} else {
     return MP_OBJ_NULL;
}