Transcript ***** 5
6 תרגול
AVL Trees
AVL עצי
• Height- Balance Property
– For every internal node v of a tree T, the height of the
children nodes of v differ by at most 1.
• AVL Tree
– Any binary search tree that satisfies the HeightBalance property.
• AVL Interface
– The AVL interface supports the following operations in
O(log n):
• insert, search, delete, maximum, minimum, predecessor and
successor.
• AVL Height
– Lemma: The height of an AVL tree storing n keys is
O(logn)
AVL עצי
:AVL • דוגמא של עץ
44
h=4
h=2
h=3
17
78
h=1
h=2
h=1
32
88
50
h=1
48
h=1
62
איזון בעץ AVL
• כאשר תכונת איזון הגובה מופרת בהכנסה\הוצאה
של קודקוד (נוצר קודקוד שהפרש הגבהים בין שני
בניו הוא ,)2צריך לאזן את העץ.
• האיזון נעשה בקודקוד הנמוך ביותר בו מופר האיזון
• סיבוב יחיד:
– כאשר חוסר האיזון
או
מצורת
איזון בעץ AVL
• כאשר תכונת איזון הגובה מופרת בהכנסה\הוצאה
של קודקוד (נוצר קודקוד שהפרש הגבהים בין שני
בניו הוא ,)2צריך לאזן את העץ.
• האיזון נעשה בקודקוד הנמוך ביותר בו מופר האיזון
• סיבוב יחיד:
• סיבוב כפול:
– כאשר חוסר האיזון
או
מצורת
הדגמה:
10
15
h=11
h=10
h=10
– כאשר חוסר האיזון
או
מצורת
– את הסיבוב הראשון
נבצע מתחת לקודקוד
הלא מאוזן ,כדי להביא
לחוסר איזון מצורת \
שאלה 2
• הכניסו את האיברים הבאים לפי הסדר לעץ ( AVLהעץ
ריק בהתחלה)19 ,18 ,16 ,30 ,25 ,15 ,20 ,10 :
חוסר איזון מצורת
– סיבוב כפול
10
20
15
קודקוד
לא מאוזן
שאלה 2
• הכניסו את האיברים הבאים לפי הסדר לעץ ( AVLהעץ
ריק בהתחלה)19 ,18 ,16 ,30 ,25 ,15 ,20 ,10 :
חוסר איזון מצורת
– סיבוב כפול
קודקוד
לא מאוזן
10
15
20
שאלה 2
• הכניסו את האיברים הבאים לפי הסדר לעץ ( AVLהעץ
ריק בהתחלה)19 ,18 ,16 ,30 ,25 ,15 ,20 ,10 :
15
20
25
30
10
שאלה 2
• הכניסו את האיברים הבאים לפי הסדר לעץ ( AVLהעץ
ריק בהתחלה)19 ,18 ,16 ,30 ,25 ,15 ,20 ,10 :
חוסר איזון מצורת
– סיבוב יחיד
קודקוד
לא מאוזן
25
30
15
20
קודקוד
לא מאוזן
10
שאלה 2
• הכניסו את האיברים הבאים לפי הסדר לעץ ( AVLהעץ
ריק בהתחלה)19 ,18 ,16 ,30 ,25 ,15 ,20 ,10 :
חוסר איזון מצורת
קודקוד
לא מאוזן
– סיבוב כפול
15
25
30
10
20
16
שאלה 2
• הכניסו את האיברים הבאים לפי הסדר לעץ ( AVLהעץ
ריק בהתחלה)19 ,18 ,16 ,30 ,25 ,15 ,20 ,10 :
חוסר איזון מצורת
– סיבוב כפול
15
20
25
30
10
16
שאלה 2
• הכניסו את האיברים הבאים לפי הסדר לעץ ( AVLהעץ
ריק בהתחלה)19 ,18 ,16 ,30 ,25 ,15 ,20 ,10 :
חוסר איזון מצורת
– סיבוב יחיד
קודקוד לא
מאוזן
20
15
25
30
קודקוד לא
מאוזן
16
18
19
קודקוד לא
מאוזן
10
שאלה 2
• הכניסו את האיברים הבאים לפי הסדר לעץ ( AVLהעץ
ריק בהתחלה)19 ,18 ,16 ,30 ,25 ,15 ,20 ,10 :
20
15
25
30
10
18
19
16
שאלה 2
• כעת הסירו את האיבר 30
חוסר איזון מצורת
– סיבוב כפול
קודקוד לא
מאוזן
20
15
25
30
10
18
19
16
שאלה 2
• כעת הסירו את האיבר 30
18
15
20
25
19
16
10
שאלה 1
• קודקוד בעץ בינארי Tנקרא בן יחיד אם יש לו קודקוד
הורה ואין לו קודקוד אח (השורש אינו בן יחיד)
• יחס הבדידות של עץ Tמוגדר כמספר הבנים היחידים
בעץ חלקי מספר כל הקודקודים בעץ
LR(T) = (The number of nodes in T that are only children) /
)(The number of nodes in T
1
2
.aהוכיחו כי בכל עץ T AVLמתקיים ≤ 𝑇 𝑅𝐿
שאלה 1
1
2
.aהוכיחו כי בכל עץ T AVLמתקיים ≤ 𝑇 𝑅𝐿
פתרון:
אם קודקוד בעץ AVLהוא בן יחיד ,אז הוא עלה (למה?)
לכל בן יחיד יש קודקוד אבא ,ולשני בנים יחידים שונים יש
אבות שונים (למה?)
מספר הבנים היחידים +האבות שלהם = * 2מספר הבנים
היחידים (למה?)
סה"כ מספר הקודקודים בעץ ≤ מספר הבנים היחידים +
האבות שלהם = * 2מספר הבנים היחידים
1
2
לכן ≤ 𝑇 𝑅𝐿
שאלה 1
• קודקוד בעץ בינארי Tנקרא בן יחיד אם יש לו קודקוד
הורה ואין לו קודקוד אח (השורש אינו בן יחיד)
• יחס הבדידות של עץ Tמוגדר כמספר הבנים היחידים
בעץ חלקי מספר כל הקודקודים בעץ
– LR(T) = (The number of nodes in T that are only children) /
)(The number of nodes in T
.aהוכיחו כי
1
בכל עץ T AVLמתקיים ≤
2
1
שלכל עץ בינארי ,Tאם ≤
2
.bהאם נכון
)?Height(T)=O(log n
𝑇 𝑅𝐿
𝑇 𝑅𝐿 אז
שאלה 1
.bהאם נכון שלכל עץ בינארי ,Tאם
)?Height(T)=O(log n
1
2
≤ 𝑇 𝑅𝐿 אז
פתרון :זה לא נכון .זה רק אומר שיש לכל היותר
𝑛
2
דוגמאות נגדיות:
𝑛
2
קודקודים
…
עץ מלא
בגודל
𝑛
2
…
בנים יחידים.
שאלה 1
• קודקוד בעץ בינארי Tנקרא בן יחיד אם יש לו קודקוד
הורה ואין לו קודקוד אח (השורש אינו בן יחיד)
• יחס הבדידות של עץ Tמוגדר כמספר הבנים היחידים
בעץ חלקי מספר כל הקודקודים בעץ
– LR(T) = (The number of nodes in T that are only children) /
)(The number of nodes in T
.aהוכיחו כי
1
בכל עץ T AVLמתקיים ≤
2
1
שלכל עץ בינארי ,Tאם ≤
2
𝑇 𝑅𝐿
𝑇 𝑅𝐿 אז
.bהאם נכון
)?Height(T)=O(log n
.cהאם נכון שבכל עץ בינארי ,Tאם יש 𝑛 𝜃 בנים יחידים,
שכולם עלים ,אז )?Height(T)=O(log n
שאלה 1
.cהאם נכון שבכל עץ בינארי ,Tאם יש 𝑛 𝜃 בנים יחידים,
שכולם עלים ,אז )?Height(T)=O(log n
פתרון :זה לא נכון.
דוגמה נגדית:
שאלה 3
• במימוש ל AVLשלמדתם בכיתה ,לכל קודקוד שדה
נוסף ,hששומר את גובה הקודקוד .בגובה
משתמשים בכדי לאזן את העץ.
• מכיוון שגובה הקודקוד יכול להיות עד ),log(n
דרושים )) log(log(nביטים בכל קודקוד לשמירת
שדה הגובה.
.1כיצד ניתן להקטין את מספר הביטים שעל כל
קודקוד לשמור?
שאלה 3
.1כיצד ניתן להקטין את מספר הביטים שעל כל קודקוד
לשמור?
פתרון:
במקום לשמור את הגובה ,כל קודקוד ישמור רק את
מצב האיזון שלו – אם תת-העץ השמאלי\ימני גבוה יותר
או אם הוא מאוזן
)– 00 ≡ ’/’ – h(x.left) > h(x.right
)– 01 ≡ ’–‘ – h(x.left) = h(x.right
)– 10 ≡ ’\’ - h(x.left) < h(x.right
כיצד נדע מתי ואיפה יש לבצע סיבוב\סיבוב כפול
בהכנסה בהצגה הנ"ל?
שאלה 3
• הדגמה:
בצעו הכנסה של האיבר .40כיצד ישתנו הסמנים?
כיצד מזהים היכן יש לבצע סיבוב?
\
44
\
/
17
78
==
==
88
32
50
==
48
==
97
==
81
62
72
60
49
47
37
16
20
שאלה 3
• במימוש ל AVLשלמדתם בכיתה ,לכל קודקוד שדה
נוסף ,hששומר את גובה הקודקוד .בגובה
משתמשים בכדי לאזן את העץ.
• מכיוון שגובה הקודקוד יכול להיות עד ),log(n
דרושים )) log(log(nביטים בכל קודקוד לשמירת
שדה הגובה.
.1כיצד ניתן להקטין את מספר הביטים שעל כל
קודקוד לשמור?
.2הציעו דרך למציאת גובה העץ במימוש שהוצע
ב?1
שאלה 3
.2הציעו דרך למציאת גובה העץ במימוש שהוצע
ב?1
פתרון:
גובה העץ = העומק המקסימלי של עלה בעץ
נרד לעלה העמוק ביותר ,ע"י כך שבכל התפצלות
נבחר את הצד הגבוה יותר
מה יקרה אם נוריד את
התנאי הזה?
שאלה 4
• הליכה לפי שלבים מוגדרת כביקור בקודקודים בעץ
כך שמבקרים קודם בקודקודים עם עומק נמוך
יותר (ובאותו עומק מבקרים משמאל לימין).
.1מהו הסדר של ההליכה לפי שלבים בעץ הבא:
שאלה 4
.1מהו הסדר של ההליכה לפי שלבים בעץ הבא:
Answer:
FBHADGJCEI
שאלה 4
• הליכה לפי שלבים מוגדרת כביקור בקודקודים בעץ
כך שמבקרים קודם בקודקודים עם עומק נמוך
יותר (ובאותו עומק מבקרים משמאל לימין).
.1מהו הסדר של ההליכה לפי שלבים בעץ הבא:
.2הציעו אלגוריתם לביצוע הליכה לפי שלבים בעץ
בינארי נתון .T
שאלה 4
.2הציעו אלגוריתם לביצוע הליכה לפי שלבים בעץ
בינארי נתון .T
פתרון:
• נשתמש בתור ( )Queueשל קודקודים:
– כל עוד המחסנית אינה ריקה ,נוציא את הקודקוד הראשון
בתור ,נדפיס אותו ונכניס את בניו לתור.
– נתחיל עם תור שמכיל רק את השורש
)PrintLevelOrder(AVL T
)if (T.root ≠ null) Q.enqueue(T.root
))(while(!Q.isEmpty
)(n ← Q.dequque
מה יקרה אם נעביר
)print(n.val
שורה זו לסוף?
)if (T.left ≠ null) Q.enquque(n.left
מה יקרה אם נחליף
בין 2השורות הללו?
)if (T.right ≠ null) Q.enquque(n.right
שאלה 4
• הליכה לפי שלבים מוגדרת כביקור בקודקודים בעץ
כך שמבקרים קודם בקודקודים עם עומק נמוך
יותר (ובאותו עומק מבקרים משמאל לימין).
.1מהו הסדר של ההליכה לפי שלבים בעץ הבא:
.2הציעו אלגוריתם לביצוע הליכה לפי שלבים בעץ
בינארי נתון .T
.3האם ניתן לבנות כל עץ AVLחוקי ע"י פעולות BST
של הכנסה ומחיקה של ערכים (ללא סיבובים) ,כך
שלאחר כל הכנסה\מחיקה העץ יישאר מאוזן?
שאלה 4
.1האם ניתן לבנות כל עץ AVLחוקי ע"י פעולות BST
של הכנסה ומחיקה של ערכים (ללא סיבובים) ,כך
שלאחר כל הכנסה\מחיקה העץ יישאר מאוזן?
פתרון :כן ,נכניס את האיברים לפי סדר הרמות שלהם.
5 שאלה
• הציעו מבנה נתונים שתומך בפעולות הבאות בזמנים
. הסבירו כיצד ממשים את הפעולות.הנתונים
Init()
Insert(x)
Delete(x)
Delete_in_place(i)
Get_place(x)
Initialize the ADT
Insert x into the ADT, if it is not in ADT yet
Delete x from the ADT, if exists
Delete from the ADT an element, which is in the ith
place (as determined by the order of insertion) among
the elements that are in the ADT at that moment.
Return the place (which is determined by the order of
insertion) of x among the elements that are in the ADT
at that moment. If x does not exist, return -1.
O(1)
O(log n)
O(log n)
O(log n)
O(log n)
For example, for the following sequence of actions:
Insert(3), Insert(5), Insert(11), Insert(4), Insert(7), Delete(5)
Get_place(7) returns 4, and Delete_in_place(2) will delete 11 from the tree.
שאלה 5
• הציעו מבנה נתונים שתומך בפעולות הבאות בזמנים
הנתונים .הסבירו כיצד ממשים את הפעולות.
פתרון :נשמור 2עצי ,AVLאחד ממוין לפי מפתח ,ואחד
ממוין לפי זמן הכנסה.
לכל קודקוד יהיה מצביע לקודקוד המקביל בעץ השני.
בנוסף ,כל קודקוד בעץ ( T2הממוין לפי זמן הכנסה) יכיל
שדה של גודל תת-העץ המושרש בו.
)Example: Delete(5
)Insert(3), Insert(5), Insert(11), Insert(4), Insert(7
5 שאלה
Init() –
• הציעו מבנה נתונים שתומך בפעולות הבאות בזמנים
. הסבירו כיצד ממשים את הפעולות.הנתונים
ואחד, אחד ממוין לפי מפתח,AVL עצי2 נשמור:פתרון
.ממוין לפי זמן הכנסה
.לכל קודקוד יהיה מצביע לקודקוד המקביל בעץ השני
(הממוין לפי זמן הכנסה) יכילT2 כל קודקוד בעץ,בנוסף
.העץ המושרש בו-שדה של גודל תת
initialize 2 empty trees
אילו שינויים ניתן לבצע על מנת להשתמש
סטנדרטי? (ממיין לפי שדה כלשהוAVL בעץ
Insert(x) – insert an element by key into T1,
)בקודקוד
insert the element as the biggest to T2, and update the pointers.
In T2 update the field x.size in the insertion path. (The insertion is
as in an AVL tree)
Delete(x) – find the element in T1 (regular search), and delete it from both the
trees.
In T2, go up from the deleted element to the root and update x.size
for all the nodes in this path. (The deletion is as in an AVL tree)
5 שאלה
Delete_by_place(i) – find the ith element in T2 in the following way:
x ← T2.root
if (x.size<i) return //less than i elements, do nothing
while(x!=null) {
if x.left = null
z←0
else
z ← x.left.size
if (i ≤ z)
x ← x.left
else if (i = z + 1)
Delete(x) and break
else // i > z+1
{
i ← i – (z + 1)
x ← x.right
}
}
5 שאלה
Get_place(x) – find x in T1 (if it’s not there, return -1). Go by its pointer to T2, then calculate
the index of x in the tree – Go up from x to the root. In this path sum the number of nodes that
are in the left subtree of the nodes in the path that are smaller than x:
place ← 1
place ← place+x.left.size
while (x.parent != null)
{
if (x is left_child of x.parent)
x ← x.parent
else //x is right child
place ← place+1+x.parent.left.size
x ← x.parent
}
return place
6 שאלה
לכל.• פקיד רוצה לשמור רשימה של המטלות שלו
ולכל מטלה הפקיד,מטלה יש מספר מזהה ייחודי
.מעוניין לשמור האם היא כבר בוצעה או לא
• הציעו מבנה נתונים שיבצע עבור הפקיד את
. במקרה הגרועO(log n)הפעולות הבאות ב
1.
2.
3.
Insert(k, t) - Insert a new task t with id = k to the data structure,
at first mark the task as not completed.
Update(k) – Update task with ID = k to be completed.
FindDiff(k) – Find the difference between the number of
completed and incomplete (| #of completed – #of incomplete|)
among all the tasks with ID smaller than k.
6 שאלה
1.
2.
3.
Insert(k, t) - Insert a new task t with id = k to the data structure,
at first mark the task as not completed.
Update(k) – Update task with ID = k to be completed.
FindDiff(k) – Find the difference between the number of
completed and incomplete (| #of completed – #of incomplete|)
among all the tasks with ID smaller than k.
ממויין לפי המספרAVL נשתמש בעץ:פתרון
שדות נוספים – מספר2 בו כל קודקוד מכיל,המזהה
.העץ המושרש בו-המטלות שבוצעו ולא בוצעו בתת
6 שאלה
Insert (k, t)
create new node x
x.ID ← k
x.task ← t
x.isCompleted ← 0 //(incomplete task)
x.num_incomplete ← 1 // (a new node is always inserted as a leaf)
x.num_completed ← 0
AVL-Insert(x) // With rotations that update new fields where necessary.
for every node v in the path from x to the root do:
v. num_incomplete ← v. num_incomplete + 1
Time complexity : O(logn)
Update (k)
x ← AVL-search(k) // O(logn)
if x.isCompleted ===1 0
O(1)
x. isCompleted ← 10
for every node v in the path from x to the root do:
v. num_incomplete ← v. num_incomplete – 1
v. num_completed ← v. num_completed + 1
Time complexity : O(logn)
O(logn)
O(1)
O(logn)
6 שאלה
FindDiff (k)
sum_c ← 0
O(1)
sum_i ← 0
T ← the root of the tree
// search for a node with ID = k:
while (T != NULL)
if (T.ID < k )
sum_c ← sum_c + T.left.num_completed
sum_i ← sum_i + T.left.num_incomplete
if (T.isCompleted = 1)
sum_c = sum_c + 1
else
sum_i = sum_i + 1
T ← T.right
else
T ← T.left
return sum_c – sum_i |
Time complexity : O(logn)
O(logn)
שאלות נוספות (אם יש זמן(
•
•
•
•
•
מה יהיה שדה ה sizeשל הקודקודים הבאים בעץ,
לאחר הסיבוב?
האם ייתכן עץ ה AVLהבא ,לאחר הכנסה (אך לפני
key=15
הסיבוב)?
size= 19
ייתכן לאחר מחיקה?
האם זה
key=20
key=8
size= 3
עץ AVLעם 2עליםsize= 15,
שאחד בעומק 5
האם ייתכן
key=4
key=10
ואחד בעומק ?9
size= 7
size= 7
האם ייתכן עץ AVLעם 2עלים ,שאחד בעומק 3
ואחד בעומק ?7