דוא"ל:




קורס:"מבוא לתכנות"

שיעור 3: אלגוריתמים 

[ <<< הקודם ] [ תוכן עניינים ]

מתוך הספר: C - מדריך מקצועי       C - מדריך מקצועי
תוכן עניינים



אלגוריתם - מה זה?

אלגוריתם הוא סדרה של הוראות מדויקות לביצוע משימה נתונה. הוראות האלגוריתם חייבות להיות מובנות וחד-משמעיות למי שאמור לבצע אותו.

לדוגמא, נניח שבבעלותנו פיצרייה, וקיבלנו הזמנה טלפונית למשלוח פיצה ללקוח בכתובת מסוימת. ההוראות לשליח עם קטנוע יהיו:

:סע לכתובת הלקוח :אתר את  הדירה עפ"י שם הלקוח או עפ"י מספר הדירה :מסור ללקוח את הפיצה וגבה ממנו תשלום :חזור לפיצרייה :

מכיוון שהשליח מבין כל אחת מההוראות והן חד-משמעיות הוא יבצען ללא קושי.

לעומתו, מורה לנהיגה על קטנוע לא ייתן לתלמיד בשיעורו הראשון את ההוראה "סע לכתובת זו" מכיוון שהתלמיד לא יודע כיצד לבצע זאת.

הוא ייתן לו סדרת הוראות לביצוע תת-משימה זו:

התנע את הקטנוע
שחרר את הבלם
הכנס להילוך
החל לנסוע
בצומת הקרובה פנה ימינה
...

באופן דומה, בהגדרת אלגוריתם ליצירת תכנית מחשב יש לקחת בחשבון אילו הוראות בסיסיות קיימות בשפת התכנות המיועדת.

אלגוריתמים כתכנון תכנית מחשב

אלגוריתמים משמשים להגדרה מקדימה, לפני כתיבת תכנית המחשב, למשימה הנדרשת לביצוע.

את הוראות האלגוריתם ניתן לרשום באופן טקסטואלי, בדומה להכנת מתכון לבישול, ע"י תרשים זרימה,  או בכל צורה אחרת.

לדוגמא, נתונה המשימה הבאה:

כתוב/י תכנית שתקרא מהקלט 3 מספרים, תחשב ותדפיס את הממוצע שלהם.

ננסה להגדיר את האלגוריתם לביצוע המשימה:

קרא 3 מספרים מהקלט
חשב את סכום שלושת המספרים
חלק את הסכום ב- 3
הדפס את התוצאה

האם האלגוריתם מוביל לביצוע המשימה? ראשית, נבדוק אם הוראותיו מובנות בשפת התכנות המיועדת:

  • ההוראה "קרא 3 מספרים מהקלט" היא אינה הוראה בסיסית ויש להגדירה ביתר פירוט - יש לציין את שמות תאי הזיכרון שלתוכם ייקלטו המספרים.
תאי זיכרון אלו נקראים משתנים מכיוון שערכם יכול להשתנות במהלך התכנית. את המשתנים נגדיר בתחילת האלגוריתם:
משתנים:      num1, num2, num3 - משתני הקלט
קרא מספר ראשון מהקלט לתוך num1
קרא מספר שני מהקלט לתוך num2
קרא מספר שלישי מהקלט לתוך num3
  • ההוראה "חשב את סכום שלושת המספרים" היא הוראה חשבונית בסיסית מובנת,  אולם יש לציין היכן לשמור את הסכום שחושב, כלומר באיזה תא זיכרון או באיזה משתנה.
לשם כך, נגדיר משתנה נוסף
                   avg - משתנה התוצאה

ונגדיר את ההוראה במפורט:

חשב את הסכום של num1 ,num2 ,num3 והצב אותו ב- avg
  • ההוראה "חלק את הסכום ב- 3" גם היא הוראה הדורשת פירוט בהתייחס למשתנים:
