Document

advertisement
‫תרגול מס' ‪:1‬‬
‫מבני נתונים – מבוא‬
‫כללי‬
‫•‬
‫•‬
‫•‬
‫•‬
‫מבנה נתונים – דרך לארגן נתונים במחשב ולגשת אליהם‪.‬‬
‫בקורס זה נלמד על מבני נתונים שונים אשר משמשים לבניית‬
‫אלגוריתמים יעילים למגוון בעיות‪ .‬בבואנו לתכנן אלגוריתם הדורש‬
‫פעולות על קבוצות נרצה להשתמש במבנה נתונים המתאים לנו‬
‫מבחינת סוג הפעולות אשר הוא תומך בהן‪ ,‬ומבחינת יעילות (זמן‬
‫ריצה‪ ,‬מקום בזיכרון)‪.‬‬
‫מבני נתונים הידועים לנו עד כה‪ :‬מערכים‪ ,‬עצים‪ ,‬תורים‪ ,‬מחסניות‪,‬‬
‫רשימות‪ .‬למשל כאשר רצינו לבצע חיפוש יעיל על קבוצת מספרים‬
‫השתמשנו במערך ממוין והפעלנו עליו חיפוש בינרי‪.‬‬
‫החומר התיאורטי יוצג בהרצאות‪ ,‬כאשר בתרגולים נתרכז בפתרון‬
‫בעיות בעזרת מבנים שונים‪.‬‬
‫הצורך במבני נתונים‪:‬‬
‫• מאפשרים תכנון ומימוש של בעיות מורכבות‪.‬‬
‫• בעזרתם ניתן ללמוד על תכונות שונות של הקבוצה‪ ,‬תכונות לא‬
‫בולטות לעין‪.‬‬
‫• תכנון נכון יכול להביא לכתיבת תכניות באופן פשוט‪ ,‬יעיל ומדויק‬
‫(ראה דוגמא )‪.‬‬
‫דוגמה‬
‫• שני אנשים ‪ S‬ו ‪ Y‬קיבלו עבודה בתור מזכירים‪ .‬במסגרת העבודה כל‬
‫אחד אחראי על ארון תיקים אישיים‪ .‬סדר יומו של ‪ S‬בהינתן תיק‬
‫אישי חדש היה פשוט לזרוק את התיק לתוך המגירה‪ .‬סדר יומו של‬
‫‪ Y‬בהינתן תיק אישי חדש היה להכניסו למקומו לפי סדר אלף‪-‬בית‪.‬‬
‫כמה זמן עבד כל אחד מהם?‬
‫ל ‪ S‬העבודה הייתה מאוד פשוטה‪ ,‬למעשה הוא לא עבד בכלל!‬
‫לעומתו ‪ Y‬היה צריך למצוא את מיקומו של התיק החדש ורק אז‬
‫להכניסו למקום!‬
‫האם העבודה של ‪ S‬יעילה יותר?‬
‫התשובה לשאלת היעילות תלויה בהמשך‪ .‬אם בזה סיימנו את‬
‫העבודה‪ ,‬אז עבודת ‪ S‬יעילה יותר!‬
‫•‬
‫•‬
‫•‬
‫•‬
‫•‬
‫•‬
‫•‬
‫•‬
‫אבל מה אם יבקשו תיק מתוך האוסף? איזה עבודה תהיה יעילה‬
‫יותר?‬
‫ברור ש ‪ Y‬יוכל לשלוף את התיק מהר יותר!‬
‫ומה היה קורה אם היו מבקשים תיק לפי מספר ת‪.‬ז‪?.‬‬
‫במקרה זה לא יהיה הבדל!‬
‫כל זאת בכלל בלי להתייחס למקום‪.‬‬
‫איזה צורת ארגון דורשת יותר מקום?‬
‫‪ S‬יכול להשתמש במגירה אחת גדולה עבור כל התיקים‪.‬‬
‫אינטואיטיבית נראה ש‪ Y -‬צריך יותר מקום (חוצצים או מגירה לכל‬
‫אות)‪ .‬אך האם זה באמת נחוץ?‬
‫הנקודה החשובה בדוגמה זו היא שיעילות נקבעת לפי צורת ארגון‬
‫הנתונים‪ .‬צורת הארגון‪ ,‬אם היא מתוכננת כראוי‪ ,‬צריכה להיות‬
‫מותאמת לסוג הבעיה‪ .‬בקורס זה‪ ,‬נרצה לחקור את צורות הארגון‬
‫השונות כדי שבבוא העת נוכל להתאים מבנה נכון לכל בעיה‪.‬‬
‫זמן הריצה של אלגוריתם הוא הערכה‪ ,‬באמצעות חסמים‪ ,‬על מספר‬
‫הפעולות האטומיות שמבצע האלגוריתם במהלך פעולתו‪,‬‬
‫כפונקציה של גודל הקלט (‪.)n‬‬
‫אין בוחנים את זמן הריצה ביחידות זמן (שניות‪ ,‬דקות וכו')‪ ,‬שכן משך‬
‫הזמן לביצוע פעולות משתנה מסביבת ריצה אחת לשנייה‪ ,‬אלא‬
‫ביחידות מדידה מוחלטות (כגון‪ ,‬מספר פעולות ו‪/‬או מספר פעולות‬
‫השוואה)‪ .‬לכן‪ ,‬נוטים להתעלם מקבועים בעת התייחסות לזמן ריצה‬
‫של אלגוריתם‪.‬‬
‫פעולות יסוד (אטומיות)‪ :‬השמה‪ ,‬פעולה מתמטית‪ ,‬פעולת השוואה וכו'‬
Question 1
• An array of n elements is given, how many
comparisons between elements in the array are
needed in order to find the maximum element?
Solution:
• FindMax(A)
• n ← size(A)
• max ← A[0]
• for i ← 1 to n-1
• if A[i] > max then
•
max ← A[i]
The for-loop is executed n-1 times, in each ‘max’ is
compared to the next element in A, thus the
number of comparisons is n-1.
Question 2
• An array of n elements is given, how many
comparisons between two elements in the array
are needed in order to find both the largest and
the second largest number?
Solution 1:
Execute the algorithm described in question 1 twice. Thus n-1
comparisons are needed in order to find the largest and n-2 in
order to find the second largest.
Find2Largest(A)
n ← size(A)
max1 ← A[0]
index ← 0 //index of maximum
for i ← 1 to n-1 then
if A[i] > max1
max1 ← A[i]
index ← i
A' ← A - A[index]
max2 ← A'[0]
for i ← 1 to n-2
if A'[i] > max2
max2 ← A'[i]
• The first for-loop is executed n-1 times and the second is
executed n-2 times. Total = n-1 + n-2 = 2n - 3
Solution 2:
• We build a tournament tree. We place all the n elements in
the leaves and as in tennis tournament, in each round several
pairs “play” against each other and only the larger element of
each pair make it to the next round. The winner is the largest
one, and the second largest is the largest among the elements
who “competed” against the winner, there are log2 n such
elements.
Example
The largest element is 'max'
The second largest element is max{ x1, x2, x3 }
Number of comparisons
• Finding the largest:
n/21 + n/22 + n/23 + ... + n/2k =
n/2 + n/4 + n/8 + ... + 1 = n-1 .
• Finding the second largest:
Use the algorithm shown in question 1 to find the largest
among the (log2 n) numbers who "competed" against the
maximum,
thus (log2 n - 1) comparisons are needed.
• If we sum (1) and (2): n - 1 + log n - 1 = n + log2 n - 2 (instead
of 2n – 3)
Question 3
• What will be the value of k after each execution of the
following code section?
• Provide a rough approximation on the runtime of the
following code sections (disregarding constants).
a. k ← 0
for i ← 1 to n
k++
b.
k←0
for i ← 1 to n
for j ← 1 to n
k++
c.
k←0
for i ← 1 to n
for j ← 1 to i
k++
Solution:
• a. The loop is executed n times, each time k is incremented.
k=n
runtime ≈ n
b. The main loop is executed n times.
The inner loop is executed n times for each execution of the main
loop, in each execution k is incremented.
k=n2
runtime ≈ n2
c. The main loop is executed n times.
The inner loop is executed i times for the i’th iteration of the main
loop, in each execution k is incremented.
k =1+2+…+n=
runtime ≈ n2
n(n  1)
2
Question 4
• What is the number of multiplications in the following code?
• Provide a rough approximation on the runtime of the
following code (disregarding constants).
k←1
while (k < n)
k←k*2
Solution:
• Let i be the number of loop executions.
• The loop ends when 2i ≥ n, thus executed ⌈ log2 n ⌉ times, each
time k is multiplied once.
Number of multiplications: ⌈ log2 n ⌉
Runtime ≈ log2 n
Question 5
• What is the number of multiplications in the following code.
• Provide a rough approximation on the runtime of the
following code (disregarding constants).
for i ← 1 to n
k←1
while (k < i)
k ← k*2
Solution:
• The while-loop is executed ⌈ log2 i⌉ times for each i ( i = 1..n),
each time k is multiplied by two exactly once, therefore the
number of multiplications is:
• ⌈ log 1 ⌉ + ⌈ log 2 ⌉ + ⌈ log 3 ⌉ + … + ⌈ log2 n ⌉≈
• log2 1 + log2 2 + log2 3 + … + log2 n = log2(1*2*3*…*n) =
log2 (n!)
• Consequently, the runtime is roughly log2(n!).
Question 6
• Evaluate the number of multiplications in the following code
(assume that n=2k):
my_power( x, n)
if (n=0) return 1
if (n=1) return x
return my_power(x, n/2)*my_power(x, n/2)
• How can we reduce this number?
Solution:
• The number of multiplications equals to the number of the
inner nodes in the recurrence tree:
• 1+2+4+8…+n/2 = n-1
Improvement
• Evaluate the number of multiplications in the following code:
my_power( x, n)
if (n=0) return 1
if (n=1) return x
temp ← my_power(x, n/2)
return temp*temp
Solution:
• For each recursive call of the improved function my_power,
we have only one new recursive call (and not two as in the
previous code). So, the recurrence tree becomes a path of
length log n (every node has only one child). As we saw
before, the number of multiplications equals to the number of
inner nodes in the recurrence tree, that is for the improved
code, log n – 1
Question 7
• Describe an algorithm that, given a sorted array A of n
integers and an integer x, determines whether or not there
exist two elements in A whose sum is exactly x, by doing at
most 3n comparisons between elements.
Solution:
• TwoSum(A, x)
p←0
q ← n-1
while (p < q)
if (A[p]+A[q] = x)
return "Yes"
else if (A[p]+A[q] < x)
p++
else
q-return "No"
Solution:
• At each iteration of the while loop, either p is incremented or
q is decremented. Hence the number of iterations is bounded
by n-1, in every iteration we do at most 3 comparisons (one to
check the condition of the while loop, and two more inside
the loop).
Example:
• x = 25, A =
1
5
6
7
p
current sum: 32
10
11
12
20
30
31
q
Example:
• x = 25, A =
1
5
6
7
p
current sum: 31
10
11
12
20
30
q
31
Example:
• x = 25, A =
1
5
6
7
p
current sum: 21
10
11
12
20
q
30
31
Example:
• x = 25, A =
1
5
p
• Return "Yes".
6
7
10
11
12
20
q
30
31
‫שאלה ‪8‬‬
‫• נתון מערך ‪ A‬ובו ‪ n‬מספרים‪ .‬הראה כיצד ניתן למצוא‬
‫את המינימום ואת המקסימום של ‪ A‬באמצעות לא‬
‫יותר מאשר ‪ 3n/2‬השוואות‪.‬‬
‫פתרון‪:‬‬
‫• הרעיון‪ :‬נחלק את המספרים לזוגות‪ ,‬בכל זוג נשים את המספר‬
‫הקטן ב – ‪ A1‬ואת הגדול ב – ‪ ,A2‬כך מובטח כי המינימום‬
‫והמקסימום של ‪ ,A‬הם המינימום והמקסימום של ‪A1‬ו – ‪A2‬‬
‫בהתאמה‪.‬‬
• Min_and_Max(A,n)
• A1[n/2],A2[n/2]
• for i←1 to n/2
if (A[i] < A[i + n/2])
A1[i] ← A[i]
A2[i] ← A[i + n/2]
‫ השוואות‬n/2
else
A1[i] ← A[i + n/2]
A2[i] ← A[i]
min ← A1[1]
max ← A2[1]
for i=2 to n/2
if (A1[i] < min)
‫ השוואות‬n/2-1
min ← A1[i]
if (A2[i] > max)
‫ השוואות‬n/2-1
max ← A2[i]
‫• אם ‪ n‬הוא אי‪-‬זוגי‪ ,‬אפשר להכניס את האיבר האחרון של ‪ ,A‬גם ל –‬
‫‪𝑛−1‬‬
‫𝑛‬
‫𝑛‬
‫‪A1‬וגם ל – ‪ A2‬ולקבל שמספר ההשוואות הוא ‪+ + 1 − 1 +‬‬
‫‪3𝑛−1‬‬
‫‪2‬‬
‫= ‪ ,+ 1 − 1‬כלומר עדיין פחות מ ‪-‬‬
‫𝑛‪3‬‬
‫‪2‬‬
‫‪2‬‬
‫השוואות‪.‬‬
‫‪2‬‬
‫‪2‬‬
Download