การหมุนต้นไม้ เพื่อให้คงสภาพ Balance Tree (AVL Tree)

การหมุนเพื่อคงสภาพ AVL Tree

สมมุติต้นไม้ Binary Search Tree ขึ้นมา 1 ต้น ที่อยู่ในสภาพ balance และสมมุติโหนด p เป็นโหนดที่อาจจะต้องถูก rebalance เนื่องมีโหนดใหม่ถูกเพิ่มเข้ามาเป็นลูกของ subtree ด้านซ้าย หรือ subtree ด้านขวา
เช่น ถ้าสมมุติ Binary Search Tree ไว้ดังภาพนี้

เราจะต้องทำการ rebalance ก็ต่อเมื่อ Height ด้านซ้ายของ p แตกต่างจาก Height ด้านขวาของ p มากกว่า 2 เช่นแบบนี้

แต่ถ้าความสูง (height) แตกต่างกันน้อยกว่า 2 (เช่น 0 หรือ 1) เราจะไม่ต้องทำการ rebalance

เพราะฉะนั้นกรณีที่จะทำให้เราต้อง rebalance โหนด p มีอยู่ 4 กรณีคือ
กรณี 1 เพิ่มโหนดใหม่เข้าไปที่ subtree ด้านซ้าย ของโหนดลูกด้านซ้ายของ p (สมมุติ n เป็นโหนดใหม่)

กรณี 2 เพิ่มโหนดใหม่เข้าไปที่ subtree ด้านขวา ของโหนดลูกด้านซ้ายของ p

กรณี 3 เพิ่มโหนดใหม่เข้าไปที่ subtree ด้านซ้ายของโหนดลูกด้านขวาของ p

กรณี 4 เพิ่มโหนดใหม่เข้าไปที่ subtree ด้านขวาของโหนดลูกด้านขวาของ p

ทั้ง 4 กรณีนี้อาจจะทำให้ length ด้านซ้ายมีความยาวต่างกับ length ด้านขวาเท่ากับ 2 ก็ได้ แต่กรณีที่ 1 กับ 4 เราเรียกว่าเป็น outside เพราะอยู่ขอบนอก แบบ outside นี้จะ rebalance โดยวิธี single-rotation ส่วนกรณีที่ 2 กับ 3 เราเรียกว่าเป็น inside เพราะอยู่ด้านใน (ตามภาพ) แบบ inside นี้จะ rebalance โดยวิธี double-rotation

1. single-rotation

1.1 การหมุนขวาครั้งเดียว (single right rotation)

การหมุนครั้งเดียว แบบหมุนขวา (right rotate) ทำได้ดังนี้ สมมุติมีสภาพเริ่มต้นอยู่แบบนี้




และ a เป็นโหนดแม่ ที่มี length ด้านซ้ายยาวกว่า length ด้านขวาเท่ากับ 2 (a ไม่จำเป็นต้องเป็น root เสมอไป แต่อยู่ในเส้นทางจาก c ขึ้นไปที่ root) ส่วนโหนด c คือโหนดที่เพิ่มเข้ามาใหม่ ทำตามขั้นตอนต่อไปนี้
A.       เอา b ไปแทนที่ a แขนซ้าย a จะว่าง
B.       ยกลูกด้านขวาของ b ให้แขนซ้าย a ถือไว้ แขนขวา a จะว่าง
C.      เอาแขนขวา b ที่ว่างอยู่จับหัว a เอาไว้
ทั้ง 3 ขั้นตอนสามารถแสดงเป็นรูปภาพได้ดังนี้

A. เอา b ไปแทนที่ a แขนซ้าย a จะว่าง



B. ยกลูกด้านขวาของ b ให้แขนซ้าย a ไปถือไว้



C. เอาแขนขวา b ที่ว่างอยู่จับหัว a ไว้


ตัวอย่างการหมุนขวา เช่น


จากภาพเมื่อนำโหนดใหม่เพิ่มเข้าไป เช่นโหนดมีค่าเป็น 1 เพิ่มเข้าไปดังนี้

เมื่อไล่ length เปรียบเทียบกันระหว่างด้านซ้าย และด้านขวา ขึ้นมาตั้งแต่โหนด 1 ไล่ขึ้นมาเรื่อยๆตามทางพุ่งขึ้นสู่ root จะมาหยุดที่โหนด 10 เพราะ legnth ด้านซ้ายยาว 3 และ length ด้านขวายาว 1 ซึ่งแตกต่างกันเป็น 2 แสดงว่าจุดหมุน (Pivot Node) อยู่ที่โหนด 10 เราจะใช้วิธีการหมุนขวา โดยยึดหลัก A. B. C. ตามขั้นตอนที่กล่าวไว้ข้างต้น แสดงได้ด้วยภาพดังนี้

หรือเขียนแบบสั้นๆ จะได้ภาพโหนดหลังจากหมุนขวาเสร็จแล้วดังนี้

จะเห็นว่าเมื่อหมุนแล้วจะไม่มีโหนดไหนที่ length ด้านซ้าย แตกต่างจาก length ด้านขวาเกิน 1 ซึ่งยังคงความเป็น AVL Tree ไว้ได้

