ทำไมการค้นหาแบบไบนารี่จึงเร็วกว่าการค้นหาแบบไตรภาค


49

การค้นหาอาเรย์ขององค์ประกอบโดยใช้การค้นหาแบบไบนารี่จะใช้เวลาในกรณีที่ซ้ำที่สุดการทำซ้ำเพราะในแต่ละขั้นตอนเราตัดแบ่งครึ่งของพื้นที่การค้นหาของเรา หากเราใช้ 'การค้นหาแบบไตรภาค' แทนเราจะตัดพื้นที่การค้นหาของเราสองในสามในแต่ละการวนซ้ำดังนั้นกรณีที่แย่ที่สุดควรใช้การซ้ำ ...log 2 N log 3 N < log 2 NNlog2Nlog3N<log2N

ดูเหมือนว่าการค้นหาแบบไตรภาคเร็วกว่าแล้วทำไมเราถึงใช้การค้นหาแบบไบนารี่?


3
หนึ่งไม่สามารถใช้เหตุผลเดียวกันเกี่ยวกับการค้นหา Quaternary? หรือแม้แต่การค้นหาทศนิยม ... หรืออะไรที่มีขนาดใหญ่กว่า 2
d'alar'cop

4
โปรดอ่านเกี่ยวกับ B + Trees
arunmoezhi

5
การค้นหาแบบเชิงเส้นมักจะเร็วกว่าการค้นหาแบบไบนารี่สำหรับปัญหาที่มีขนาดเล็กถึงขนาดกลางบนฮาร์ดแวร์ที่ทันสมัยเนื่องจากมีการเชื่อมโยงกันของแคชและเกือบทุกสาขาจะทำนายได้อย่างถูกต้อง
นามแฝง

2
นอกจากนี้ 2 * log_3 (N) = log_3 (N ^ 2) ถ้ามันพูดกับสัญชาตญาณของคุณ
PawelP

6
ลองนำสิ่งนี้มาเป็นคำศัพท์ที่เข้าใจง่าย หากใช้การค้นหาแบบ 3 รายการจะเร็วกว่าเพราะจะลดพื้นที่การค้นหาได้มากขึ้นในการทำซ้ำแต่ละครั้งดังนั้นการใช้การค้นหาแบบอิงล้านครั้งนั้นไม่เร็วกว่านี้หรือไม่ แต่คุณสามารถเห็นได้อย่างง่ายดายว่าโดยเฉลี่ยคุณต้องตรวจสอบ 500,000 ครั้งภายในแต่ละรอบซ้ำเพื่อกำหนดชิ้นที่ 1 ล้านที่มีเป้าหมาย เห็นได้ชัดว่าการตัดช่องว่างในการค้นหาซ้ำในแต่ละครึ่งและไม่มากทำให้คุณได้รับข้อมูลมากที่สุดในขั้นตอนเดียวเชื่อถือได้
ErikE

คำตอบ:


76

หากคุณใช้การค้นหาแบบไบนารีคุณมีการเปรียบเทียบจำนวนมาก หากคุณใช้การค้นหาแบบไตรภาคคุณมีการเปรียบเทียบจำนวนมากเช่นเดียวกับในแต่ละขั้นตอนคุณจะต้องทำการเปรียบเทียบ 2 ครั้งเพื่อตัดพื้นที่การค้นหาออกเป็นสามส่วน ตอนนี้ถ้าคุณทำคณิตศาสตร์คุณสามารถสังเกตได้ว่า: เนื่องจากเรารู้ว่าเราได้รับการเปรียบเทียบเพิ่มเติมกับการค้นหาแบบไตรภาค

log2(n)+O(1)
2log3(n)+O(1)
2log3(n)+O(1)=2log(2)log(3)log2(n)+O(1)
2log(2)log(3)>1

โดยวิธีการ: การค้นหาแบบ -ary อาจจะสมเหตุสมผลในกรณีที่การเปรียบเทียบค่อนข้างมีราคาแพงและสามารถทำการขนานกันได้ในขณะนั้นคอมพิวเตอร์แบบขนานสามารถใช้งานได้n

โปรดทราบว่าอาร์กิวเมนต์สามารถวางนัยให้การค้นหาแบบ -ary ค่อนข้างง่าย คุณเพียงแค่ต้องแสดงให้เห็นว่าฟังก์ชันเป็นเสียงเดียวอย่างเคร่งครัดเพิ่มขึ้นสำหรับค่าจำนวนเต็มของkf ( k ) = ( k - 1 ) บันทึก( 2 )n kf(k)=(k1)log(2)log(k)k


1
และ LHS เป็นเส้นตรงและ RHS เป็นลอการิทึมดังนั้นมันจะไม่ช่วยอะไรสี่อย่างหรืออะไรมากกว่านั้น .... คำอธิบายที่ดี .... ขอบคุณ
The Mean Square

