กลับไปหน้าบทความ

อ่าน 12 นาที

ต้นไม้ AVL

ใน วิทยาการคอมพิวเตอร์ ต้นไม้ AVL (ตั้งชื่อตามผู้คิดค้นคือ Adelson - Velsky และ Landis ) คือ ต้นไม้ค้นหาแบบไบนารีที่ปรับสมดุลได้เอง ในต้นไม้ AVL ความสูงของ ต้นไม้ย่อย ลูก สอง...

ต้นไม้ AVL

ต้นไม้ AVL
พิมพ์ต้นไม้
ประดิษฐ์พ.ศ. 2505
คิดค้นโดยจอร์จี อเดลสัน-เวลสกีและเอฟเกนี แลนดิส
ความซับซ้อนในสัญกรณ์บิ๊กโอ
ความซับซ้อนของพื้นที่
ช่องว่าง
ความซับซ้อนเชิงเวลา
การทำงานตัดจำหน่ายกรณีที่เลวร้ายที่สุด
ค้นหา[ 1 ][ 1 ]
แทรก[ 1 ][ 1 ]
ลบ[ 1 ][ 1 ]
ภาพเคลื่อนไหวแสดงการแทรกองค์ประกอบหลายอย่างลงในโครงสร้าง AVL ซึ่งรวมถึงการหมุนไปทางซ้าย ขวา ซ้ายขวา และขวาซ้าย
รูปที่ 1: แผนภูมิ AVL พร้อมปัจจัยสมดุล (สีเขียว)

ในวิทยาการคอมพิวเตอร์ต้นไม้AVL (ตั้งชื่อตามผู้คิดค้นคือAdelson - VelskyและLandis ) คือต้นไม้ค้นหาแบบไบนารีที่ปรับสมดุลได้เองในต้นไม้ AVL ความสูงของ ต้นไม้ย่อย ลูก สอง ต้นของโหนดใดๆ จะแตกต่างกันไม่เกินหนึ่ง หากเมื่อใดก็ตามที่แตกต่างกันมากกว่าหนึ่ง จะมีการปรับสมดุลใหม่เพื่อคืนค่าคุณสมบัตินี้ การค้นหา การแทรก และการลบทั้งหมดใช้ เวลา O (log n )ทั้งในกรณีเฉลี่ยและกรณีที่เลวร้ายที่สุด โดยที่ n คือจำนวนโหนดในต้นไม้ก่อนการดำเนินการ การแทรกและการลบอาจต้องมีการปรับสมดุลต้นไม้ ใหม่ โดย การหมุนต้นไม้หนึ่งครั้งหรือมากกว่านั้น

ต้นไม้ AVL ได้รับการตั้งชื่อตามนักประดิษฐ์ชาวโซเวียต สองคนคือ Georgy Adelson-VelskyและEvgenii Landisซึ่งตีพิมพ์ในบทความปี 1962 ของพวกเขาเรื่อง "อัลกอริทึมสำหรับการจัดระเบียบข้อมูล" [ 2 ] นับเป็น โครงสร้างข้อมูล ต้นไม้ค้นหาไบนารีแบบปรับสมดุลตัวเองตัวแรกที่ถูกคิดค้นขึ้น[ 3 ]

ต้นไม้ AVL มักถูกเปรียบเทียบกับต้นไม้แดง-ดำเนื่องจากทั้งสองรองรับชุดการดำเนินการเดียวกันและใช้เวลาในการดำเนินการพื้นฐาน สำหรับแอปพลิเคชันที่เน้นการค้นหา ต้นไม้ AVL จะเร็วกว่าต้นไม้แดง-ดำ เนื่องจากมีความสมดุลที่เข้มงวดกว่า[ 4 ]เช่นเดียวกับต้นไม้แดง-ดำ ต้นไม้ AVL มีความสมดุลของความสูง โดยทั่วไปแล้วทั้งสองจะไม่สมดุลของน้ำหนักหรือสมดุลของค่าใดๆ[ 5 ] กล่าวคือ โหนดพี่น้องสามารถมีจำนวนลูกหลานที่แตกต่างกันอย่างมาก

คำนิยาม

ปัจจัยสมดุล

ในต้นไม้ไบนารีปัจจัยสมดุลของโหนดXถูกกำหนดให้เป็นผลต่างความสูง

[ 6 ] : 459

โดยมีโหนดลูกย่อยสอง โหนด เป็นรากที่โหนดX

ต้นไม้ไบนารีจะถูกนิยามว่าเป็นต้นไม้ AVLถ้า

ใช้ได้กับทุกโหนดXในต้นไม้

โหนดXที่มีเรียกว่า "หนักซ้าย" โหนดที่มีเรียกว่า "หนักขวา" และโหนดที่มีบางครั้งเรียกว่า "สมดุล"

คุณสมบัติ

ปัจจัยสมดุลสามารถอัปเดตได้โดยการทราบปัจจัยสมดุลก่อนหน้าและการเปลี่ยนแปลงความสูง – ไม่จำเป็นต้องทราบความสูงสัมบูรณ์ สำหรับการเก็บข้อมูลสมดุล AVL สองบิตต่อโหนดก็เพียงพอแล้ว[ 7 ]

