TL; DR: ตารางแฮชรับประกันO(1)ว่าจะเกิดกรณีเลวร้ายที่สุดหากคุณเลือกฟังก์ชันแฮชของคุณอย่างสม่ำเสมอโดยการสุ่มจากฟังก์ชันแฮชสากล กรณีที่เลวร้ายที่สุดที่คาดไว้ไม่เหมือนกับกรณีทั่วไป
ข้อจำกัดความรับผิดชอบ:ฉันไม่ได้พิสูจน์อย่างเป็นทางการว่าตารางแฮชO(1)นั้นเป็นอย่างไรลองดูวิดีโอนี้จาก coursera [ 1 ] ฉันยังไม่ได้พูดคุยเกี่ยวกับลักษณะการตัดจำหน่ายของตารางแฮช นั่นคือมุมฉากของการอภิปรายเกี่ยวกับการแฮชและการชนกัน
ฉันเห็นความสับสนอย่างมากเกี่ยวกับหัวข้อนี้ในคำตอบและความคิดเห็นอื่น ๆ และจะพยายามแก้ไขบางส่วนในคำตอบยาว ๆ นี้
การให้เหตุผลเกี่ยวกับกรณีที่เลวร้ายที่สุด
การวิเคราะห์กรณีที่เลวร้ายที่สุดมีหลายประเภท การวิเคราะห์คำตอบส่วนใหญ่ในที่นี้ไม่ใช่กรณีที่เลวร้ายที่สุด แต่เป็นกรณีเฉลี่ย [ 2 ] การวิเคราะห์กรณีโดยเฉลี่ยมีแนวโน้มที่จะนำไปใช้ได้จริงมากกว่า บางทีอัลกอริทึมของคุณอาจมีอินพุตกรณีเลวร้ายที่สุดตัวหนึ่ง แต่ใช้งานได้ดีสำหรับอินพุตอื่น ๆ ทั้งหมดที่เป็นไปได้ Bottomline คือรันไทม์ของคุณขึ้นอยู่กับชุดข้อมูลที่คุณใช้งานอยู่
พิจารณา pseudocode ต่อไปนี้ของgetวิธีการของตารางแฮช ที่นี่ฉันสมมติว่าเราจัดการการชนกันโดยการผูกมัดดังนั้นแต่ละรายการของตารางจึงเป็นรายการ(key,value)คู่ที่เชื่อมโยงกัน นอกจากนี้เรายังถือว่าจำนวนถังmได้รับการแก้ไข แต่O(n)ที่nเป็นจำนวนขององค์ประกอบในการป้อนข้อมูล
function get(a: Table with m buckets, k: Key being looked up)
bucket <- compute hash(k) modulo m
for each (key,value) in a[bucket]
return value if k == key
return not_found
ในฐานะที่เป็นคำตอบอื่น ๆ ที่มีออกแหลมวิ่งนี้เฉลี่ยและกรณีที่เลวร้ายO(1) O(n)เราสามารถร่างบทพิสูจน์เล็ก ๆ น้อย ๆ ได้โดยการท้าทายที่นี่ ความท้าทายมีดังนี้:
(1) คุณให้อัลกอริทึมตารางแฮชของคุณแก่ฝ่ายตรงข้าม
(2) ฝ่ายตรงข้ามสามารถศึกษาและเตรียมตัวได้นานเท่าที่เขาต้องการ
(3) ในที่สุดฝ่ายตรงข้ามจะให้ข้อมูลขนาดnเพื่อให้คุณแทรกในตารางของคุณ
คำถามคือตารางแฮชของคุณอยู่บนอินพุตของฝ่ายตรงข้ามเร็วแค่ไหน?
จากขั้นตอนที่ (1) ฝ่ายตรงข้ามรู้ฟังก์ชันแฮชของคุณ ในขั้นตอนที่ (2) ฝ่ายตรงข้ามสามารถสร้างรายการnองค์ประกอบที่เหมือนกันhash modulo mได้โดยการสุ่มคำนวณแฮชขององค์ประกอบจำนวนมาก จากนั้นใน (3) พวกเขาสามารถให้รายการนั้นแก่คุณได้ แต่ดูเถิดเนื่องจากnองค์ประกอบทั้งหมดแฮชไปยังที่เก็บข้อมูลเดียวกันอัลกอริทึมของคุณจะใช้O(n)เวลาในการสำรวจรายการที่เชื่อมโยงในที่เก็บข้อมูลนั้น O(n)กี่ครั้งที่เราลองใหม่อีกครั้งความท้าทายไม่มีศัตรูชนะเสมอและที่ว่าไม่ดีขั้นตอนวิธีการของคุณคือกรณีที่เลวร้ายที่สุด
การแฮชเป็นอย่างไร O (1)?
สิ่งที่ทำให้เราผิดหวังในความท้าทายก่อนหน้านี้คือฝ่ายตรงข้ามรู้จักฟังก์ชันแฮชของเราเป็นอย่างดีและสามารถใช้ความรู้นั้นเพื่อสร้างข้อมูลที่แย่ที่สุดเท่าที่จะเป็นไปได้ จะเกิดอะไรขึ้นถ้าแทนที่จะใช้ฟังก์ชันแฮชคงที่เสมอเรามีชุดของฟังก์ชันแฮชHซึ่งอัลกอริทึมสามารถสุ่มเลือกจากรันไทม์ได้? ในกรณีที่คุณอยากรู้อยากเห็นHเรียกว่าฟังก์ชันแฮชสากล [ 3 ] เอาล่ะเรามาลองเพิ่มการสุ่มกันดีกว่า
ก่อนอื่นสมมติว่าตารางแฮชของเรามีเมล็ดพันธุ์rด้วยและrกำหนดให้เป็นตัวเลขสุ่มในเวลาก่อสร้าง เรากำหนดครั้งเดียวแล้วแก้ไขสำหรับอินสแตนซ์ตารางแฮชนั้น ตอนนี้เรามาดูรหัสเทียมของเราอีกครั้ง
function get(a: Table with m buckets and seed r, k: Key being looked up)
rHash <- H[r]
bucket <- compute rHash(k) modulo m
for each (key,value) in a[bucket]
return value if k == key
return not_found
ถ้าเราพยายามท้าทายอีกครั้งหนึ่ง: จากขั้นตอนที่ (1) ฝ่ายตรงข้ามสามารถรู้ทุกฟังก์ชันแฮชที่เรามีในแต่ตอนนี้ฟังก์ชั่นที่เฉพาะเจาะจงกัญชาเราขึ้นอยู่กับการใช้งานH rมูลค่าของrมันเป็นส่วนตัวสำหรับโครงสร้างของเราฝ่ายตรงข้ามไม่สามารถตรวจสอบได้ที่รันไทม์หรือคาดการณ์ล่วงหน้าดังนั้นเขาจึงไม่สามารถสร้างรายการที่ไม่ดีสำหรับเราได้เสมอไป สมมติว่าในขั้นตอนที่ (2) ฝ่ายตรงข้ามเลือกหนึ่งฟังก์ชั่นhashในการHที่สุ่มจากนั้นเขาก็ฝีมือรายการnชนภายใต้hash modulo mและส่งว่าสำหรับขั้นตอน (3) นิ้วข้ามว่าที่รันไทม์H[r]จะเหมือนกันhashที่พวกเขาเลือก
นี่คือทางออกที่ร้ายแรงสำหรับปฏิปักษ์รายการที่เขาสร้างขึ้นมาภายใต้ collides hashแต่จะเป็นเพียงการป้อนข้อมูลแบบสุ่มภายใต้กัญชาฟังก์ชันอื่น ๆ Hใน ถ้าเขาชนะเดิมพันนี้เวลาทำงานของเราจะเป็นกรณีที่เลวร้ายO(n)เหมือนก่อน แต่ถ้าเขาสูญเสียแล้วดีเราก็จะได้รับการป้อนข้อมูลแบบสุ่มซึ่งจะมีค่าเฉลี่ยของO(1)เวลา และแน่นอนที่สุดครั้งที่ฝ่ายตรงข้ามจะแพ้เขาชนะเพียงครั้งเดียวในทุก|H|ความท้าทายและเราสามารถสร้างราย|H|ใหญ่ได้มาก
เปรียบเทียบผลลัพธ์นี้กับอัลกอริทึมก่อนหน้าซึ่งฝ่ายตรงข้ามชนะการท้าทายเสมอ การโบกมือที่นี่เล็กน้อย แต่เนื่องจากส่วนใหญ่แล้วฝ่ายตรงข้ามจะล้มเหลวและนี่เป็นเรื่องจริงสำหรับกลยุทธ์ที่เป็นไปได้ทั้งหมดที่ฝ่ายตรงข้ามสามารถลองได้ตามมาว่าแม้ว่าจะเป็นกรณีO(n)ที่เลวร้ายที่สุด แต่ในความเป็นจริงO(1)แล้วกรณีที่เลวร้ายที่สุดที่คาดไว้ก็คือ
อีกครั้งนี่ไม่ใช่การพิสูจน์อย่างเป็นทางการ การรับประกันที่เราได้รับจากการวิเคราะห์กรณีที่เลวร้ายที่สุดที่คาดไว้นี้คือเวลาทำงานของเราไม่ขึ้นอยู่กับข้อมูลใด นี่เป็นการรับประกันแบบสุ่มอย่างแท้จริงเมื่อเทียบกับการวิเคราะห์กรณีโดยเฉลี่ยที่เราแสดงให้เห็นว่าฝ่ายตรงข้ามที่มีแรงจูงใจสามารถสร้างปัจจัยการผลิตที่ไม่ดีได้อย่างง่ายดาย