3
เพื่อประโยชน์ของความสมบูรณ์: โปรดทราบว่าการวัดเชิงนามธรรมเช่นจำนวนการเปรียบเทียบองค์ประกอบอาจหรือไม่อาจควบคุมรันไทม์ที่เกิดขึ้นจริง โดยเฉพาะอย่างยิ่งคุณอาจต้องพิจารณาถึงจำนวนแคชที่คุณอาจได้รับในอาร์เรย์ที่ยาวด้วยการค้นหาอย่างใดอย่างหนึ่ง (ที่นี่พวกเขาตรงฉันเพียงแค่สังเกตเพราะ OP ถามว่า "ทำไมมันเร็วกว่านี้?" และตอบว่าด้วยการวัดที่เป็นนามธรรมสามารถทำให้เข้าใจผิดสำหรับอัลกอริทึมบางอย่าง)
Raphael

10
ในการค้นหาแบบไตรภาค 1/3 ของเวลาที่คุณจะต้องทำการเปรียบเทียบ 1 ครั้งเท่านั้น (ทำการเปรียบเทียบที่ต่ำกว่า: หากในส่วนที่สามต่ำกว่าคุณไม่จำเป็นต้องทำการเปรียบเทียบครั้งที่สอง) สิ่งนั้นทำให้ ternary เพียงประมาณ 5% ช้าลงแทนที่จะเป็น 25% (ในโลกนี้ที่เราสนใจเพียงแค่การเปรียบเทียบการนับ) ฉันไม่แน่ใจว่าจะพูดคุยเรื่องนี้กับ n-ary อย่างไรแม้ว่าฉันจะสงสัยว่ามันจะไม่เร็วกว่าระบบเลขฐานสอง
Aaron Dufour

2
@AaronDufour: เนื่องจากเราสามารถทำการค้นหาแบบ quaternary โดยเปรียบเทียบกับรายการระดับกลางก่อนจากนั้นจึงข้ามผลลัพธ์ของการเปรียบเทียบอื่น ๆ การค้นหาแบบ quaternary เพียงวิธีเดียวอาจทำได้เร็วกว่าหากการเปรียบเทียบสามแบบสามารถทำได้ในแบบขนานมากกว่าราคาที่เปรียบเทียบสองครั้ง สามารถดำเนินการตามลำดับ
supercat

1
@AaronDufour แต่คุณต้องตัดค่าใช้จ่ายมากกว่าองค์ประกอบเพื่อค้นหาและมันไม่ชัดเจนสำหรับฉันว่าทำไมมันโอเค ในกรณีที่เลวร้ายที่สุดการเปรียบเทียบทั้งสองอาจทำได้ในทุกขั้นตอน
Sasho Nikolov

26

DCTLib นั้นถูกต้อง แต่ลืมคณิตศาสตร์ไปหนึ่งวินาที

โดยตรรกะของคุณแล้วn -ary ควรจะเร็วที่สุด แต่ถ้าคุณคิดเกี่ยวกับมันn -ary จะเท่ากับการค้นหาการวนซ้ำปกติ (เพียงแค่วนซ้ำในรายการ 1 คูณ 1 แต่เรียงตามลำดับย้อนหลัง) ก่อนอื่นให้คุณเลือกรายการสุดท้าย (หรือถัดจากสุดท้าย) ในรายการและเปรียบเทียบค่านั้นกับค่าการเปรียบเทียบของคุณ จากนั้นคุณลบรายการนั้นออกจากรายการของคุณแล้วเลือกรายการสุดท้ายในรายการใหม่ซึ่งเป็นเพียงถัดจากค่าสุดท้ายในอาร์เรย์ แต่ละครั้งคุณจะกำจัดค่า 1 ครั้งเท่านั้นจนกว่าคุณจะพบค่าของคุณ

คุณควรคิดแบบนี้แทน - ฉันจะกำจัดค่ามากที่สุดจากรายการแต่ละการวนซ้ำได้อย่างไร ในการค้นหาแบบไบนารีคุณจะกำจัดรายการครึ่งหนึ่งได้เสมอ ในการค้นหาแบบไตรภาคมีความเป็นไปได้ (33.33% มีโอกาสจริง ๆ ) ที่คุณสามารถกำจัด 2/3 ของรายการ แต่มีโอกาสมากขึ้น (66.66%) ที่คุณจะกำจัดเพียงหนึ่งในสามของรายการ ในการคำนวณ O (n) คุณต้องดูสถานการณ์กรณีที่เลวร้ายที่สุดคือ 1/3 ซึ่งน้อยกว่า 1/2 เมื่อคุณเข้าใกล้ n มากขึ้นเรื่อย ๆ มันยิ่งแย่ลงไปอีก