ความสูง(นับเป็นจำนวนระดับสูงสุด) ของต้นไม้ AVL ที่มีโหนดอยู่ในช่วง: [ 6 ] : 460

อัตราส่วนทองคำ   อยู่ที่ไหนและ นี่เป็นเพราะต้นไม้ AVL ที่มีความสูง ประกอบด้วย โหนดอย่างน้อย โดยที่ คือลำดับฟิโบนาชี่ที่มีค่าเริ่มต้น

การดำเนินงาน

การดำเนินการแบบอ่านอย่างเดียวของต้นไม้ AVL นั้นเกี่ยวข้องกับการกระทำเช่นเดียวกับที่ดำเนินการกับต้นไม้ค้นหาแบบไบนารี ที่ไม่สมดุล แต่การแก้ไขจะต้องคำนึงถึงและฟื้นฟูความสมดุลของความสูงของต้นไม้ย่อยด้วย

กำลังค้นหา

การค้นหาคีย์เฉพาะในต้นไม้ AVL สามารถทำได้ในลักษณะเดียวกับการค้นหาในต้นไม้ไบนารีแบบสมดุลหรือไม่สมดุลใดๆ[ 8 ] : บทที่ 8 เพื่อให้การค้นหามีประสิทธิภาพ จำเป็นต้องใช้ฟังก์ชันเปรียบเทียบซึ่งกำหนดลำดับทั้งหมด (หรืออย่างน้อยก็ลำดับก่อนหน้าทั้งหมด ) บนชุดของคีย์[ 9 ] : 23 จำนวนการเปรียบเทียบที่จำเป็นสำหรับการค้นหาที่สำเร็จนั้นถูกจำกัดด้วยความสูงhและสำหรับการค้นหาที่ไม่สำเร็จนั้นใกล้เคียงกับh มาก ดังนั้นทั้งสองจึงอยู่ในO(log n )โดยที่ n คือจำนวนโหนดในต้นไม้[ 10 ] : 216

การเดินทาง

เนื่องจาก AVL tree เป็นการทำงานแบบอ่านอย่างเดียว การท่องไปใน AVL tree จึงทำงานเหมือนกับการท่องไปใน Binary Tree อื่นๆ การสำรวจโหนดทั้งnโหนดของ Tree จะเยี่ยมชมแต่ละลิงก์สองครั้ง ครั้งแรกเป็นการเยี่ยมชมลงเพื่อเข้าสู่ซับทรีที่มีโหนดนั้นเป็นราก และครั้งที่สองเป็นการเยี่ยมชมขึ้นเพื่อออกจากซับทรีของโหนดนั้นหลังจากสำรวจเสร็จแล้ว

เมื่อพบโหนดในต้นไม้ AVL แล้วสามารถเข้าถึงโหนดถัดไปหรือ โหนด ก่อนหน้า ได้ใน เวลาคงที่โดยเฉลี่ย[ 11 ] : 58 ในบางกรณี การสำรวจโหนด "ใกล้เคียง" เหล่านี้ จำเป็นต้องเดินทางผ่านลิงก์มากถึงh ∝ log( n )ลิงก์ (โดยเฉพาะอย่างยิ่งเมื่อนำทางจากใบขวาสุดของซับทรีด้านซ้ายของรากไปยังราก หรือจากรากไปยังใบซ้ายสุดของซับทรีด้านขวาของราก ในต้นไม้ AVL ในรูปที่ 1 การนำทางจากโหนด P ไปยังโหนด Q ที่อยู่ถัดจากด้านขวา ต้องใช้ 3 ขั้นตอน) เนื่องจากมี ลิงก์ n −1ในต้นไม้ใดๆ ต้นทุนโดยเฉลี่ยคือ2×( n −1)/ nหรือประมาณ 2

แทรก

เมื่อแทรกโหนดลงในต้นไม้ AVL ขั้นตอนแรกจะเหมือนกับการแทรกโหนดลงในต้นไม้ค้นหาแบบไบนารีหากต้นไม้ว่างเปล่า โหนดจะถูกแทรกเป็นโหนดรากของต้นไม้ หากต้นไม้ไม่ว่างเปล่า เราจะลงไปตามโหนดราก และลงไปในต้นไม้แบบเรียกซ้ำเพื่อค้นหาตำแหน่งที่จะแทรกโหนดใหม่ การสำรวจนี้จะถูกชี้นำโดยฟังก์ชันเปรียบเทียบ ในกรณีนี้ โหนดจะแทนที่ค่าอ้างอิง NULL (ซ้ายหรือขวา) ของโหนดภายนอกในต้นไม้เสมอ กล่าวคือ โหนดนั้นจะเป็นโหนดลูกซ้ายหรือลูกขวาของโหนดภายนอก