1.2 การหมุนซ้าย (single left rotation)

การหมุนครั้งเดียว (single-rotation) แบบหมุนซ้ายจะเกิดกับกรณีที่ 4 แบบ outside โดยใช้หลักการเดียวกันกับการหมุนขวา

ขั้นตอนการหมุนซ้ายคือ
A. เอา b ไปแทนที่ a แขนขวา a จะว่าง
B. เอาลูกด้านซ้ายของ b ยกให้แขนขวา a ไปถือไว้ แขนซ้าย b จะว่าง
C. เอาแขนซ้าย b ที่ว่างอยู่ไปจับหัว a ไว้
สามารถอธิบายเป็นรูปภาพได้ดังนี้

ตัวอย่างเช่นสมมุติว่าเรามีต้นไม้ที่มีโหนดเรียงกันมาแบบนี้

และเราจะเพิ่มโหนดใหม่เข้าไปมีค่าเป็น 20

ลองไล่ระดับจากโหนดที่เพิ่มเข้าไป ขึ้นไปหา root จะพบว่าโหนดที่มี length ด้านซ้ายต่างจาก length ด้านขวาเป็น 2 คือ โหนด 16 เพราะฉะนั้น Pivot Point คือโหนด 16 และทำให้เราหมุนซ้ายได้แบบนี้

2. double rotation
การหมุน 2 ครั้งจะทำกับการเพิ่มโหนดแบบ inside ที่ลักษณะ left-right หรือ right-left จากโหนดที่เป็น Pivot Point เท่านั้น เช่น แบบนี้

จะเห็นว่าเมื่อเพิ่มโหนด 18 เข้าไปจะทำให้ไม่เป็นต้นไม้ AVL เพราะหนักมาด้านขวามากเกินไป และเมื่อไรความยาวจากโหนด 18 ขึ้นไปถึงโหนด 10 จะพบว่ามีความแตกต่างระหว่าง length ด้านซ้ายกับ length ด้านขวาเป็น 2 ดังนั้นจุดหมุนคือ 10

เป้าหมายก็คือเราจะต้องเอา b ไปแทนที่ a คือเอาโหนด 16 ไปแทนที่ตรงที่โหนด 10 อยู่ให้ได้ ซึ่งจะต้องทำให้เราต้องหมุน 2 ครั้งคือ ครั้งแรกหมุน 16 มาด้านขวา และครั้งที่ 2 หมุน 16 ไปด้านซ้าย เราจะใช้กฏการหมุนแบบ single rotation ตามที่เรียนมาข้างต้น มาหมุนโหนด 16 ให้ขึ้นไปอยู่ที่ตรงตำแหน่งโหนด 10 ให้ได้ตามภาพนี้

และเมื่อหมุนขวาอีกครั้งที่ b เพื่อให้โหนด 16 ไปแทนที่ตำแหน่งของโหนด 10 จะได้ภาพดังนี้

จะเห็นวิธีการ double rotation แบบ ขวา-ซ้าย คือ หมุนขวาก่อน แล้วค่อยมา หมุนซ้าย อีกแบบหนึ่งคือแบบ ซ้าย-ขวา คือหมุนซ้ายก่อนแล้วค่อยมา หมุนขวา สมมุติว่าเรามีข้อมูลอยู่ตามภาพสุดท้ายด้านบน และมีโหนดใหม่ถูกเพิ่มเข้ามาคือโหนด 9 ดังนี้

เมื่อไล่ระดับขึ้นไปตามเส้นทางจากโหนด 9 จนถึงโหนด root จะพบว่าโหนด 10 คือโหนดที่มี length ด้านซ้ายต่างกับ length ด้านขวาเป็น 2 ทำให้เรารู้ว่าโหนด 10 เป็น Pivot Point และถ้าเริ่มหมุนครั้งแรกเราจะหมุนโหนด 9 ไปด้านซ้ายก่อนตามภาพดังนี้

เราจะหมุนขวาอีกครั้งเพื่อให้ 9 ไปแทนที่ตำแหน่งของโหนด 10 ให้ได้ดังนี้

ตัวอย่างการหมุนแบบทีละขั้น

สมมุติว่าเราค่อยๆเพิ่มโหนด 1 2 3 4 5 6 7 8 9 และ 10 เข้าไปในต้นไม้จะทำให้เกิดการหมุนไล่กันมาแบบนี้

และเมื่อนำ 4 5 6 ใส่เข้าไปอีกจะได้ตามภาพนี้

เมื่อเติมโหนด 7 8 9 เข้าไปจะได้ภาพดังนี้


ถ้าลองเพิ่ม 16 15 14 เข้ามาจะได้ตามภาพนี้





และเมื่อเอาโหนด 14 ใส่เข้าไปจะต้องหมุนแบบนี้



ความคิดเห็น

โพสต์ยอดนิยมจากบล็อกนี้

การจัดเรียงแบบ Quick Sort

กราฟอัลกอริธึม

Huffman's Code