เมื่อใดที่ควรเลือก RB tree, B-Tree หรือ AVL tree?


88

ในฐานะโปรแกรมเมอร์ฉันควรพิจารณาใช้ต้นไม้ RB ต้นไม้ B หรือต้นไม้ AVL เมื่อใด ประเด็นสำคัญที่ต้องพิจารณาก่อนตัดสินใจเลือกคืออะไร?

ใครช่วยอธิบายด้วยสถานการณ์สำหรับโครงสร้างต้นไม้แต่ละต้นได้ไหมว่าทำไมจึงเลือกโครงสร้างต้นไม้อื่น ๆ โดยอ้างอิงถึงประเด็นสำคัญ


10
สำหรับคำถามนี้ฉันขอขอบคุณสำหรับคำถามนี้ - ปัจจุบันมีตัวเลือก fastutil IntAVLTreeSet เทียบกับ IntRBTreeSet
ยาง

คำตอบ:


115

ใช้เกลือเล็กน้อย:

B-tree เมื่อคุณจัดการรายการมากกว่าหลายพันรายการและคุณกำลังเพจจากดิสก์หรือสื่อจัดเก็บข้อมูลที่ทำงานช้า

RB tree เมื่อคุณทำการแทรกลบและดึงข้อมูลบนต้นไม้บ่อยพอสมควร

โครงสร้าง AVL เมื่อการแทรกและการลบของคุณไม่บ่อยนักเมื่อเทียบกับการดึงข้อมูลของคุณ


34
เพียงเพื่อเพิ่มรายละเอียดเพิ่มเติม: B-tree สามารถมีจำนวนลูกที่แตกต่างกันซึ่งอนุญาตให้มีการบันทึกจำนวนมาก แต่ยังคงรักษาต้นไม้ที่มีความสูงสั้นได้ RB Tree มีกฎที่เข้มงวดน้อยกว่าเกี่ยวกับการปรับสมดุลใหม่ซึ่งทำให้การแทรก / การลบเร็วกว่าทรี AVL ในทางกลับกันต้นไม้ AVL มีความสมดุลมากกว่าดังนั้นการค้นหาจึงเร็วกว่าต้นไม้ RB
pschang

ต้นไม้ RB ยังมีประสิทธิภาพที่ดีกว่า O (1) ในการปรับสมดุลซึ่งทำให้เหมาะสำหรับโครงสร้างข้อมูลแบบต่อเนื่องที่มีการย้อนกลับและย้อนกลับ

20

ฉันคิดว่าต้นไม้ B + เป็นโครงสร้างข้อมูลคอนเทนเนอร์ตามสั่งทั่วไปที่ดีแม้ในหน่วยความจำหลัก แม้ว่าหน่วยความจำเสมือนจะไม่ใช่ปัญหา แต่ความเป็นมิตรกับแคชก็มักจะเป็นเช่นกันและต้นไม้ B + นั้นดีอย่างยิ่งสำหรับการเข้าถึงตามลำดับ - ประสิทธิภาพแบบไม่แสดงอาการเช่นเดียวกับรายการที่เชื่อมโยง แต่มีความเป็นมิตรกับแคชใกล้เคียงกับอาร์เรย์ธรรมดา ทั้งหมดนี้และ O (log n) ค้นหาแทรกและลบ

ต้นไม้ B + จะมีปัญหาเช่นรายการที่เคลื่อนที่ไปมาภายในโหนดเมื่อคุณแทรก / ลบตัวชี้ที่ไม่ถูกต้องไปยังรายการเหล่านั้น ฉันมีไลบรารีคอนเทนเนอร์ที่ "การบำรุงรักษาเคอร์เซอร์" - เคอร์เซอร์จะแนบตัวเองกับโหนดลีฟที่กำลังอ้างอิงในรายการที่เชื่อมโยงอยู่ดังนั้นจึงสามารถแก้ไขหรือยกเลิกโดยอัตโนมัติ เนื่องจากไม่ค่อยมีเคอร์เซอร์มากกว่าหนึ่งหรือสองตัวจึงทำงานได้ดี - แต่มันก็ใช้งานได้ดีเหมือนกัน

อีกอย่างคือต้นไม้ B + มีพื้นฐานแค่นั้น ฉันเดาว่าคุณสามารถถอดหรือสร้างโหนดที่ไม่ใช่ลีฟใหม่ขึ้นอยู่กับว่าคุณต้องการหรือไม่ แต่ด้วยโหนดต้นไม้ไบนารีคุณจะมีความยืดหยุ่นมากขึ้น แผนภูมิไบนารีสามารถแปลงเป็นรายการที่เชื่อมโยงและย้อนกลับได้โดยไม่ต้องคัดลอกโหนด - คุณเพียงแค่เปลี่ยนคำแนะนำจากนั้นจำไว้ว่าคุณถือว่าเป็นโครงสร้างข้อมูลที่แตกต่างกันในขณะนี้ เหนือสิ่งอื่นใดนั่นหมายความว่าคุณจะได้รับ O (n) การรวมต้นไม้ที่ค่อนข้างง่าย - แปลงต้นไม้ทั้งสองเป็นรายการรวมเข้าด้วยกันแล้วแปลงกลับเป็นต้นไม้