หลังจากแทรกโหนดนี้แล้ว หากต้นไม้เกิดการไม่สมดุล เฉพาะบรรพบุรุษของโหนดที่แทรกใหม่เท่านั้นที่จะไม่สมดุล เนื่องจากมีเพียงโหนดเหล่านั้นเท่านั้นที่มีต้นไม้ย่อยเปลี่ยนแปลง[ 12 ]ดังนั้นจึงจำเป็นต้องตรวจสอบบรรพบุรุษของแต่ละโหนดว่าสอดคล้องกับค่าคงที่ของต้นไม้ AVL หรือไม่ ซึ่งเรียกว่า "การย้อนรอย" โดยทำได้โดยพิจารณาปัจจัยสมดุลของแต่ละโหนด[ 6 ] : 458–481 [ 11 ] : 108

เนื่องจากการแทรกเพียงครั้งเดียวทำให้ความสูงของซับทรี AVL ไม่สามารถเพิ่มขึ้นได้มากกว่าหนึ่ง ดังนั้นปัจจัยสมดุลชั่วคราวของโหนดหลังจากการแทรกจะอยู่ในช่วง[–2, +2]สำหรับแต่ละโหนดที่ตรวจสอบ หากปัจจัยสมดุลชั่วคราวยังคงอยู่ในช่วงตั้งแต่ –1 ถึง +1 ก็จำเป็นต้องอัปเดตปัจจัยสมดุลเท่านั้น ไม่จำเป็นต้องหมุน อย่างไรก็ตาม หากปัจจัยสมดุลชั่วคราวเป็น ±2 ซับทรีที่รากอยู่ที่โหนดนี้จะไม่สมดุล AVL และจำเป็นต้องมีการหมุน[ 9 ] : 52 ด้วยการแทรกดังที่โค้ดด้านล่างแสดง การหมุนที่เหมาะสม จะทำให้ ต้นไม้ สมดุลขึ้น อย่างสมบูรณ์แบบทันที

ในรูปที่ 1 เมื่อแทรกโหนดใหม่ Z เป็นโหนดลูกของโหนด X ความสูงของซับทรี Z จะเพิ่มขึ้นจาก 0 เป็น 1

ค่าคงที่ของลูปย้อนกลับสำหรับการแทรก

ความสูงของซับทรีที่รากเป็น Z เพิ่มขึ้น 1 แล้ว และมีรูปร่างแบบ AVL แล้ว

เพื่ออัปเดตค่าสมดุลของโหนดทั้งหมด ขั้นแรกให้สังเกตว่าโหนดทั้งหมดที่ต้องการการแก้ไขนั้นเรียงตัวจากโหนดลูกไปยังโหนดแม่ตามเส้นทางของใบที่แทรกเข้าไป หากใช้วิธีการข้างต้นกับโหนดตามเส้นทางนี้ โดยเริ่มจากใบ โหนดทุกโหนดในต้นไม้จะมีค่าสมดุลเป็น -1, 0 หรือ 1 อีกครั้ง

กระบวนการย้อนรอยสามารถหยุดได้หากค่าตัวประกอบสมดุลเป็น 0 ซึ่งหมายความว่าความสูงของซับทรีนั้นยังคงไม่เปลี่ยนแปลง

ถ้าค่าตัวประกอบสมดุลกลายเป็น ±1 ความสูงของซับทรีจะเพิ่มขึ้นหนึ่ง และจำเป็นต้องทำการย้อนรอยต่อไป

หากค่าตัวประกอบสมดุลกลายเป็น ±2 ชั่วคราว จะต้องทำการแก้ไขโดยการหมุนที่เหมาะสม หลังจากนั้นต้นไม้ย่อยจะมีระดับความสูงเท่าเดิม (และรากของต้นไม้ย่อยจะมีค่าตัวประกอบสมดุลเป็น 0)

เวลาที่ต้องการคือO(log n ) สำหรับการค้นหา บวกกับ ระดับการย้อนรอยสูงสุดO(log n ) (โดยเฉลี่ย O(1) ) ระหว่างทางกลับไปยังราก ดังนั้นการดำเนินการจึงสามารถเสร็จสิ้นได้ในเวลาO(log n ) [ 9 ] : 53

ลบ

ขั้นตอนเบื้องต้นสำหรับการลบโหนดนั้นเหมือนกับกรณีของต้นไม้ค้นหาแบบไบนารีกล่าวคือ การลบโหนดเป้าหมายหรือโหนดทดแทนจะทำให้ความสูงของต้นไม้ลูกที่เกี่ยวข้องลดลงจาก 1 เป็น 0 หรือจาก 2 เป็น 1 หากโหนดนั้นมีโหนดลูกอยู่

เริ่มต้นจากซับทรีนี้ จำเป็นต้องตรวจสอบความสอดคล้องของบรรพบุรุษแต่ละตัวกับค่าคงที่ของต้นไม้ AVL ซึ่งเรียกว่า "การย้อนรอย" (retracing)

