You are on page 1of 36

‫קורס תכנות בשפת ‪C‬‬

‫פרק ‪19‬‬
‫מבני נתונים – תור ‪Queue -‬‬

‫ד"ר שייקה בילו‬


‫יועץ ומרצה בכיר למדעי המחשב וטכנולוגית מידע‬
‫מומחה למערכות מידע חינוכיות‪ ,‬אקדמיות ומנהליות‬
‫‪SCE-Chapter 19‬‬ ‫‪Shayke Bilu PhD‬‬
‫תור – הגדרה והסבר‬

‫‪ ‬תורים מוכרים לכם בוודאי ממקומות רבים (מכולת‪ ,‬בנק‪ ,‬אוטובוס‪,‬‬


‫וכו')‪.‬‬
‫‪ ‬בניגוד לתורים מחיי היומיום‪ ,‬שבהם יש כאלה שמתעקשים לעקוף‬
‫כדי לקצר את זמן ההמתנה‪ ,‬התורים שנעסוק בהם מסודרים מאוד‪:‬‬
‫הכניסה אל התור נעשית בקצהו האחד‪ ,‬והיציאה ממנו נעשית‬
‫בקצהו השני‪.‬‬
‫‪ ‬למעשה‪ ,‬תור דומה במקצת למחסנית‪ .‬כזכור‪ ,‬הגישה למחסנית‬
‫נעשית בשיטת "נכנס אחרון – יוצא ראשון" (‪ ,)LIFO‬ואילו‬
‫הגישה לתור נעשית בשיטת "נכנס ראשון – יוצא ראשון"‬
‫(‪.)FIFO – First In First Out‬‬
‫‪SCE-Chapter 19‬‬ ‫‪Shayke Bilu PhD‬‬
‫תור – הגדרה והסבר‬

‫‪ ‬מבין כל האיברים בתור‪ ,‬זה שיצא ראשון הוא האיבר ה"ותיק"‬


‫ביותר בתור‪ ,‬כלומר – האיבר ששהה בתור זמן רב ביותר‪.‬‬
‫‪ ‬טיפוס הנתונים המופשט (טנ"מ) "תור" הוא בעל התכונות‬
‫הבאות‪:‬‬
‫‪ ‬כשמכניסים איבר חדש לתור‪ ,‬האיבר נכנס לסוף התור ("זנב התור")‪.‬‬
‫‪ ‬כשמוציאים איבר מתור‪ ,‬מּוצא האיבר הנמצא בראש התור‪.‬‬

‫‪SCE-Chapter 19‬‬ ‫‪Shayke Bilu PhD‬‬


‫תור – הגדרה והסבר‬
‫לטיפוס הנתונים המופשט (טנ"מ) "תור" ישנם שימושים רבים בתוכנה‪.‬‬ ‫‪‬‬
‫לדוגמא‪ ,‬כל מדפסת מנהלת תור הדפסות (‪ ,)print queue‬אשר מכיל את כל‬ ‫‪‬‬
‫העבודות שנשלחו למדפסת‪.‬‬
‫העבודות מתבצעות לפי הסדר בו נשלחו להדפסה (לפי עקרון ‪.)FIFO‬‬ ‫‪‬‬
‫במיוחד יש חשיבות לתור כזה במדפסת אשר מחוברים אליה מספר מחשבים‪,‬‬ ‫‪‬‬
‫ברשת תקשורת מקומית‪ ,‬כדי להבטיח הוגנות בגישה למשאב המשותף‪.‬‬

‫‪SCE-Chapter 19‬‬ ‫‪Shayke Bilu PhD‬‬


‫תור – הגדרה והסבר‬

‫אילו פעולות ממשק נרצה שתהיינה מוגדרות על טנ"מ תור?‬ ‫‪‬‬


‫דרושות פעולות ממשק של הכנסה לתור והוצאה מתור‪.‬‬ ‫‪‬‬
‫לפני שמוציאים איבר מתור‪ ,‬צריך לוודא שבתור יש איברים‪,‬‬ ‫‪‬‬
‫לכן נכלול בממשק פעולה של בדיקה האם התור הוא ריק‪.‬‬
‫נכלול גם פעולה שימושית המחזירה את ערכו של האיבר‬ ‫‪‬‬
‫הנמצא בראש התור‪ ,‬אך מבלי להוציאו מהתור‪.‬‬
‫לבסוף‪ ,‬נכלול בממשק גם פעולה שיוצרת תור מאותחל (כלומר‪,‬‬ ‫‪‬‬
‫תור חוקי וריק)‪.‬‬

‫‪SCE-Chapter 19‬‬ ‫‪Shayke Bilu PhD‬‬


‫תור – תאור טיפוס הנתונים‬
‫‪ ‬כך יראה הממשק של טיפוס הנתונים המופשט "תור"‪:‬‬

‫‪SCE-Chapter 19‬‬ ‫‪Shayke Bilu PhD‬‬


‫תור – פיתוח אלגוריתם‬

‫‪ ‬כתבו אלגוריתם המקבל מס' טבעי ‪ n‬ומערך ‪ a‬המכיל ‪ n‬מס'‬


‫שלמים‪ .‬האלגוריתם יבנה ויחזיר תור המכיל רק את האיברים‬
‫השליליים המופיעים במערך ‪ ,a‬לפי הסדר בו הם הופיעו במערך‪.‬‬
‫‪ ‬תור‪-‬שליליים (‪)a,n‬‬
‫‪ ‬אתחל‪-‬תור ‪Q ‬‬
‫‪ ‬עבור ‪ i‬מ‪ 0-‬עד ‪ ,n-1‬בצע‪:‬‬
‫‪ ‬אם ‪ ,a[i] < 0‬אזי‪:‬‬
‫הכנס‪-‬לתור (]‪)Q,a[i‬‬ ‫‪‬‬

‫‪ ‬החזר ‪Q‬‬

‫‪SCE-Chapter 19‬‬ ‫‪Shayke Bilu PhD‬‬


?‫שאלות‬

SCE-Chapter 19 Shayke Bilu PhD


‫תור – תרגול ‪1‬‬

‫במשרד הפנים מתקבלות בקשות רבות להנפקת דרכונים‬ ‫‪‬‬


‫חדשים במקום דרכונים שפג תוקפם‪.‬‬
‫כדי למנוע המתנה ארוכה‪ ,‬מקליד כל אדם המגיע למשרד‬ ‫‪‬‬
‫הפנים את מספר הדרכון שלו‪ ,‬והבקשות מטופלות בהתאם‬
‫לסדר הגעתן‪.‬‬
‫כשעה לפני סגירת משרד הפנים נבדק אורכו של התור‪ ,‬ואם יש‬ ‫‪‬‬
‫בו למעלה מ‪ 30-‬בקשות לא מאפשרים קבלת בקשות נוספות‬
‫לאותו יום‪.‬‬
‫פתחו אלגוריתם המקבל את תור הדרכונים‪ ,‬ומחזיר את מספר‬ ‫‪‬‬
‫הבקשות הממתינות‪.‬‬

‫‪SCE-Chapter 19‬‬ ‫‪Shayke Bilu PhD‬‬


‫תור – פתרון תרגול ‪1‬‬

‫נפתור את הבעיה בשתי דרכים שונות‪.‬‬ ‫‪‬‬


‫ראשית‪ ,‬נבחין כי בסריקת תור‪ ,‬כאשר מוציאים את האיבר‬ ‫‪‬‬
‫הנמצא בראש התור – הוא אובד‪.‬‬
‫כדי לא לאבד אותו‪ ,‬ניתן להכניסו לסוף התור‪ ,‬וכך גם נשמר‬ ‫‪‬‬
‫הסדר‪.‬‬
‫כיצד נדע שהושלמה סריקה של כל איברי התור?‬ ‫‪‬‬
‫נשתמש במנגנון סריקה שיכלול אלמנט נוסף‪ :‬מאחר והתור‬ ‫‪‬‬
‫מכיל מספרי דרכונים המיוצגים ע"י מחרוזת‪ ,‬ניתן להכניס‬
‫לסוף התור מחרוזת דמה המכילה ערך שאינו יכול להיות מספר‬
‫דרכון‪.‬‬
‫‪SCE-Chapter 19‬‬ ‫‪Shayke Bilu PhD‬‬
‫תור – פתרון תרגול ‪1‬‬

‫• כל איבר בתור המייצג מספר דרכון יצא מתחילת התור ויכנס אל‬
‫סופו‪.‬‬
‫• כאשר מחרוזת הדמה תחזור להיות ראשונה‪ ,‬הושלם למעשה‬
‫סיבוב של כל איברי התור‪.‬‬

‫‪SCE-Chapter 19‬‬ ‫‪Shayke Bilu PhD‬‬


‫תור – פתרון תרגול ‪ – 1‬חלופה א'‬

‫מספר‪-‬אנשים (‪)Q‬‬
‫הכנס‪-‬לתור (”‪)Q,”000‬‬
‫‪count  0‬‬
‫כל עוד ראש‪-‬התור (‪ )Q‬שונה מ‪ ,"000"-‬בצע‪:‬‬
‫הוצא‪-‬מתור (‪x  )Q‬‬
‫הכנס‪-‬לתור (‪)Q,x‬‬
‫‪count  count + 1‬‬
‫הוצא‪-‬מתור (‪x  )Q‬‬
‫החזר ‪count‬‬
‫‪SCE-Chapter 19‬‬ ‫‪Shayke Bilu PhD‬‬
‫תור – פתרון תרגול ‪ – 1‬חלופה ב'‬
‫‪ ‬בדרך ב'‪ ,‬נשתמש בתור עזר על מנת למנות את מספר האיברים בתור‪.‬‬
‫‪ ‬נעביר את כל איברי התור המקורי לתור עזר‪ ,‬ולאחר מכן נחזיר אותם חזרה‪.‬‬
‫מספר‪-‬אנשים (‪)Q‬‬
‫אתחל‪-‬תור ‪Q1 ‬‬
‫‪count  0‬‬
‫כל עוד לא תור‪-‬ריק? (‪ ,)Q‬בצע‪:‬‬
‫הוצא‪-‬מתור (‪x  )Q‬‬
‫הכנס‪-‬לתור (‪)Q1,x‬‬
‫‪count  count + 1‬‬
‫כל עוד לא תור‪-‬ריק? (‪ ,)Q1‬בצע‪:‬‬
‫הכנס‪-‬לתור (הוצא‪-‬מתור (‪)Q ,)Q1‬‬
‫החזר ‪count‬‬

‫‪SCE-Chapter 19‬‬ ‫‪Shayke Bilu PhD‬‬


?‫שאלות‬

SCE-Chapter 19 Shayke Bilu PhD


‫תרגילים ‪1 -‬‬

‫‪ ‬פתחו אלגוריתם המקבל תור ‪ Q‬של מספרים שלמים‪ ,‬ומחזיר‬


‫תור חדש ‪ Q1‬המכיל את ההפרש בין כל זוג איברים ב‪.Q-‬‬
‫‪ ‬אין לשנות את התור המקורי ‪.Q‬‬
‫‪ ‬לדוגמא‪ ,‬עבור התור הבא‪Q = 7 , 2 , 6 , 9 , 5 , 3 :‬‬
‫‪Q1 = 5 , -4 , -3 , 4 , 2‬‬ ‫‪ ‬יוחזר התור הבא‪:‬‬

‫‪SCE-Chapter 19‬‬ ‫‪Shayke Bilu PhD‬‬


‫תרגילים ‪2 -‬‬

‫‪ ‬פתחו אלגוריתם עדכן‪-‬תור (‪ )Q,x1,x2‬המקבל תור ‪ Q‬של‬


‫מספרים שלמים‪ ,‬ומשנה את התור כך שכל מופע של ‪ x1‬ב‪,Q-‬‬
‫הוחלף בערך ‪.x2‬‬
‫‪ ‬לדוגמא‪ ,‬עבור ‪x1 = 3 , x2 = 5‬‬
‫והתור‪Q = 6 , 3 , 5 , -1 , 3 , -3 :‬‬
‫‪ ‬לאחר זימון האלגוריתם‪ ,‬התור יראה כך‪:‬‬
‫‪Q = 6 , 5 , 5 , -1 , 5 , -3‬‬

‫‪SCE-Chapter 19‬‬ ‫‪Shayke Bilu PhD‬‬


‫תרגילים ‪3 -‬‬

‫‪ ‬פתחו אלגוריתם המקבל תור המכיל מספרים שלמים‪,‬‬


‫ומחזיר את התור כאשר בתחילתו מופיעים כל‬
‫המספרים החיוביים ובסופו כל המספרים האי‪-‬חיוביים‪.‬‬
‫‪ ‬מותר להשתמש רק בטיפוס הנתונים "תור" ‪.‬‬

‫‪SCE-Chapter 19‬‬ ‫‪Shayke Bilu PhD‬‬


‫מימוש תור‬

‫‪ ‬כיצד נייצג תור בסביבת העבודה?‬


‫‪ ‬ניתן לייצג את איברי התור על‪-‬ידי רשימה מקושרת חד‪-‬‬
‫כיוונית‪ ,‬ולשמור מצביע ‪ head‬לראש הרשימה ומצביע ‪rear‬‬
‫לסוף הרשימה‪.‬‬
‫‪ ‬מדוע עדיף להשתמש בשני מצביעים כאלו מאשר להסתפק באחד?‬
‫‪ ‬אפשר להסתפק באחד‪ ,‬אולם אז סיבוכיות זמן הריצה תגדל‪.‬‬
‫‪ ‬פעולות על תור באופן טבעי מתייחסות לשני מקומות בו‪:‬‬
‫ראש התור וסוף התור‪ ,‬ולכן רצוי לאחסן מצביע לכל אחד משני‬
‫המקומות השונים האלה‪.‬‬

‫‪SCE-Chapter 19‬‬ ‫‪Shayke Bilu PhD‬‬


‫מימוש תור‬

:‫) ברשימה המקושרת‬node( ‫ חוליה‬,‫ כמקודם‬,‫נגדיר‬

typedef int queue_item;

typedef struct node_type


{
queue_item info;
struct node_type *next;
} node;

SCE-Chapter 19 Shayke Bilu PhD


‫מימוש תור‬

‫‪ ‬את ההגדרה של ‪ queue_item‬נכלול בקובץ ‪ ,queue.h‬ובקובץ‬


‫‪ queue.c‬נכתוב את הגדרת ה‪ node-‬ואת הגדרת התור‪.‬‬

‫‪ ‬נגדיר תור בתור מבנה‪ ,‬המכיל בתוכו מצביע לחוליה הראשונה‬


‫(ראש התור) ומצביע לחוליה האחרונה (סוף התור)‪:‬‬

‫{ ‪typedef struct‬‬
‫;‪node *head, *rear‬‬
‫;‪} queue‬‬
‫‪SCE-Chapter 19‬‬ ‫‪Shayke Bilu PhD‬‬
‫מימוש תור‬

‫איך יראו פעולות הממשק ב‪?queue.h-‬‬


‫;)‪void queue_init(queue *q‬‬
‫‪ */‬הפונקציה בונה תור ריק *‪/‬‬

‫;)‪void enqueue (queue *q, queue_item x‬‬


‫‪ */‬הפונקציה מכניסה את הערך ‪ x‬לסוף התור ‪/* q‬‬

‫;)‪queue_item dequeue (queue *q‬‬


‫‪ */‬הפונקציה שולפת את הערך שבראש התור ומחזירה אותו *‪/‬‬

‫;)‪queue_item queue_top (queue q‬‬


‫‪ */‬הפונקציה מחזירה את הערך שבראש התור‪ ,‬מבלי לשלוף אותו *‪/‬‬

‫;)‪int queue_empty (queue q‬‬


‫‪ */‬הפונקציה תחזיר ‪ 1‬אם התור ריק‪ ,‬ו‪ 0-‬אם לא *‪/‬‬

‫‪SCE-Chapter 19‬‬ ‫‪Shayke Bilu PhD‬‬


‫מימוש תור‬
:queue.c ‫כך יראה קובץ המימוש‬
void queue_init (queue *q)
{
q->head = q->rear = NULL;
}
int queue_empty (queue q)
{
return (q.head == NULL);
}
void enqueue (queue *q, queue_item x)
{
node *a = malloc(sizeof(node));
a->info = x; a->next = NULL;
if (queue_empty(*q))
q->head = q->rear = a; ‫ לא לקחנו את שתי‬,enqueue ‫מדוע במימוש‬
else { ‫ והפכנו אותן להשמה‬,else-‫ההשמות שב‬
q->rear->next = a;
q->rear = a; ‫מרובה אחת (בדומה להשמה המרובה‬
} ?)if-‫שאחרי ה‬
}
SCE-Chapter 19 Shayke Bilu PhD
‫מימוש תור‬
:queue.c ‫המשך המימוש‬
queue_item dequeue (queue *q)
{
queue_item x;
node *ptr = q->head;
if (!queue_empty(*q)) {
x = q->head->info;
q->head = q->head->next;
if (q->head == NULL)
q->rear = NULL;
free(ptr);
return x;
}
}
queue_item queue_top (queue q)
{
if (!queue_empty(q)) {
return q.head->info;
}
}
SCE-Chapter 19 Shayke Bilu PhD
‫מימוש תור‬

‫‪ ‬נסמן ב‪ n-‬את מספר האיברים בתור‪ .‬עבור המימוש שהוצג‪,‬‬


‫מהי סיבוכיות זמן הריצה‪ ,‬כפונקציה של ‪ ,n‬של כל אחת‬
‫מפעולות הממשק של טנ"מ תור?‬
‫‪ ‬במימוש תור באמצעות רשימה מקושרת‪ ,‬עם מצביע לראש‬
‫הרשימה ולסופה‪ ,‬כל אחת מפעולות הממשק (איתחול‪ ,‬הכנסה‪,‬‬
‫הוצאה‪ ,‬בדיקה האם ריק‪,‬הצצה) מבצעת כמות קבועה של‬
‫עבודה‪ ,‬ללא קשר לשאלה כמה איברים נמצאים כרגע בתור‪.‬‬
‫‪ ‬מכיוון שהפעולות הללו אינן תלויות בגודל ‪ ,n‬הן מתבצעות‬
‫בזמן קבוע )‪.Θ(1‬‬

‫‪SCE-Chapter 19‬‬ ‫‪Shayke Bilu PhD‬‬


‫מימוש תור‬
‫‪ ‬כיצד ישתנו פעולות הממשק‪ ,‬וכיצד תשתנה סיבוכיות זמן הריצה שלהם‪ ,‬אם‬
‫משנים את המימוש של טנ"מ תור באופן הבא‪...‬‬
‫‪ ‬כעת מחזיקים רק מצביע ‪ head‬לראש הרשימה‪ ,‬מבלי להחזיק מצביע ‪rear‬‬
‫לסופה‪.‬‬
‫‪ ‬כעת מחזיקים רק מצביע ‪ ,rear‬ללא מצביע ‪ .front‬הניחו כי ‪ rear‬מצביע‬
‫על רשימה מקושרת חד‪-‬כיוונית שתחילתה מציינת את סוף התור‪ ,‬וסופה‬
‫מציין את ראש התור‪.‬‬
‫‪ ‬כעת מחזיקים רק מצביע ‪ ,head‬המציין את ראש התור‪ ,‬והמצביע‬
‫על חוליה ברשימה מקושרת מעגלית דו‪-‬כיוונית‪.‬‬
‫‪ ‬יתכן ונרצה להוסיף למימוש גם פונקציה ‪ ,queue_full‬המקבלת‬
‫תור ובודקת אם הוא מלא או לא‪ .‬במימוש שלנו (העושה שימוש‬
‫ברשימה מקושרת) – התור אף פעם לא יתמלא‪ .‬במימושים‬
‫אחרים (נניח‪ ,‬במערך סטטי) התור עשוי להתמלא‪.‬‬
‫‪SCE-Chapter 19‬‬ ‫‪Shayke Bilu PhD‬‬
?‫שאלות‬

SCE-Chapter 19 Shayke Bilu PhD


‫חידה לחימום‬

‫כדי להיכנס לבניין‪ ,‬לילך צריכה להקיש קוד המורכב מספרות‪,‬‬ ‫‪‬‬
‫שכל אחת מהן היא ‪ 3,2,1‬או ‪ ,4‬ולבסוף להקיש סולמית‪.‬‬
‫ניתן להקיש ספרה יותר מפעם אחת‪.‬‬ ‫‪‬‬
‫לילך שכחה את הקוד‪ ,‬אך זכרה שסכום הספרות שלו הוא ‪.10‬‬ ‫‪‬‬
‫מהו מספר האפשרויות השונות שתצטרך לילך לבדוק‪ ,‬במקרה‬ ‫‪‬‬
‫הגרוע ביותר‪ ,‬עד שתגיע לקוד הנכון‪ ,‬אם מספר הספרות להקשה‬
‫הוא בדיוק ‪?4‬‬
‫למשל‪ ,‬אם הסכום היה ‪( 4‬במקום ‪ ,)10‬אז התשובה הייתה ‪ ,1‬כי‬ ‫‪‬‬
‫הדרך היחידה להגיע לסכום ‪ 4‬עם ‪ 4‬ספרות היא ‪.1,1,1,1‬‬
‫שימו לב שסדר הקשת הספרות הוא חשוב‪.‬‬ ‫‪‬‬
‫‪SCE-Chapter 19‬‬ ‫‪Shayke Bilu PhD‬‬
‫תור קדימויות‬
‫‪ ‬תור קדימויות (‪ ,)priority queue‬המכונה לעיתים גם תור‬
‫עדיפויות‪ ,‬הוא טיפוס נתונים מופשט‪ ,‬המאפשר לנהל אוסף של‬
‫איברים‪ ,‬שכל אחד מהם כולל גם שדה מידע (‪ )info‬וגם שדה‬
‫עדיפות (‪.)priority‬‬
‫‪ ‬להבדיל מתור רגיל (המתנהל לפי עקרון ‪ ,FIFO‬כלומר – מי‬
‫שנכנס ראשון גם יישלף ראשון) ולהבדיל ממחסנית (המתנהלת‬
‫לפי עקרון ‪ – LIFO‬מי שנכנס אחרון הוא שיישלף ראשון)‪,‬‬
‫בתור קדימויות השליפה היא לפי סדר העדיפויות – ראשית‬
‫יישלף האיבר שעדיפותו היא הגבוהה ביותר‪.‬‬

‫‪SCE-Chapter 19‬‬ ‫‪Shayke Bilu PhD‬‬


‫תור קדימויות‬

‫‪ ‬פעולות ממשק על טנ"מ "תור קדימויות"‪:‬‬


‫‪ ‬הוספת איבר חדש – פעולה המקבלת איבר להוספה (הן את‬
‫ערכו ואת עדיפותו) ומצרפת אותו לתור הקדימויות‪.‬‬
‫‪ ‬איחזור האיבר המקסימלי – זו פעולה אשר מחזירה את‬
‫האיבר שעדיפותו היא מקסימלית‪ ,‬אך מבלי להוציאו מתור‬
‫הקדימויות‪ .‬נשים לב שהמקסימליות כאן היא על העדיפות‪,‬‬
‫ולא על הערך‪.‬‬
‫‪ ‬הוצאת האיבר המקסימלי – זו פעולה אשר מוציאה מתור‬
‫הקדימויות‪ ,‬ומחזירה את האיבר שעדיפותו היא מקסימלית‪.‬‬
‫גם כאן המקסימליות היא על העדיפות‪ ,‬ולא על הערך‪.‬‬
‫‪SCE-Chapter 19‬‬ ‫‪Shayke Bilu PhD‬‬
‫תור קדימויות‬
‫‪ ‬דוגמאות לשימוש בתור קדימויות‪:‬‬
‫‪ ‬במערכות הפעלה מרובות‪-‬תהליכים‪ ,‬ישנו סדרן תכניות‬
‫(‪ )Scheduler‬שתפקידו להקצות זמן מעבד לתהליכים השונים‪.‬‬
‫הוא עושה זאת‪ ,‬בדרך כלל‪ ,‬לפי עדיפות המוצמדת לכל תהליך‪.‬‬
‫‪ ‬דרך נתב תקשורת (‪ )router‬עוברים זרמי מידע הקשורים‬
‫לפעולות מסוימות‪ ,‬שחייבות להתבצע באופן מקוון (כמו צ'אט‬
‫וידאו)‪ .‬כמו כן‪ ,‬עוברים זרמי מידע הקשורים לפעולות שאינן‬
‫חייבות להתבצע באופן מקוון (נניח‪ ,‬שליחת דוא"ל)‪ .‬בעזרת‬
‫תור קדימויות אפשר להבטיח שמידע מסוים הנשלח בערוץ‬
‫יקבל תיעדוף בהקצאת רוחב פס‪.‬‬

‫‪SCE-Chapter 19‬‬ ‫‪Shayke Bilu PhD‬‬


?‫שאלות‬

SCE-Chapter 19 Shayke Bilu PhD


‫מימוש תור קדימויות‬
‫‪ ‬נציע מבנה נתונים שיהווה מימוש לטנ"מ 'תור קדימויות'‪:‬‬
‫נחזיק רשימה מקושרת בה האיברים ממוינים בסדר יורד (לפי שדה העדיפות‪,‬‬ ‫‪‬‬
‫ולא לפי שדה המידע)‪.‬‬
‫באופן זה נבטיח‪ ,‬שהאיבר שעדיפותו היא הגבוהה ביותר‪ ,‬יהיה תמיד בראש‬ ‫‪‬‬
‫הרשימה (בדוגמא שלפנינו‪ :‬מדובר באיבר שערכו ‪ ,44‬ועדיפותו היא ‪.)30‬‬

‫‪head‬‬ ‫‪NULL‬‬
‫‪30‬‬ ‫‪20‬‬ ‫‪20‬‬ ‫‪5‬‬
‫‪44‬‬ ‫‪-5‬‬ ‫‪21‬‬ ‫‪12‬‬
‫‪ ‬מה תהיה הסיבוכיות של פעולות הממשק?‬
‫איחזור המקסימום יתבצע בזמן קבוע (‪.Θ)1‬‬ ‫‪‬‬
‫נמקו מדוע!‬ ‫הוצאת המקסימום תתבצע בזמן קבוע (‪.Θ)1‬‬ ‫‪‬‬
‫הכנסת איבר חדש תתבצע בזמן לינארי (‪.Θ)n‬‬ ‫‪‬‬

‫‪SCE-Chapter 19‬‬ ‫‪Shayke Bilu PhD‬‬


‫מימוש תור קדימויות‬

‫‪ ‬מימוש חלופי לטנ"מ "תור קדימויות"‪:‬‬


‫‪ ‬נחזיק עץ חיפוש בינארי מאוזן (למשל – עץ ‪ ,)AVL‬אשר הכלל לפיו‬
‫מסודרים בו האיברים הוא הסדר הנקבע בידי שדה העדיפות‪ ,‬ולא בידי‬
‫שדה המידע‪.‬‬
‫‪priority: 12‬‬
‫‪info: 107‬‬
‫‪ ‬באופן זה נבטיח‪ ,‬שהאיבר שעדיפותו‬
‫היא הגבוהה ביותר‪ ,‬יהיה תמיד בקצהו‬
‫‪priority: 18‬‬ ‫הימני של העץ‪.‬‬
‫‪priority: 8‬‬ ‫‪info: 25‬‬
‫‪info: 6‬‬ ‫‪ ‬אנחנו יודעים‪ ,‬מהיכרות‬
‫‪priority: 17‬‬ ‫‪ ‬עם עצי חיפוש בינארי‪ ,‬שמציאת‬
‫‪info: 6‬‬ ‫‪ ‬מקסימום נעשית בזמן לוגריתמי‪.‬‬
‫‪SCE-Chapter 19‬‬ ‫‪Shayke Bilu PhD‬‬
‫מימוש תור קדימויות‬
‫‪ ‬כדי שלא נצטרך לבצע חישוב שאורכו לוגריתמי‪ ,‬בכל פעם שנרצה‬
‫להגיע אל האיבר המקסימלי‪ ,‬נשמור באופן קבוע מצביע אל איבר‬
‫זה‪.‬‬
‫‪priority: 12‬‬
‫‪info: 107‬‬ ‫‪max‬‬ ‫‪ ‬כמה זמן יארכו פעולות‬
‫הממשק של הטנ"מ?‬
‫‪ ‬איחזור המקסימום יתבצע‬
‫‪priority: 8‬‬
‫‪info: 6‬‬ ‫‪priority: 18‬‬ ‫‪ ‬בזמן קבוע (‪.Θ)1‬‬
‫‪info: 25‬‬ ‫‪ ‬הוצאת המקסימום‬ ‫מדוע?‬
‫‪ ‬תתבצע בזמן לוגריתמי (‪.Θ)logn‬‬
‫‪ ‬הכנסת איבר חדש תתבצע‬
‫‪priority: 17‬‬
‫‪info: 6‬‬ ‫‪ ‬בזמן לוגריתמי (‪.Θ)logn‬‬

‫‪SCE-Chapter 19‬‬ ‫‪Shayke Bilu PhD‬‬


‫מימוש תור קדימויות‬
‫‪ ‬לעיתים מעוניינים שבתור הקדימויות הנתונים יישמרו בסדר‬
‫עולה של עדיפות‪ ,‬ולא בסדר יורד‪.‬‬
‫‪ ‬במקרה כזה פעולות הממשק איחזור מקסימום והוצאת מקסימום‪,‬‬
‫יוחלפו באיחזור מינימום והוצאת מינימום‪.‬‬
‫‪ ‬מה יש לשנות בשני המימושים שהוצעו לעיל?‬
‫‪ ‬במימוש באמצעות רשימה מקושרת ממוינת‪ ,‬סדר המיון יהיה יורד במקום‬
‫עולה‪.‬‬
‫‪ ‬במימוש באמצעות עץ חיפוש בינארי מאוזן (עץ ‪ ,)AVL‬המצביע‬
‫שנשמור יהיה אל האיבר המינימלי במקום למקסימלי‪.‬‬
‫‪ ‬סיבוכיות זמן הריצה של פעולות הממשק לא תשתנה‪.‬‬

‫‪SCE-Chapter 19‬‬ ‫‪Shayke Bilu PhD‬‬


?‫שאלות‬

SCE-Chapter 19 Shayke Bilu PhD

You might also like