อีกสิ่งหนึ่งคือการจัดสรรหน่วยความจำและการปลดปล่อย ในต้นไม้ไบนารีสิ่งนี้สามารถแยกออกจากอัลกอริทึม - ผู้ใช้สามารถสร้างโหนดจากนั้นเรียกใช้อัลกอริทึมการแทรกและการลบสามารถแยกโหนด (แยกออกจากทรี แต่อย่าปล่อยหน่วยความจำให้ว่าง) ใน B-tree หรือ B + -tree เห็นได้ชัดว่าใช้ไม่ได้ - ข้อมูลจะอยู่ในโหนดหลายรายการ การเขียนวิธีการแทรกที่ "วางแผน" การดำเนินการโดยไม่ต้องแก้ไขโหนดจนกว่าพวกเขาจะรู้ว่าจำเป็นต้องมีโหนดใหม่จำนวนเท่าใดและสามารถจัดสรรได้เป็นเรื่องที่ท้าทาย

แดงดำกับ AVL? ฉันไม่แน่ใจว่ามันสร้างความแตกต่างอย่างมาก ไลบรารีของฉันมีคลาส "เครื่องมือ" ตามนโยบายเพื่อจัดการโหนดโดยมีวิธีการสำหรับรายการที่เชื่อมโยงสองครั้งต้นไม้ไบนารีแบบง่ายต้นไม้สเปรย์ต้นไม้สีแดงดำและทรีปรวมถึงการแปลงต่างๆ วิธีการเหล่านั้นบางส่วนถูกนำไปใช้เพียงเพราะฉันเบื่อในคราวเดียว ฉันไม่แน่ใจว่าฉันได้ทดสอบวิธีการเหยียบแล้ว เหตุผลที่ฉันเลือกต้นไม้สีแดง - ดำมากกว่า AVL เป็นเพราะฉันเองเข้าใจอัลกอริทึมดีกว่า - ซึ่งไม่ได้หมายความว่ามันง่ายกว่า แต่เป็นเพียงความบังเอิญในประวัติศาสตร์ที่ฉันคุ้นเคยกับพวกเขามากกว่า

สิ่งสุดท้าย - เดิมทีฉันพัฒนาคอนเทนเนอร์ต้นไม้ B + ของฉันเพื่อเป็นการทดลองเท่านั้น เป็นการทดลองอย่างหนึ่งที่ไม่เคยสิ้นสุดจริงๆ แต่ไม่ใช่สิ่งที่ฉันแนะนำให้คนอื่นทำซ้ำ หากสิ่งที่คุณต้องการคือคอนเทนเนอร์ที่สั่งซื้อคำตอบที่ดีที่สุดคือใช้สิ่งที่ไลบรารีที่คุณมีอยู่ให้ - เช่น std :: map ฯลฯ ใน C ++ ห้องสมุดของฉันพัฒนามาหลายปีใช้เวลาพอสมควรกว่าจะเสถียรและฉันเพิ่งค้นพบเมื่อไม่นานมานี้ว่ามันไม่สามารถพกพาได้ในทางเทคนิค (ขึ้นอยู่กับพฤติกรรมที่ไม่ได้กำหนด WRT offsetof)


5

ในความทรงจำทรี B มีความได้เปรียบเมื่อจำนวนของรายการที่เป็นมากกว่า 32000 ... ดูที่speedtest.pdfจากSTX-btree


0

เมื่อเลือกโครงสร้างข้อมูลคุณกำลังแลกเปลี่ยนปัจจัยต่างๆเช่น

  • ความเร็วในการดึงข้อมูล v ความเร็วของการอัปเดต
  • โครงสร้างสามารถรับมือกับการดำเนินการกรณีที่เลวร้ายที่สุดได้ดีเพียงใดตัวอย่างเช่นการแทรกระเบียนที่มาในลำดับที่เรียงลำดับ
  • เสียพื้นที่

ฉันจะเริ่มต้นด้วยการอ่านบทความ Wikipedia ที่อ้างอิงโดย Robert Harvey

ในทางปฏิบัติเมื่อทำงานในภาษาเช่น Java โปรแกรมเมอร์โดยเฉลี่ยมักจะใช้คลาสคอลเลกชันที่มีให้ หากในกิจกรรมการปรับแต่งประสิทธิภาพพบว่าประสิทธิภาพการรวบรวมมีปัญหาก็สามารถหาวิธีใช้งานอื่นได้ ไม่ค่อยเป็นสิ่งแรกที่การพัฒนาที่นำโดยธุรกิจต้องพิจารณา เป็นเรื่องยากมากที่จะต้องใช้โครงสร้างข้อมูลด้วยมือโดยปกติจะมีไลบรารีที่สามารถใช้งานได้


1
เพื่อความเป็นธรรม, OP ถามไม่ได้when should I consider using when should I consider implementingแม้ว่าย่อหน้าสุดท้ายจะเป็นจริง แต่ก็ไม่ได้ให้คุณค่ามากนักในบริบทของคำถามนี้ แม้จะมีห้องสมุด แต่คุณต้องเข้าใจอัลกอริทึมเพื่อที่จะเลือกโครงสร้างที่เหมาะสมกับความต้องการทางธุรกิจของคุณได้อย่างมีประสิทธิภาพ
Dan Bechard
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.