Maps และ Dictionaries

dictionaries และ maps ของ MicroPython ใช้เทคนิคที่เรียกว่า open addressing และ linear probing บทนี้อธิบายรายละเอียดทั้งสองวิธีนี้

Open addressing

Open addressing ถูกใช้เพื่อแก้ไขการชน การชนเกิดขึ้นบ่อยมากและเกิดขึ้นเมื่อสองรายการมี hash ไปยัง slot หรือตำแหน่งเดียวกัน ตัวอย่างเช่น กำหนดการตั้งค่า hash แบบนี้:

../_images/collision.png

หากมีคำขอเติม slot 0 ด้วย 70 เนื่องจาก slot 0 ไม่ว่าง open addressing จะหา slot ถัดไปที่ว่างใน dictionary เพื่อดำเนินการตามคำขอนี้ การค้นหาตามลำดับสำหรับตำแหน่งสำรองนี้เรียกว่า probing มีอัลกอริทึม probing ลำดับหลายชนิดแต่ MicroPython ใช้ linear probing ที่อธิบายในส่วนถัดไป

Linear probing

Linear probing เป็นหนึ่งในวิธีการหาที่อยู่หรือ slot ที่ว่างใน dictionary ใน MicroPython ใช้ร่วมกับ open addressing เพื่อดำเนินการตามคำขอที่อธิบายข้างต้น ต่างจากอัลกอริทึม probing อื่น ๆ linear probing สันนิษฐานช่วงคงที่ 1 ระหว่างการ probe คำขอจะถูกดำเนินการโดยการวางรายการใน slot ว่างถัดไปซึ่งคือ slot 4 ในตัวอย่างของเรา:

../_images/linprob.png

วิธีการเดียวกัน กล่าวคือ open addressing และ linear probing ถูกใช้เพื่อค้นหารายการใน dictionary สมมติว่าเราต้องการค้นหา data item 33 ค่า hash ที่คำนวณได้จะเป็น 2 การมองที่ slot 2 เผย 33 ณ จุดนี้ เราคืนค่า True การค้นหา 70 ค่อนข้างแตกต่างเนื่องจากมีการชนในเวลาของการแทรก ดังนั้นค่า hash ที่คำนวณได้คือ 0 ซึ่งปัจจุบันถือ 44 แทนที่จะคืนค่า False เฉย ๆ เราทำการค้นหาตามลำดับเริ่มต้นที่จุด 1 จนกว่าจะพบรายการ 70 หรือเราพบ slot ว่าง นี่คือวิธีทั่วไปในการทำการค้นหาใน hashes:

// 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;
}