เนื่องจากการลบเพียงครั้งเดียวจะทำให้ความสูงของซับทรี AVL ลดลงได้ไม่เกินหนึ่ง ดังนั้นค่าตัวประกอบสมดุลชั่วคราวของโหนดจะอยู่ในช่วงตั้งแต่ -2 ถึง +2 หากค่าตัวประกอบสมดุลยังคงอยู่ในช่วงตั้งแต่ -1 ถึง +1 ก็สามารถปรับให้สอดคล้องกับกฎ AVL ได้ หากค่าตัวประกอบสมดุลกลายเป็น ±2 แสดงว่าซับทรีไม่สมดุลและจำเป็นต้องหมุน (ต่างจากการแทรกที่การหมุนจะทำให้ต้นไม้สมดุลเสมอ หลังจากการลบ อาจมี BF(Z) ≠ 0 (ดูรูปที่ 2 และ 3) ดังนั้นหลังจากการหมุนครั้งเดียวหรือสองครั้งที่เหมาะสม ความสูงของซับทรีที่ปรับสมดุลแล้วจะลดลงหนึ่ง ซึ่งหมายความว่าต้นไม้จะต้องได้รับการปรับสมดุลอีกครั้งในระดับที่สูงขึ้นถัดไป) กรณีต่างๆ ของการหมุนจะอธิบายไว้ในส่วนการปรับสมดุล

ค่าคงที่ของลูปการย้อนรอยสำหรับการลบ

ความสูงของต้นไม้สาขาที่รากเป็น N ลดลง 1 หน่วย ขณะนี้อยู่ในรูปทรง AVL แล้ว

กระบวนการย้อนกลับจะหยุดลงได้หากค่าตัวประกอบสมดุลกลายเป็น ±1 (ซึ่งก่อนหน้านี้ต้องเป็น 0) หมายความว่าความสูงของซับทรีนั้นยังคงไม่เปลี่ยนแปลง

ถ้าค่าตัวประกอบสมดุลกลายเป็น 0 (ซึ่งต้องเป็น ±1) ความสูงของซับทรีจะลดลงหนึ่งระดับ และจำเป็นต้องทำการย้อนรอยต่อไป

หากค่าสมดุลชั่วคราวกลายเป็น ±2 จะต้องทำการแก้ไขโดยการหมุนที่เหมาะสม ความสูงของซับทรีจะลดลงหนึ่งระดับ –และต้องทำการย้อนรอยต่อไป– หรือไม่เปลี่ยนแปลง (หาก Z มีค่าสมดุลเป็น 0) และต้นไม้ทั้งหมดจะอยู่ในรูปทรง AVL นั้น ขึ้นอยู่กับค่าสมดุลของพี่น้อง Z (ต้นไม้ลูกที่อยู่สูงกว่าในรูปที่ 2)

เวลาที่ใช้ในการค้นหาคือO(log n )บวกกับการย้อนรอยสูงสุดO(log n )ระดับ ( โดยเฉลี่ย O(1) ) ระหว่างทางกลับไปยังราก ดังนั้นการดำเนินการจึงสามารถเสร็จสิ้นได้ในเวลา O(log n )

การดำเนินการตั้งค่าและการดำเนินการจำนวนมาก

นอกเหนือจากการดำเนินการแทรก ลบ และค้นหาองค์ประกอบเดี่ยวแล้ว ยังมีการกำหนดการดำเนินการเซตหลายอย่างบนต้นไม้ AVL ได้แก่ยูเนียนอินเตอร์เซกชันและผลต่างเซต จากนั้นจึงสามารถดำเนินการแทรกหรือลบ จำนวนมากได้อย่างรวดเร็วโดยอาศัยฟังก์ชันเซตเหล่านี้ การดำเนินการเซตเหล่านี้อาศัยการดำเนินการช่วยเหลือสองอย่างคือสปลิตและจอยน์ด้วยการดำเนินการใหม่เหล่านี้ การใช้งานต้นไม้ AVL จึงมีประสิทธิภาพมากขึ้นและสามารถขนานการทำงานได้สูง[ 13 ]

ฟังก์ชันJoinบนต้นไม้ AVL สองต้นt1 และ t2 และคีย์kจะส่งคืนต้นไม้ที่มีองค์ประกอบทั้งหมดในt1 , t2รวมถึงk ด้วย โดยมี เงื่อนไข ว่า kต้องมากกว่าคีย์ทั้งหมดในt1และน้อยกว่าคีย์ทั้งหมดในt2หากต้นไม้ทั้งสองแตกต่างกันที่ความสูงไม่เกินหนึ่ง ฟังก์ชัน Joinจะสร้างโหนดใหม่ที่มีซับทรีด้านซ้ายเป็นt1 , รากเป็นkและซับทรีด้านขวาเป็น t2 มิฉะนั้น สมมติว่าt1สูงกว่าt2 มากกว่า หนึ่งค่า (กรณีอื่นเป็นแบบสมมาตร) ฟังก์ชัน Joinจะตามแกนด้านขวาของt1 ไป จนถึงโหนดcซึ่งสมดุลกับt2ณ จุดนี้ โหนดใหม่ที่มีลูกด้านซ้ายเป็นc , รากเป็นkและลูกด้านขวาเป็นt2 จะถูกสร้างขึ้นเพื่อแทนที่ c โหนดใหม่นี้เป็นไปตามเงื่อนไขคงที่ของ AVL และความสูงของมันมากกว่าc หนึ่ง ค่า การเพิ่มความสูงอาจทำให้ความสูงของบรรพบุรุษเพิ่มขึ้น ซึ่งอาจทำให้ค่าคงที่ AVL ของโหนดเหล่านั้นไม่ถูกต้อง สามารถแก้ไขได้โดยการหมุนสองครั้งหากไม่ถูกต้องที่โหนดแม่ หรือหมุนซ้ายครั้งเดียวหากไม่ถูกต้องที่ระดับสูงกว่าในโครงสร้างต้นไม้ ในทั้งสองกรณีจะคืนค่าความสูงให้กับโหนดบรรพบุรุษถัดไป ดังนั้น ฟังก์ชัน Joinจะต้องใช้การหมุนอย่างมากที่สุดสองครั้ง ค่าใช้จ่ายของฟังก์ชันนี้คือผลต่างของความสูงระหว่างต้นไม้สองต้นที่ป้อนเข้ามา