חלק את avg ב- 3 והצב את התוצאה ב- avg
  • גם את ההוראה "הדפס את התוצאה" נרשום באופן מפורש:
הדפס את avg

נכתוב שוב את האלגוריתם במלואו:

משתנים:      num1, num2, num3 - משתני הקלט
                                   avg - משתנה התוצאה
קרא מספר ראשון מהקלט לתוך num1
קרא מספר שני מהקלט לתוך num2
קרא מספר שלישי מהקלט לתוך num3
חשב את הסכום של num1, num2, num3 והצב אותו ב- avg
חלק את avg ב- 3 והצב את התוצאה ב- avg
הדפס את avg


תרשים האלגוריתם:

האם הוראות האלגוריתם הן חד-משמעיות? התשובה לכך שוב תלויה בשפת התכנות: בהגדרת המשתנים לא צוין סוג המספר - ממשי או שלם - ולכן היא איננה חד-משמעית בשפת תכנות המפרידה בין טיפוס מספרים שלם לבין ממשי.

נכתוב שוב את האלגוריתם, תוך ציון הטיפוס המספרי של המשתנים: משתני הקלט יהיו ממשפחת השלמים.

משתנה התוצאה, avg, צריך להיות ממשי מכיוון שהוא מכיל ממוצע, וזה בדרך כלל אינו ערך שלם.

משתנים:      num1, num2, num3 - משתני הקלט, שלמים
                                   avg - משתנה התוצאה, ממשי
קרא מספר ראשון מהקלט לתוך num1
קרא מספר שני מהקלט לתוך num2
קרא מספר שלישי מהקלט לתוך num3
חשב את הסכום של num1, num2, num3 והצב אותו ב- avg
חלק את avg ב- 3 והצב את התוצאה ב- avg
הדפס את avg

כעת האלגוריתם מוגדר היטב עבור שפות תכנות עיליות.

דוגמא שנייה: מציאת המקסימום מבין 3 מספרים

נדרש לחשב את המקסימום מבין 3 מספרים שלמים הנתונים מהקלט ולהדפיסו.

1) אלגוריתם טקסטואלי:

משתנים: x, y, z - משתני קלט, מטיפוס שלם
                   max - משתנה התוצאה, מטיפוס שלם
קלוט את שלושת המספרים לתוך המשתנים x,y,z
אם x גדול מ- y :
             אם x גדול מ- z  הצב ל- max את x
             אחרת, הצב ל- max את z
אחרת:
             אם y גדול מ- z  הצב ל- max את y
             אחרת, הצב ל- max את z
הדפס את max


2) אלגוריתם ע"י תרשים זרימה:

3) אלגוריתם ע"י פסאודו-קוד:

Integer x,y, z, max

read x, y, z

if x > y

if x > z

                max <-- x

else

                max <-- z

else

                if y > z

                                max <-- y

                else

                                max <-- z

print max

פירוק האלגוריתם למשימות משנה

תהליך הגדרת האלגוריתם מתחיל בהגדרת המשימה הכללית לביצוע כמשפט בשפת אנוש המתאר את המטרה הכללית של התכנית.

משפט זה בדרך כלל מופשט וכללי מדי להבנה ע"י המחשב. בהגדרת הוראות האלגוריתם, יש לקחת בחשבון אילו הוראות בסיסיות ניתנות לביצוע ע"י המחשב, ולאילו נדרשת הגדרה מפורטת יותר.

כל הוראה מורכבת שאינה "מובנת" דיה ע"י המחשב ניתנת לפירוק באחד משלושה אופנים:

    1. פירוק לסדרת הוראות משנה
    2. פירוק כמשפט תנאי
    3. פירוק כלולאה

תהליך הפירוק ממשיך באופן רקורסיבי עד להגעה להוראות ברמת שפת התכנות שאיתה מממשים את האלגוריתם.