สถานการณ์กรณีที่เลวร้ายที่สุดไม่เพียง แต่จะได้รับการปรับปรุงด้วยการค้นหาแบบไบนารี แต่เวลาเฉลี่ยของคุณก็จะดีขึ้นเช่นกัน ดูค่าที่คาดหวัง (ส่วนใดของรายการที่เราสามารถลบได้โดยเฉลี่ย) เราใช้สูตรนี้:

(P_lower) x (ส่วนที่เราสามารถลบได้ถ้าต่ำกว่า) + (P_higher) x (ส่วนที่เราสามารถลบได้ถ้าสูงกว่า) = E

สำหรับการค้นหาแบบไบนารีนี่คือ. 5x.5 + .5x.5 = .5 (เราลบครึ่งรายการเสมอ) สำหรับการค้นหาแบบไตรภาคค่านี้คือ. 666x.333 + .333x.666 = 0.44 หรือในแต่ละขั้นตอนเรามีแนวโน้มที่จะลบ 44% ของรายการเท่านั้นทำให้มีประสิทธิภาพน้อยกว่าการค้นหาแบบไบนารีโดยเฉลี่ย ค่านี้มีค่าสูงสุดที่ 1/2 (ครึ่งหนึ่งของรายการ) และลดค่าที่คุณได้รับให้ใกล้กับ n (กลับรายการซ้ำ) และ 0 (การวนซ้ำปกติ)

ตกลงดังนั้นฉันโกหก .. มีคณิตศาสตร์เล็กน้อยที่เกี่ยวข้อง แต่ฉันหวังว่าจะช่วยได้!


1
นี่คือคำตอบที่ดี
The_Sympathizer

การวิเคราะห์ขอบเขตยาช่วยให้เข้าใจคณิตศาสตร์อย่างหนัก! การค้นหาตามลำดับ n-ary มีค่าใช้จ่ายการค้นหาเชิงเส้น O (n) เท่ากัน
shuva

-2

โปรดทราบว่าการเปรียบเทียบ log (N) vs 2 log (N) นั้นขึ้นอยู่กับการตีความของอัลกอริทึมที่ไร้เดียงสา หากฉันต้องนั่งลงและเขียนสิ่งนี้ในชุดประกอบ x86 ผลลัพธ์จะกลับด้าน ปัญหาคือการใช้จำนวนเต็มสำหรับกรณีทดสอบรวมกับคอมไพเลอร์สมาร์ทไม่เพียงพอที่ไม่สามารถลบการเปรียบเทียบซ้ำซ้อน ลองอีกครั้งกับสตริงและฟังก์ชั่นการเปรียบเทียบสตริงที่เหมาะสมและรหัสเพื่อเรียกฟังก์ชั่นการเปรียบเทียบหนึ่งครั้งต่อวงและคุณจะพบว่าการค้นหาแบบไตรภาคจะเร็วขึ้นอีกครั้ง


2
แน่นอนว่าการค้นหาแบบไตรภาคจะเร็วขึ้นหากคุณสามารถทำได้ด้วยการเปรียบเทียบเพียงครั้งเดียวต่อการวนซ้ำ แต่ไม่ว่าจะเป็นสตริงหรือจำนวนเต็มคุณไม่สามารถทำได้
FrankW

การเปรียบเทียบจะไม่ซ้ำซ้อนและปัญหาไม่เกี่ยวข้องกับคอมไพเลอร์ ในการแบ่งพื้นที่ค้นหาออกเป็นสามส่วนคุณต้องเปรียบเทียบ 2 รายการ ในการค้นหาแบบไบนารีคุณจะต้องเปรียบเทียบกับองค์ประกอบกลางและจากนั้นคุณรู้ว่าครึ่งหนึ่งของพื้นที่การค้นหาที่ผลลัพธ์จะอยู่ในการค้นหาแบบไตรภาคคุณจะต้องเปรียบเทียบกับองค์ประกอบ 1/3 ของวิธีผ่าน รายการและหนึ่งใน 2/3 ของทางผ่านรายการ ข้อมูลประเภทใดที่คุณกำลังเปรียบเทียบหรือภาษาที่คุณใช้ไม่เกี่ยวข้อง จริงอยู่ถ้ารายการนั้นอยู่ในอันดับที่ 1 คุณสามารถหยุดหลังจากการเปรียบเทียบ 1 รายการ
reirab

2
ในบางแพลตฟอร์มการค้นหาแบบไตรภาคอาจเร็วขึ้นเนื่องจากทำให้ CPU มีเวลามากขึ้นในการดึงข้อมูลตัวถูกดำเนินการจาก RAM ก่อนที่จะต้องทำการเปรียบเทียบ แต่นั่นขึ้นอยู่กับแพลตฟอร์มที่ใช้และเวลาในการตอบสนองและแคช
jpa

1
Darn it - คำจำกัดความที่ไม่ถูกต้องของการค้นหาแบบไตรภาค
Joshua
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.