ในการแบ่งต้นไม้ AVL ออกเป็นสองต้นไม้เล็กๆ คือ ต้นไม้ที่มีค่าน้อยกว่าคีย์kและต้นไม้ที่มีค่ามากกว่าคีย์kขั้นแรกให้ลากเส้นทางจากรากโดยการแทรกค่า kเข้าไปใน AVL หลังจากแทรกค่าแล้ว ค่าทั้งหมดที่น้อยกว่าkจะอยู่ทางด้านซ้ายของเส้นทาง และค่าทั้งหมดที่มากกว่าkจะอยู่ทางด้านขวา โดยการใช้Joinต้นไม้ย่อยทั้งหมดทางด้านซ้ายจะถูกรวมเข้าด้วยกันจากล่างขึ้นบนโดยใช้คีย์บนเส้นทางเป็นโหนดกลางจากล่างขึ้นบนเพื่อสร้างต้นไม้ด้านซ้าย ส่วนด้านขวาจะไม่สมมาตร ค่าใช้จ่ายในการแบ่งคือO(log n )ซึ่งเป็นลำดับของความสูงของต้นไม้

การรวมกันของต้นไม้ AVL สองต้นt 1 และ t 2 ซึ่งแทนเซตAและBคือ AVL tที่แทนAB

อัลกอริทึมสำหรับการหาจุดร่วมหรือความแตกต่างนั้นคล้ายกัน แต่ต้องใช้ รูทีนตัวช่วย Join2ซึ่งเหมือนกับJoinแต่ไม่มีคีย์ตรงกลาง โดยอาศัยฟังก์ชันใหม่สำหรับการรวม จุดร่วม หรือความแตกต่าง สามารถแทรกหรือลบคีย์เดียวหรือหลายคีย์ออกจากต้นไม้ AVL ได้ เนื่องจากSplitเรียกใช้ Joinแต่ไม่ได้จัดการกับเกณฑ์การปรับสมดุลของต้นไม้ AVL โดยตรง การใช้งานแบบนี้จึงมักเรียกว่าการใช้งานแบบ "อิงตาม Join "

ความซับซ้อนของการรวม การตัดกัน และความแตกต่างแต่ละรายการนั้นสำหรับต้นไม้ AVL ที่มีขนาดและที่สำคัญกว่านั้น เนื่องจากคำสั่งเรียกซ้ำสำหรับการรวม การตัดกัน หรือความแตกต่างเป็นอิสระต่อกัน จึงสามารถดำเนินการแบบขนานได้ด้วยความลึกแบบขนาน [ 13 ] เมื่อการใช้งานแบบรวมจะมี DAG การคำนวณแบบเดียวกันกับการแทรกและการลบองค์ประกอบเดียว

การปรับสมดุลใหม่

หากในระหว่างการดำเนินการแก้ไข ความแตกต่างของความสูงระหว่างซับทรีลูกสองอันเปลี่ยนแปลงไป ตราบใดที่ความแตกต่างนั้นน้อยกว่า 2 อาจสะท้อนให้เห็นได้จากการปรับข้อมูลสมดุลที่ซับทรีแม่ ในระหว่างการดำเนินการแทรกและลบ ความแตกต่างของความสูง (ชั่วคราว) 2 อาจเกิดขึ้น ซึ่งหมายความว่าซับทรีแม่จะต้อง "ปรับสมดุลใหม่" เครื่องมือซ่อมแซมที่ให้มานั้นเรียกว่าการหมุนต้นไม้เนื่องจากมันจะย้ายคีย์เฉพาะใน "แนวตั้ง" เท่านั้น ดังนั้นลำดับ (ในแนวนอน) ของคีย์จึงได้รับการรักษาไว้อย่างสมบูรณ์ (ซึ่งจำเป็นสำหรับต้นไม้ค้นหาแบบไบนารี) [ 6 ] : 458–481 [ 11 ] : 33

ให้ X เป็นโหนดที่มีปัจจัยสมดุล (ชั่วคราว) เท่ากับ −2 หรือ +2 โดยที่ซับทรีด้านซ้ายหรือด้านขวาของโหนดนี้ได้รับการแก้ไขแล้ว ให้ Z เป็นโหนดลูกที่มีซับทรีที่สูงกว่า (ดูรูปที่ 2 และ 3) โปรดสังเกตว่าโหนดลูกทั้งสองมีรูปร่างแบบ AVL ตามสมมติฐานการอุปมาน