כמו כן, במהלך הפירוק צצות בעיות ונקודות הדורשות הגדרות נוספות, כגון:

  - הגדרות משתנים, קבועים וטיפוסים
  - אתחול המשתנים

משפטי תנאי ולולאות הם מרכיבים בסיסיים בכל שפת תכנות עילית, ולעתים תכופות נכתבים באופן שמזכיר שפת אנוש.

דוגמא שלישית: אלגוריתם למציאת ערך מקסימום בקלט

כדוגמא נוספת להגדרת אלגוריתם ולפירוקו נגדיר את המשימה הבאה:

כתוב תכנית שתקרא מהקלט סדרת מספרים שלמים, ותדפיס את המספר בעל הערך המקסימלי מביניהם.

1) נבצע פירוק של המשימה הכללית ללולאה:

משתנים: x - המספר הנוכחי שנקרא מהקלט
כל עוד נקרא מספר מהקלט לתוך x  בהצלחה
             אם x גדול מהמספר המקסימלי שנקרא הצב אותו למספר המקסימלי
הדפס את המספר המקסימלי

כפי שניתן לראות, המשימה הכללית תורגמה למבנה לולאה הכוללת תנאי לביצוע הלולאה ושתי הוראות לביצוע בגוף הלולאה, ולאחריה הוראת הדפסה של המספר המקסימלי.

תנאי הלולאה הוא הצלחה בקריאת מספר לתוך המשתנה x: במצב זה אם המשתמש יקליד תו לא חוקי, או תו מסיים קובץ במקום מספר, הלולאה תסתיים.



2) נמשיך ונפרק את משימות המשנה:

  - תנאי הלולאה "כל עוד נקרא מספר מהקלט לתוך x  בהצלחה" מתורגם להצלחה בפעולת הקלט של מספר שלם לתוך x.
  - הוראת הבדיקה "אם x גדול מהמספר המקסימלי שנקרא עד כה הצב אותו למספר המקסימלי" מפורקת כמשפט תנאי.
    בנוסף, נדרשת הגדרת משתנה max שישמור את הערך המקסימלי בכל שלב. max ייבדק לעומת המספר הנקרא, x, ואם x גדול יותר - יקבל את ערכו.
  - ההוראה "הדפס את המספר המקסימלי" היא הוראת פלט בסיסית ולכן אין צורך להמשיך ולפרקה.


האלגוריתם:

משתנים: max - שלם המייצג את המספר המקסימלי שנקרא עד כה,
                   x - המספר הנוכחי שנקרא מהקלט
כל עוד נקרא מספר מהקלט לתוך x  בהצלחה
                   אם x גדול מ- max 
                                   הצב ל- max את x
הדפס את max

מהתבוננות שנייה באלגוריתם, ניתן לראות שישנה בעיה: max אינו מאותחל. זה עלול לגרום להדפסת תוצאה שגויה, ולכן התכנית אינה תקינה. לאיזה ערך נאתחל  את max ? קיימות שתי אפשרויות:

  1. למספר השלם המינימלי האפשרי
  2. למספר הראשון הנקרא מהקלט

לשם הפשטות נבחר בשיטה השנייה.

3) האלגוריתם בתוספת הוראת האתחול ל- max מובא בעמ' 112.

בעיה: כיצד תגיב התכנית במקרה של קלט ריק, כלומר 0 מספרים בקלט? כרגע תגובת התכנית לא מוגדרת, מה שאומר שיודפס ערך לא הגיוני. יש לתקן אותה כך שתודפס הודעה מתאימה במקרה זה.

פתרון: נוסיף בדיקה באתחול המשתנה max מהקלט: רק אם פעולת הקלט הצליחה, נבצע את הלולאה ונדפיס לאחריה את ערכו של max. אחרת, נדפיס הודעה למשתמש על קלט ריק.

4) האלגוריתם בצירוף טיפול בקלט ריק מובא בעמ' 112.



[ <<< הקודם ] [ תוכן עניינים ]