ในกรณีของการเพิ่มจำนวน การเพิ่มจำนวนนี้เกิดขึ้นกับลูกคนใดคนหนึ่งของ Z ในลักษณะที่ทำให้ความสูงของ Z เพิ่มขึ้น ในกรณีของการลบออก การลบออกนี้เกิดขึ้นกับพี่น้อง t1 ของ Z ในลักษณะที่ทำให้ความสูงของ t1 ซึ่งต่ำอยู่แล้วลดลง (นี่เป็นกรณีเดียวที่ค่าสมดุลของ Z อาจเป็น 0 ได้)

การละเมิดดังกล่าวมีรูปแบบที่เป็นไปได้สี่แบบ:

ถูกต้อง ถูกต้อง⟹ Z คือสิทธิ์ลูกของพ่อแม่ X และ BF(Z) ≥ 0
ซ้าย ซ้าย⟹ Z คือด้านซ้ายลูกของพ่อแม่ X และ BF(Z) ≤ 0
ขวา ซ้าย⟹ Z คือสิทธิ์ลูกของพ่อแม่ X และ BF(Z) < 0
ซ้าย ขวา⟹ Z คือด้านซ้ายลูกของแม่ X และ BF(Z) > 0

และการปรับสมดุลจะดำเนินการแตกต่างออกไป:

ถูกต้อง ถูกต้อง⟹ X ได้รับการปรับสมดุลใหม่ด้วยเรียบง่ายการหมุนrotate_Left(ดูรูปที่ 2)
ซ้าย ซ้าย⟹ X ได้รับการปรับสมดุลใหม่ด้วยเรียบง่ายการหมุนrotate_Right(ภาพสะท้อนของรูปที่ 2)
ขวา ซ้าย⟹ X ได้รับการปรับสมดุลใหม่ด้วยสองเท่าการหมุนrotate_RightLeft(ดูรูปที่ 3)
ซ้าย ขวา⟹ X ได้รับการปรับสมดุลใหม่ด้วยสองเท่าการหมุนrotate_LeftRight(ภาพสะท้อนของรูปที่ 3)

ดังนั้น สถานการณ์ต่างๆ จึงถูกกำหนดให้เป็นCB โดยที่C (= ทิศทางของลูก) และB (= ความสมดุล) มาจากเซต{ ซ้าย , ขวา } โดยที่ขวา  := − ซ้ายการละเมิดความสมดุลในกรณีC == Bจะได้รับการแก้ไขโดยการหมุนแบบง่ายrotate_(− C )ในขณะที่กรณีC  != B จะได้รับ การแก้ไขโดยการหมุนสองครั้งrotate_CB

ค่าใช้จ่ายในการหมุน ไม่ว่าจะเป็นแบบธรรมดาหรือแบบสองรอบ ก็มีค่าคงที่

การหมุนแบบง่ายๆ

รูปที่ 2 แสดงสถานการณ์ Right Right ในครึ่งบน โหนด X มีต้นไม้ลูกสองต้นที่มีปัจจัยสมดุล+2ยิ่งไปกว่านั้น ต้นไม้ลูกภายใน t 23ของ Z (กล่าวคือ ต้นไม้ลูกซ้ายเมื่อ Z เป็นต้นไม้ลูกขวา หรือต้นไม้ลูกขวาเมื่อ Z เป็นต้นไม้ลูกซ้าย) จะไม่สูงกว่าต้นไม้พี่น้อง t 4ซึ่งอาจเกิดขึ้นได้จากการเพิ่มความสูงของต้นไม้ย่อย t 4หรือการลดความสูงของต้นไม้ย่อย t 1ในกรณีหลังนี้ สถานการณ์ที่ t 23มีความสูงเท่ากับ t 4 ก็ อาจเกิดขึ้น ได้เช่นกัน

ผลลัพธ์ของการหมุนไปทางซ้ายแสดงอยู่ในครึ่งล่างของรูปภาพ จะต้องปรับปรุงลิงก์สามลิงก์ (เส้นขอบหนาในรูปที่ 2) และปัจจัยสมดุลสองปัจจัย

ดังที่แสดงในรูป ก่อนการแทรก ชั้นใบจะอยู่ที่ระดับ h+1 ชั่วคราวอยู่ที่ระดับ h+2 และหลังจากการหมุนจะกลับมาอยู่ที่ระดับ h+1 อีกครั้ง ในกรณีที่มีการลบ ชั้นใบจะอยู่ที่ระดับ h+2 ซึ่งเป็นระดับเดียวกับที่ t 23และ t 4มีความสูงเท่ากัน มิฉะนั้น ชั้นใบจะอยู่ที่ระดับ h+1 ทำให้ความสูงของต้นไม้ที่หมุนลดลง

รูปที่ 2: การหมุนแบบง่ายrotate_Left ( X , Z )
ตัวอย่างโค้ดสำหรับการหมุนซ้ายแบบง่ายๆ
ป้อนข้อมูล:X = รากของซับทรีที่จะหมุนไปทางซ้าย
Z = ลูกทางขวาของ X, Z มีน้ำหนักไปทางขวา
    โดยที่ความสูงเท่ากับความสูงของต้นไม้ย่อยด้านซ้าย ( X ) + 2
ผลลัพธ์:รากใหม่ของซับทรีที่ปรับสมดุลใหม่
node * rotate_Left ( node * X , node * Z ) {// Z มีค่ามากกว่าค่าพี่น้องอยู่ 2t23 = left_child ( Z ); // ลูกภายในของ Zright_child ( X ) = t23 ;ถ้า( t23 != null )parent ( t23 ) = X ;left_child ( Z ) = X ;parent ( X ) = Z ;// กรณีที่ 1, BF(Z) == 0,// เกิดขึ้นเฉพาะกับการลบ ไม่ใช่การแทรก:ถ้า( BF ( Z ) == 0 ) { // t23 มีความสูงเท่ากับ t4BF ( X ) = + 1 ; // t23 ตอนนี้สูงขึ้นBF ( Z ) = 1 ; // t4 ตอนนี้ต่ำกว่า X} อื่น{ // กรณีที่ 2 เกิดขึ้นเมื่อมีการแทรกหรือลบข้อมูล:BF ( X ) = 0 ;BF ( Z ) = 0 ;}return Z ; // คืนค่ารากใหม่ของซับทรีที่หมุนแล้ว}

การหมุนสองรอบ

รูปที่ 3 แสดงสถานการณ์ซ้ายขวา ในส่วนบนสุด โหนด X มีต้นไม้ลูกสองต้นที่มีปัจจัยสมดุล+2แต่ต่างจากรูปที่ 2 ตรงที่ต้นไม้ลูกภายใน Y ของ Z สูงกว่าต้นไม้พี่น้อง t4 สิ่งนี้อาจเกิดขึ้นได้จากการแทรก Y เอง หรือการเพิ่มความสูงของต้นไม้ย่อย t2 หรือ t3 (ซึ่งส่งผลให้มีความสูงต่างกัน) หรือจากการลดความสูงของต้นไม้ย่อย t1 ในกรณีหลังนี้ อาจเกิดขึ้นได้เช่นกันว่า t2 และ t3 มีความสูงเท่ากัน

ผลลัพธ์ของการหมุนครั้งแรกทางขวาแสดงอยู่ในส่วนกลางของรูป (เมื่อพิจารณาจากปัจจัยสมดุล การหมุนนี้ไม่เหมือนกับการหมุนเดี่ยวของ AVL อื่นๆ เนื่องจากความแตกต่างของความสูงระหว่าง Y และ t 4มีเพียง 1 เท่านั้น) ผลลัพธ์ของการหมุนครั้งสุดท้ายทางซ้ายแสดงอยู่ในส่วนล่างของรูป ต้องมีการปรับปรุงลิงก์ห้าลิงก์ (ขอบหนาในรูปที่ 3) และปัจจัยสมดุลสามตัว

ดังที่แสดงในภาพ ก่อนการแทรก ชั้นใบจะอยู่ที่ระดับ h+1 ชั่วคราวอยู่ที่ระดับ h+2 และหลังจากการหมุนสองรอบจะกลับมาอยู่ที่ระดับ h+1 อีกครั้ง ในกรณีของการลบ ชั้นใบจะอยู่ที่ระดับ h+2 และหลังจากการหมุนสองรอบจะอยู่ที่ระดับ h+1 ดังนั้นความสูงของต้นไม้ที่หมุนแล้วจึงลดลง

รูปที่ 3: การหมุนสองรอบrotate_RightLeft ( X , Z ) = หมุนขวาไปรอบแกน Zตามด้วยการหมุนซ้ายไปรอบ แกน X
ตัวอย่างโค้ดสำหรับการหมุนสองทิศทางจากขวาไปซ้าย
ป้อนข้อมูล:X = รากของซับทรีที่จะถูกหมุน
Z = ลูกทางขวา หนักทางซ้าย
    โดยที่ความสูงเท่ากับความสูงของต้นไม้ย่อยด้านซ้าย ( X ) + 2
ผลลัพธ์:รากใหม่ของซับทรีที่ปรับสมดุลใหม่
node * rotate_RightLeft ( node * X , node * Z ) {// Z มีค่ามากกว่าค่าพี่น้องอยู่ 2Y = left_child ( Z ); // ลูกภายในของ Z// Y สูงกว่าพี่น้อง 1t3 = right_child ( Y );left_child ( Z ) = t3 ;ถ้า( t3 != null )parent ( t3 ) = Z ;right_child ( Y ) = Z ;parent ( Z ) = Y ;t2 = left_child ( Y );right_child ( X ) = t2 ;ถ้า( t2 != null )parent ( t2 ) = X ;left_child ( Y ) = X ;parent ( X ) = Y ;// กรณีที่ 1, BF(Y) == 0ถ้า( BF ( Y ) == 0 ) {BF ( X ) = 0 ;BF ( Z ) = 0 ;} else if ( BF ( Y ) > 0 ) {// t3 สูงกว่าBF ( X ) = 1 ; // t1 ตอนนี้สูงขึ้นBF ( Z ) = 0 ;} อื่น{// t2 สูงกว่าBF ( X ) = 0 ;BF ( Z ) = + 1 ; // t4 ตอนนี้สูงขึ้น}BF ( Y ) = 0 ;return Y ; // คืนค่ารากใหม่ของซับทรีที่หมุนแล้ว}

เมื่อเปรียบเทียบกับโครงสร้างอื่นๆ

ทั้งต้นไม้ AVL และต้นไม้แดง-ดำ (RB) เป็นต้นไม้ค้นหาไบนารีแบบปรับสมดุลตัวเอง และมีความสัมพันธ์กันทางคณิตศาสตร์ อันที่จริง ต้นไม้ AVL ทุกต้นสามารถระบายสีเป็นแดง-ดำได้[ 14 ]แต่มีต้นไม้ RB บางต้นที่ไม่สมดุลแบบ AVL การหมุนมีบทบาทสำคัญในการรักษาสภาพคงที่ของต้นไม้ AVL (หรือ RB) ในกรณีที่เลวร้ายที่สุด แม้ไม่มีการหมุน การแทรกหรือการลบ AVL หรือ RB ต้องใช้ การตรวจสอบ O(log n )และ/หรือการอัปเดตปัจจัยสมดุล AVL (หรือสี RB) การแทรกและการลบ RB และการแทรก AVL ต้องใช้การหมุนแบบเรียกซ้ำหาง ตั้งแต่ศูนย์ถึงสามครั้ง และทำงานในเวลาเฉลี่ยO(1) [ 15 ] : หน้า 165, 158 [ 16 ]ดังนั้นจึงคงที่เท่ากันโดยเฉลี่ย การลบ AVL ที่ต้องใช้ การหมุน O(log n )ในกรณีที่เลวร้ายที่สุดก็ ใช้ เวลาเฉลี่ยO(1) เช่นกัน โครงสร้างข้อมูลแบบ RB tree จำเป็นต้องจัดเก็บข้อมูลหนึ่งบิต (สี) ในแต่ละโหนด ในขณะที่โครงสร้างข้อมูลแบบ AVL tree ส่วนใหญ่ใช้สองบิตสำหรับค่าสมดุล แม้ว่าเมื่อจัดเก็บไว้ที่โหนดลูกแล้ว บิตเดียวที่มีความหมายว่า "ต่ำกว่าโหนดพี่น้อง" ก็เพียงพอแล้ว ความแตกต่างที่สำคัญกว่าระหว่างโครงสร้างข้อมูลทั้งสองคือขีดจำกัดความสูงของมัน

สำหรับต้นไม้ที่มีขนาดn ≥ 1

  • ความสูงของต้นไม้ AVL นั้นสูงสุดไม่เกิน
โดยที่  อัตราส่วนทองคำและ​   
  • ความสูงของต้นไม้ RB นั้นสูงสุดไม่เกิน
     [ 17 ]

ต้นไม้ AVL มีความสมดุลที่เข้มงวดกว่าต้นไม้ RB โดยมี ความสัมพันธ์ เชิงเส้นกำกับ AVL/RB ≈0.720 ของความสูงสูงสุด สำหรับการแทรกและการลบ Ben Pfaff แสดงให้เห็นในการวัด 79 ครั้งว่ามีความสัมพันธ์ของ AVL/RB ระหว่าง 0.677 และ 1.077 โดยมีค่ามัธยฐาน ≈0.947 และค่าเฉลี่ยเรขาคณิต ≈0.910 [ 4 ]

ดูเพิ่มเติม

อ่านเพิ่มเติม

ดึงข้อมูลมาจาก " https://en.wikipedia.org/w/index.php?title=AVL_tree&oldid=1340699903 "

สรุปเนื้อหา

ข้อมูลสำคัญจากบทความ

ข้อมูลสำคัญเกี่ยวกับ ต้นไม้ AVL

ใน วิทยาการคอมพิวเตอร์ ต้นไม้ AVL (ตั้งชื่อตามผู้คิดค้นคือ Adelson - Velsky และ Landis ) คือ ต้นไม้ค้นหาแบบไบนารีที่ปรับสมดุลได้เอง ในต้นไม้ AVL ความสูงของ ต้นไม้ย่อย ลูก สอง...

ปัจจัยสมดุล

ใน ต้นไม้ไบนารี ปัจจัย สมดุล ของโหนด X ถูกกำหนดให้เป็นผลต่างความสูง

คุณสมบัติ

ปัจจัยสมดุลสามารถอัปเดตได้โดยการทราบปัจจัยสมดุลก่อนหน้าและการเปลี่ยนแปลงความสูง – ไม่จำเป็นต้องทราบความสูงสัมบูรณ์ สำหรับการเก็บข้อมูลสมดุล AVL สองบิตต่อโหนดก็เพียงพอแล้ว [ 7 ]

การดำเนินงาน

การดำเนินการแบบอ่านอย่างเดียวของต้นไม้ AVL นั้นเกี่ยวข้องกับการกระทำเช่นเดียวกับที่ดำเนินการกับ ต้นไม้ค้นหาแบบไบนารี ที่ไม่สมดุล แต่การแก้ไขจะต้องคำนึงถึงและฟื้นฟูความสมดุลของความสูงของต้นไม้ย่อยด้วย