פיתוח חומרי עזר למורה - מרכז המורים הארצי למדעי המחשב

‫משרד החינוך‬
‫המזכירות הפדגוגית – אגף מדעים‬
‫הטכניון – מכון טכנולוגי לישראל‬
‫מרכז המורים הארצי למדעי המחשב‬
‫מינהלת מל"מ‪ ,‬המרכז הישראלי‬
‫לחינוך מדעי טכנולוגי ע"ש עמוס דה שליט‬
‫פיתוח‪:‬‬
‫משתתפי קורס מורים מובילים תשע"ה‬
‫פרויקט ‪ 8‬פיתוח חומרי עזר "מבני נתונים" (‪ 200‬עמודים)‬
‫מרכז מורים ארצי במקצוע מדעי המחשב‪ .‬הפרויקט מבוצע עפ"י מכרז ‪.9/7.2013‬‬
‫הפרויקט מבוצע עבור האגף לתכנון ופיתוח תוכניות לימודים‪ ,‬המזכירות הפדגוגית‪ ,‬משרד החינוך‬
‫יצא לאור במימון ובפיקוח המזכירות הפדגוגית‪ ,‬אגף מדעים במשרד החינוך‬
‫ומינהלת מל"מ‪ ,‬המרכז הישראלי לחינוך מדעי טכנולוגי ע"ש עמוס דה‪-‬שליט‬
‫© כל הזכויות שמורות למשרד החינוך‬
‫א‪ .‬מעבדות‬
‫משחק החיים‪ :‬מעבדה לסיכום מערך דו ממדי של עצמים ‪2 ...................................................‬‬
‫רקורסיה‪ :‬מבוא והכרות בסיסית ‪17 .........................................................................................................‬‬
‫דף עבודה רקורסיה ‪34 ....................................................................................................................................‬‬
‫פעולות שלא מחזירות ערך ‪35 ...........................................................................................................................‬‬
‫פעולות שמחזירות ערך ‪44 ..................................................................................................................................‬‬
‫מחלקת חוליה ושרשרת חוליות ‪52 ..........................................................................................................‬‬
‫שרשרת חוליות ‪64 ............................................................................................................................................‬‬
‫מערך של רשימות (שרשרת חוליות) ‪67 ................................................................................................‬‬
‫מחסנית ‪70 ............................................................................................................................................................‬‬
‫מחלקת שירות‪ :‬רשימה מקושרת של מספרים ‪88 ............................................................................‬‬
‫ב‪ .‬דפים מדורגים‬
‫מיון מיזוג‪ :‬דפים מדורגים ‪151 ...................................................................................................................‬‬
‫שמונה מלכות‪ :‬דפים מדורגים ‪156 ...........................................................................................................‬‬
‫ב‪ .‬התאמת שאלות לתכנית הלימודים החדשה במבני נתונים ‪161 ...........................................‬‬
‫‪-1-‬‬
‫משחק החיים‪ :‬מעבדה לסיכום נושא מערך דו ממדי של עצמים‬
‫פיתוח‪ :‬דפנה לוי‪-‬רשתי‪ ,‬חיה עידן‬
‫המעבדה מיועדת לתלמידים אשר סיימו את פרק הלימוד של מערך דו מימדי לפי התוכנית החדשה‪ .‬ליצירת‬
‫עניין‪ ,‬קיים שימוש בגרפיקה וב‪.windowsForm -‬‬
‫עבודה זו עוסקת במשחק החיים‪ ,‬שהוא אחת הגרסאות המפורסמות ביותר לאוטומט תאי דו‪-‬מימדי‪.‬‬
‫‪ .1‬השכלה כללית ‪ -‬למורה‬
‫ליבו של המדע המודרני‪ ,‬שתחילתו לפני כ‪ 300-‬שנים‪ ,‬נעוץ בניסיון לבסס את המודלים המדעיים על משוואות‬
‫מתמטיות‪ .‬משוואה היא אכן דבר נוח מאוד כאשר מדובר במערכת פשוטה יחסית‪ ,‬אך כאשר מדובר במערכת‬
‫מורכבת שהתהליכים בתוכה מצריכים רמה מסוימת של חישוב‪ ,‬הניסיון לתאר את ההתנהגות במספר‬
‫חישובים קטן‪ ,‬נועד לכישלון‪.‬‬
‫במקום להסתכל על מערכת ולנסות לזהות את המשוואה המתמטית שמתארת אותה‪ ,‬יש לאתר תוכנית תייצר‬
‫את התנהגות המערכת‪ .‬תוכנית כזו מכונה אוטומט תאי )‪.(*)(Cellular Automata‬‬
‫אוטומט תאי הוא מודל הנחקר במסגרת תורת החישוביות‪ ,‬מתמטיקה וביולוגיה תיאורטית‪ .‬הוא כולל סריג של‬
‫תאים‪ ,‬שלכל אחד מהם מספר סופי של מצבים‪ .‬הזמן במודל הוא בדיד‪ ,‬ומצבו של כל תא בזמן נתון ‪ t‬הוא‬
‫פונקציה של מצבו ומצב תאים אחרים (שכניו של התא הנתון) בזמן ‪ .t-1‬פונקציה זו חלה על כל התאים‪ ,‬כלומר כל‬
‫התאים משתנים על‪-‬פי אותה מערכת של כללים‪ .‬כל הפעלה של הפונקציה על כל התאים בסריג יוצרת דור חדש‪.‬‬
‫(*) זו אינה הדוגמה היחידה לתכנית כזו‬
‫‪-2-‬‬
‫האוטומט התאי מדגים כיצד ממספר מצומצם של חוקים ניתן ליצור תופעות מורכבות ובלתי צפויות וכיצד‬
‫מכמות מועטה של אינפורמציה ניתן לייצר תהליכי התפתחות ו "חיים" דינאמיים‪.‬‬
‫אוטומטים ראשונים מהסוג הזה נבנו מתוך מחשבה לחקות חיים בעזרת תוכנית מחשב‪ ,‬ובהם כל משבצת על‬
‫המסך סימנה "תא"‪ ,‬ולכן הם זכו לשם אוטומטים תאיים‪.‬‬
‫‪ .2‬משחק החיים‬
‫בשנת ‪ 1970‬המציא המתמטיקאי ג'ון קונויי את האוטומט התאי המפורסם ביותר‪ ,‬משחק החיים‪ .‬משחק‬
‫החיים זכה לפופולריות רבה מאוד בקרב מתמטיקאים‪ ,‬מתכנתים וחובבי שעשועי מתמטיקה‪ ,‬במידה רבה‬
‫בזכות סדרת מאמרים מאת מרטין גרדנר אודותם‪ ,‬שפורסמה בירחון ‪ .American Scientific‬בין השאר התגלו‬
‫באוטומט זה צורות המראות התנהגויות מורכבות ומענינות‪.1‬‬
‫התגלה שהאוטומט שקול למכונת טיורינג‪ ,‬כלומר כל חישוב שניתן לבצע על מחשב כלשהו ניתן לביצוע בעזרת‬
‫משחק החיים‪ ,‬הועלו השערות בקשר לשאלה האם אכן ניתן לייצר חיים‪ ,‬והאם ניתן לייצר יצורים חושבים‬
‫בעזרת המשחק‪ .‬השימושים הורחבו גם לנושאים שונים בביולוגיה‪ ,‬פיסיקה‪ ,‬כימיה ‪ ,‬כאוס ועוד‪.‬‬
‫המשחק מתחיל ממצב התחלתי כלשהו‪ ,‬היכול להיקבע על ידי המשתמש‪.‬‬
‫לכל תא ערך בינארי חי או מת‪ .‬מצב לוח מכונה "דור"‪.‬‬
‫בכל "דור" נולדים‪ ,‬מתים ושורדים תאים‪ ,‬לפי הכללים הבאים‪:‬‬
‫לידה – תא מת ייוולד מחדש אם יש לו‬
‫בדיוק שלושה שכנים חיים‪.‬‬
‫מוות – תא חי ימות בשני מקרים‪:‬‬
‫‪‬‬
‫אם יש לו שכן חי אחד או פחות‬
‫– התא ימות מבדידות‪,‬‬
‫או‬
‫‪‬‬
‫אם יש לו ארבעה שכנים חיים‬
‫או יותר – התא ימות מצפיפות‬
‫יתר‪.‬‬
‫הישרדות – תא חי ישרוד אם יש לו שניים‬
‫או שלושה שכנים חיים‪ .‬ברור כי תא מת‬
‫יישאר מת אם לא הייתה לו סיבה‬
‫להיוולד‪.‬‬
‫‪http://www.math.com/students/wonders/life/life.html 1‬‬
‫‪-3-‬‬
‫(לתלמיד)‬
‫‪ .1‬מהם העצמים להם אנו זקוקים במשחק? פרט את העצמים ותכונותיהם‪ .‬תכנן את המחלקות‬
‫הרלבנטיות‪.‬‬
‫(למורה)‬
‫תכנון מחלקת לוח‪CellsGrid :‬‬
‫‪public class CellsGrid‬‬
‫{‬
‫;‪private int rowsNum‬‬
‫;‪private Cell[,] world‬‬
‫;‪private int generationNum‬‬
‫}…‬
‫בחרנו לייצג את העולם כמטריצה ריבועית של תאים‪.‬‬
‫מכאן נגזרו תכונות המחלקה‪ :‬גודל המערך‪ ,‬המערך עצמו‪ ,‬ומספר הדור‪.‬‬
‫תאי המטריצה קיבלו מספר סידורי בודד‪ ,‬בנוסף למספר שורה ומספר עמודה‪ ,‬לתרגול עבודה במטריצה ולגישה‬
‫קלה יותר ללוח הגרפי‪ ,‬לדוגמה בלוח ‪:4*4‬‬
‫‪3‬‬
‫‪2‬‬
‫‪1‬‬
‫‪0‬‬
‫‪7‬‬
‫‪6‬‬
‫‪5‬‬
‫‪4‬‬
‫‪10 11‬‬
‫‪9‬‬
‫‪8‬‬
‫‪14 15‬‬
‫‪13‬‬
‫‪12‬‬
‫תכנון מחלקת תא‪Cell :‬‬
‫לעצם מטיפוס תא‪ 4 ,‬תכונות ‪ :‬מספר שורה‪ ,‬מספר עמודה‪ ,‬מספר סידורי ‪ -‬מטיפוס שלמים‪ ,‬ותכונה בוליאנית‪,‬‬
‫האם התא חי או מת‪.‬‬
‫לבד מפעולות מאחזרות‪ ,‬יש צורך בפעולה קובעת המחיה‪/‬ממיתה את התא‪ ,‬ובפעולה חישובית‪ ,‬האם התא יחיה‬
‫או ימות בדור הבא‪ ,‬על פי מספר שכניו‪.‬‬
‫‪public class Cell‬‬
‫{‬
‫;‪private int rowIndex‬‬
‫;‪private int colIndex‬‬
‫;‪private bool isAlive‬‬
‫;‪private int serial‬‬
‫}…‬
‫(לתלמיד)‬
‫‪ .2‬א‪.‬‬
‫כתוב את מחלקת ‪ .Cell‬תשומת ליבך לפעולה הבונה‪ ,‬פעולות מאחזרות וקובעות (האם צריך‬
‫כאלו לכל התכונות?)‪.‬‬
‫‪-4-‬‬
‫הוסף פעולה המקבלת את מספר השכנים של התא‪ ,‬ומחשבת האם התא יחיה או ימות בדור‬
‫ב‪.‬‬
‫הבא‪ .‬הפעולה תחזיר אמת אם התא יהיה חי‪ ,‬אחרת תחזיר שקר‪.‬‬
‫‪ .3‬במחלקת ‪ ,CellsGrid‬כתוב את תכונות המחלקה ואת הפעולות הבאות‪:‬‬
‫א‪ .‬פעולה בונה המקבלת את גודל העולם (אורך הצלע) ובונה עולם דור ראשון‪ ,‬בו מספר התאים‬
‫החיים הוא בין חמישית מספר התאים בעולם לשליש מספר התאים בעולם‪ .‬התאים החיים‬
‫ימוקמו רנדומלית בעולם‪.‬‬
‫חלק את עבודתך למשימות משנה‪.‬‬
‫ב‪ .‬פעולה בונה המקבלת את הדור הקודם (עצם מטיפוס ‪ )CellsGrid‬ובונה את הדור הבא‪ ,‬על פי כללי‬
‫המשחק‪.‬‬
‫ג‪ .‬פעולה המקבלת תא ומחזירה את מספר שכניו החיים‪.‬‬
‫(למורה – ניתן לתת לתלמיד ממשק למימוש‪) :‬‬
‫פעולה בונה‪ .‬הפעולה מקבלת את גודל העולם (אורך הצלע) ובונה את הדור‬
‫הראשון‪.‬‬
‫פעולה בונה‪ .‬הפעולה מקבלת עצם מטיפוס ‪ CellsGrid‬המייצג את הדור‬
‫הקודם‪ ,‬ובונה עצם המייצג את הדור שאחריו‪.‬‬
‫פעולה המחזירה את מספר התאים החיים בדור הראשון‪ .‬מספר התאים החיים‬
‫יהיה בין חמישית לשליש מספר התאים בעולם‪.‬‬
‫פעולה המפזרת את התאים החיים בדור הראשון באופן רנדומלי במטריצת‬
‫העולם‪.‬‬
‫פעולה המקבלת תא ומחזירה את מספר השכנים החיים שיש לו‪.‬‬
‫פעולות קובעות‪/‬מאחזרות (האם יש צורך לכל התכונות?)‬
‫(לתלמיד)‬
‫‪ .4‬תכנן ובנה את הטופס הראשי ‪ -‬חלון המשחק הראשי‪ .‬שנה את שם הטופס ל‪.LifeForm :‬‬
‫לטופס יש להוסיף (באמצעות גרירה) את הפקדים הבאים‪:‬‬
‫‪‬‬
‫התחלת משחק‪ :‬כפתור התחל – אשר יתחיל את המשחק‬
‫‪‬‬
‫מספר דורות לחישוב קדימה‪ :‬תיבת טקסט – בה יקליד המשתמש את מספר הדורות הרצוי לו‪ ,‬ותווית‬
‫אשר תבקש מהמשתמש להכניס את מספר הדורות המבוקש‪ .‬ערך ברירת המחדל בתיבת הטקסט יהיה ‪.1‬‬
‫‪‬‬
‫דור נוכחי‪ :‬שתי תוויות‪ :‬האחת תציין כי התווית השניה מציגה את מספר הדור והאחרת מציגה את‬
‫מספר הדור‪.‬‬
‫‪-5-‬‬
‫יש להשאיר מקום מספיק לשרטוט העולם‪ :‬שרטוט זה לא יעשה על ידי גרירה‪ ,‬אלא בבנייה ישירה במחלקת‬
‫הטופס‪.‬‬
‫עצב את הטופס והפקדים כרצונך (צבעים‪ ,‬פונטים‪ ,‬כותרות וכו')‪.‬‬
‫(למורה)‬
‫אם הכיתה אינה מכירה ה‪ – windowsForm -‬ניתן להוריד מהרשת את המצגת של זהבה יעקובסון‪ :‬תכנות‬
‫חלונאי‪.‬‬
‫(לתלמיד)‬
‫‪ .5‬בטופס הראשי‪ ,‬יש להוסיף את תמונות התאים‪ .‬ניתן לבחור בכל פקד מתאים‪ .‬אנו בחרנו לשרטט כל‬
‫תא ככפתור‪ ,‬שצבעו נגזר מחייו‪ .‬אם התא חי – צבע הכפתור יהיה שחור‪ .‬אם מת – צבע הכפתור יהיה‬
‫לבן‪ .‬לא הגדרנו‪ ,‬כמובן‪ ,‬פעולת קליק לכפתורים המסמנים תאים‪.‬‬
‫תכונות הטופס‪:‬‬
‫גודל העולם‬
‫קואורדינטה ‪ X‬של "תמונת" התא הראשון‬
‫קואורדינטה ‪ Y‬של "תמונת" התא הראשון‬
‫גודל "תמונת" התא‬
‫עצם מטיפוס ‪ – CellsGrid‬המייצג את הדור הנוכחי‬
‫מערך דו מימדי של פקדים מטיפוס כפתורים‪ ,‬המייצגים את הלוח הגרפי‬
‫‪-6-‬‬
:‫ אשר בונה את מטריצת הכפתורים המייצגים את התאים‬,BuildBtns() ‫נתונה הפעולה‬
private void BuildBtns()
{
Cell[,] world = this.cg.GetWorld();
this.graficWorld = new System.Windows.Forms.Button[rowsNum, rowsNum];
int n = 0;
for (int i = 0; i < rowsNum; i++)
{
for (int j = 0; j < rowsNum; j++)
{
graficWorld[i, j] = new System.Windows.Forms.Button();
graficWorld[i, j].Width = picSide; // Width of button
graficWorld[i, j].Height = picSide; // Height of button
graficWorld[i, j].Left = xPos + picSide * j;
graficWorld[i, j].Top = yPos + picSide * i;
graficWorld[i, j].Tag = n++;
if (world[i, j].GetIsAlive()) graficWorld[i, j].BackColor = Color.Black;
else graficWorld[i, j].BackColor = Color.White;
graficWorld[i, j].Enabled = false;
graficWorld[i, j].Visible = true;
this.Controls.Add(graficWorld[i, j]);
}
}
}
.‫ כתוב את תכונות הטופס‬.‫א‬
.‫ לבניית הלוח הגרפי‬,BuildBtns() ‫ המשתמשת בפעולה‬,‫ כתוב את הפעולה הבונה של הטופס‬.‫ב‬
‫ ומשנה את צבע התאים‬,‫ המשנה את טקטס תווית מספר הדור לדור הנוכחי‬,CangeBtns() ‫ כתוב את הפעולה‬.‫ג‬
.‫בהתאם לדור הנוכחי‬
.‫ הוסף את פעולת הקליק לכפתור ההתחל‬.‫ד‬
.‫ יחושבו מספר דורות בהתאם לכתוב בתיבת הטקסט שבטופס‬,‫בלחיצה על כפתור זה‬
.CangeBtns() ‫ תוך שימוש בפעולת‬,‫ ולעדכן את הלוח‬,‫ יש לייצר עצם חדש‬,‫לכל דור חדש‬
:‫זכור להשתמש בפעולות‬
-7-
this.Refresh();
System.Threading.Thread.Sleep(2000);
.‫ לבניית הלוח הגרפי‬,BuildBtns() ‫ המשתמשת בפעולה‬,‫ כתוב את הפעולה הבונה של הטופס‬.‫ה‬
.Run ‫ והעבר אותו כפרמטר בפעולה‬,CellsGrid ‫ בנה עצם חדש מטיפוס‬,Program ‫ במחלקת‬.6
:‫התוכנית המלאה‬
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace GameOfLife
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
CellsGrid cg = new CellsGrid(50);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new LifeForm(cg));
}
}
}
//----------------------------------------------------------------using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
-8-
namespace GameOfLife
{
public class Cell
{
private int rowIndex;
private int colIndex;
private bool isAlive;
private int serial;
public Cell(int rowsNum, int row, int col, bool alive)
{
this.rowIndex = row;
this.colIndex = col;
this.serial = rowsNum * row + col;
this.isAlive = alive;
}
public int GetRow()
{
return this.rowIndex;
}
public int GetCol()
{
return this.colIndex;
}
public int GetSerial()
{
return this.serial;
}
public bool GetIsAlive()
{
return this.isAlive;
}
-9-
public bool WillBeAlive(int neighborsNum)
{
if (neighborsNum == 3)
return true;
else
if ((neighborsNum == 2) && this.isAlive)
return true;
else
return false;
}
public void SetIsAlive(bool boolVal)
{
this.isAlive = boolVal;
}
}
}
//-----------------------------------------------------------------using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace GameOfLife
{
public class CellsGrid
{
private int rowsNum;
private Cell[,] world;
private int generationNum;
public CellsGrid(int rowsNum) // first generation CellsGrid
{
this.rowsNum = rowsNum;
this.generationNum = 0;
Cell[,] world = new Cell[rowsNum, rowsNum];
- 10 -
for (int i = 0; i < rowsNum; i++)
{
for (int j = 0; j < rowsNum; j++)
{
Cell c = new Cell(rowsNum, i, j, false);
world[i, j] = c;
}
}
this.PutBugsRnd(world);
}
private int bugsNum()
{
int num1 = (rowsNum * rowsNum) / 5;
int num2 = (rowsNum * rowsNum) / 3;
Random rnd = new Random();
return rnd.Next(num1, num2);
}
private void PutBugsRnd(Cell[,]cells)
{
int bugs;
bugs = this.bugsNum();
Random rnd = new Random();
while (bugs > 0)
{
int i = rnd.Next(0, rowsNum-1);
int j = rnd.Next(0, rowsNum-1);
if (!(cells[i, j].GetIsAlive()))
{
cells[i, j].SetIsAlive(true);
bugs--;
}
}
this.world = cells;
}
- 11 -
public CellsGrid(CellsGrid cg) // next generation CellsGrid
{
this.rowsNum = cg.rowsNum;
this.generationNum = cg.GetGenerationNum() + 1;
Cell[,] cells = new Cell[rowsNum, rowsNum];
for (int i = 0; i < rowsNum; i++)
{
for (int j = 0; j < rowsNum; j++)
{
Cell oldCell = cg.GetWorld()[i, j];
int count = cg.neighborsCount(oldCell);
Cell c = new Cell(rowsNum, i, j, oldCell.WillBeAlive(count));
cells[i, j] = c;
}
}
this.world = cells;
}
public int GetRowsNum()
{
return this.rowsNum;
}
public void SetRowsNum(int r)
{
this.rowsNum = r;
}
public int GetGenerationNum()
{
return this.generationNum;
}
public void SetGenerationNum(int gn)
{
this.generationNum = gn;
}
- 12 -
public Cell[,] GetWorld()
{
return this.world;
}
public int neighborsCount(Cell c)
{
int count = 0;
int row = c.GetRow();
int col = c.GetCol();
for (int i = row - 1 ; i <= row + 1; i++)
{
for (int j = col - 1 ; j <= col + 1 ; j++)
{
if ((i >= 0) && (i < this.rowsNum) &&
(j >= 0) && (j < this.rowsNum) &&
(!((i == row) && (j == col))))
{
if (this.world[i, j].GetIsAlive()) count++;
}
}
}
return count;
}
}
}
//-----------------------------------------------------------------using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
- 13 -
namespace GameOfLife
{
public partial class LifeForm : Form
{
int rowsNum;
int xPos = 20;
int yPos = 70;
int picSide = 15;
CellsGrid cg;
Button[,] graficWorld;
public LifeForm()
{
InitializeComponent();
}
public LifeForm(CellsGrid cg)
{
this.rowsNum = cg.GetRowsNum();
this.cg = cg;
BuildBtns();
InitializeComponent();
}
//The following procedure to create matrix of buttons:
private void BuildBtns()
{
Cell[,] world = this.cg.GetWorld();
this.graficWorld = new System.Windows.Forms.Button[rowsNum, rowsNum];
int n = 0;
for (int i = 0; i < rowsNum; i++)
{
for (int j = 0; j < rowsNum; j++)
{
// Initialize one variable
graficWorld[i, j] = new System.Windows.Forms.Button();
- 14 -
graficWorld[i, j].Width = picSide; // Width of button
graficWorld[i, j].Height = picSide; // Height of button
graficWorld[i, j].Left = xPos + picSide * j;
graficWorld[i, j].Top = yPos + picSide * i;
graficWorld[i, j].Tag = n++;
if (world[i, j].GetIsAlive())
graficWorld[i, j].BackColor = Color.Black;
else
graficWorld[i, j].BackColor = Color.White;
graficWorld[i, j].Enabled = false;
graficWorld[i, j].Visible = true;
this.Controls.Add(graficWorld[i, j]);
}
}
}
private void ChangeBtns()
{
this.numLbl.Text = cg.GetGenerationNum().ToString();
this.Refresh();
for (int i = 0; i < rowsNum; i++)
{
for (int j = 0; j < rowsNum; j++)
{
if (this.cg.GetWorld()[i,j].GetIsAlive())
graficWorld[i, j].BackColor = Color.Black;
else
graficWorld[i, j].BackColor = Color.White;
graficWorld[i, j].Visible = true;
}
}
}
- 15 -
private void button1_Click(object sender, EventArgs e)
{
int iters = Int32.Parse(this.iterTb.Text);
for (int i = 0; i < iters; i++)
{
CellsGrid newCg = new CellsGrid(cg);
this.cg = newCg;
this.ChangeBtns();
this.Refresh();
System.Threading.Thread.Sleep(2000);
}
if (button1.Text == "Start")
button1.Text = "Next";
}
}
}
- 16 -
‫רקורסיה‪ :‬מבוא והכרות בסיסית‬
‫פיתוח‪ :‬יוסי זהבי וישראל אברמוביץ‬
‫המעבדה מיועדת לתלמידים הלומדים בסביבת ‪ C#‬והיא מותאמת לסביבת ‪Visual Studio‬‬
‫תרגיל ‪1‬‬
‫מבקר במפעל מסוים אמור לחשב את סה"כ הוצאות השכר החודשיות במפעל‪ ,‬הוא מגלה שיש ‪ 8‬דרגות במקום העבודה‪.‬‬
‫כל עובד מדורג מ ‪ , A‬העובד הכי בכיר‪ ,‬עד ‪ H‬העובדים הכי זוטרים‪.‬‬
‫העובדים באו אל המבקר בסדר מהבכירים עד לזוטרים‬
‫כאשר הוא שאל מהי הדרגה והמשכורת של העובד העובד ענה את דרגתו ולא ענה מה משכורתו אלא אמר שמשכורתו‬
‫גדולה ב ‪ 100‬ש"ח מהעובדים שבדרגה אחת נמוכה יותר‪.‬‬
‫א‪ .‬האם בדרך זו יכול המבקר לדעת מה סה"כ הוצאות השכר החודשיות של המפעל?‬
‫________________________________________________________‬
‫ב‪ .‬אנא הסבר תשובתך‪:‬‬
‫________________________________________________________‬
‫________________________________________________________‬
‫בעקבות התנהלות העובדים ניתנה הוראה לעשות זאת שוב באותו הסדר‪ ,‬והפעם יש לומר למבקר את המשכורת‪ .‬אולם‪,‬‬
‫רק העובדים הזוטרים (בדרגה ‪ )H‬צייתו להוראה (כל השאר ענו בדיוק כמו בפעם הראשונה)‪.‬‬
‫ג‪ .‬האם הפעם יכול המבקר לדעת מה הן הוצאות השכר החודשיות בכל המפעל ?‬
‫________________________________________________________‬
‫ד‪ .‬אנא הסבר תשובתך _________________________________________‬
‫________________________________________________________‬
‫________________________________________________________‬
‫ה‪ .‬כפי שבוודאי ענית‪ ,‬הפעם יש למבקר את היכולת לחשב את הוצאות השכר‪ .‬האם תוכל לומר באיזה שלב זה קרה ?‬
‫(באיזה שלב במהלך התישאול השני יש למבקר את היכולת לחשב את כל הוצאות השכר במפעל)‬
‫________________________________________________________‬
‫________________________________________________________‬
‫ו‪ .‬הסבר כיצד המבקר יחשב את הוצאות השכר אם רק דרגה ‪ H‬אומרת את משכורתה ?‬
‫________________________________________________________‬
‫________________________________________________________‬
‫ז‪ .‬האם יש דרך לחשב את משכורת המנהל הראשי (דרגה ‪ )A‬לפני שמחשבים את כל הדרגות שמתחתיו? מדוע ?‬
‫________________________________________________________‬
‫________________________________________________________‬
‫‪- 17 -‬‬
‫תרגיל ‪2‬‬
‫התבונן בשלושת התרשימים הבאים ‪:‬‬
‫‪.A‬‬
‫‪.B‬‬
‫‪.C‬‬
‫א‪ .‬תן שם לקבוצה שישקף את המשותף לשלושת התרשימים‪.‬‬
‫________________________________________________________‬
‫ב‪ .‬כתוב תיאור לקבוצה ‪_______________________________________ :‬‬
‫________________________________________________________‬
‫ג‪ .‬נסה להוסיף עוד ‪ 2‬פריטים המתאימים לקבוצה‪______________________ .‬‬
‫________________________________________________________‬
‫‪- 18 -‬‬
‫תרגיל ‪3‬‬
‫התבונן בשלושת הצורות הבאות ‪:‬‬
‫‪.A‬‬
‫‪.B‬‬
‫‪C‬‬
‫‪.‬‬
‫‪- 19 -‬‬
‫א‪ .‬תן שם לקבוצה שישקף את המשותף לשלושתם‪.‬‬
‫________________________________________________________‬
‫ב‪ .‬כתוב תיאור לקבוצה ‪_______________________________________ :‬‬
‫________________________________________________________‬
‫________________________________________________________‬
‫ג‪ .‬נסה להוסיף עוד פריט או שניים המתאימים לקבוצה‪.‬‬
‫________________________________________________________‬
‫________________________________________________________‬
‫תרגיל ‪.4‬‬
‫קרא את שלושת המשפטים הבאים‪:‬‬
‫‪ .A‬מיהו יהודי ? כל מי שאימו יהודיה‪.‬‬
‫‪ .B‬לשוק ההייטק יכול להיכנס רק מי שיש לו ניסיון בהייטק‪.‬‬
‫‪ .C‬היה היה אדם נדיב מאד שנתן את כל כספו לעניים עד שלא נותר לו אוכל ומת‪ .‬באו כל העניים ובנו לו מצבה ועל‬
‫המצבה הם כתבו‪ :‬היה היה אדם נדיב מאד שנתן את כל כספו לעניים עד שלא נותר לו אוכל ומת‪ .‬באו כל העניים ובנו‬
‫לו מצבה ועל המצבה הם כתבו‪ :‬היה היה אדם נדיב מאד שנתן את כל כספו לעניים עד שלא נותר לו אוכל ומת‪ .‬באו כל‬
‫העניים ובנו לו מצבה ועל המצבה הם כתבו‪ :‬היה היה אדם נדיב מאד שנתן את כל כספו לעניים עד שלא נותר לו אוכל‬
‫ומת‪ .‬באו כל העניים ובנו לו מצבה ועל המצבה הם כתבו‪ :‬היה היה אדם נדיב מאד שנתן את כל כספו לעניים עד שלא‬
‫נותר לו אוכל ומת‪ .‬באו כל העניים ובנו לו מצבה ועל המצבה הם כתבו‪ :‬היה היה אדם נדיב מאד שנתן את כל כספו‬
‫לעניים עד שלא נותר לו אוכל ומת‪ .‬באו כל העניים ובנו לו מצבה ועל המצבה הם כתבו‪ :‬היה היה אדם נדיב מאד שנתן‬
‫את כל כספו לעניים עד שלא נותר לו אוכל ומת‪ .‬באו כל העניים ובנו לו מצבה ועל המצבה הם כתבו‪:‬‬
‫א‪ .‬תן שם לקבוצה שישקף את המשותף לכולם‪.‬‬
‫________________________________________________________‬
‫ב‪ .‬כתוב תיאור לקבוצה ‪_______________________________________ :‬‬
‫________________________________________________________‬
‫ג‪ .‬נסה להוסיף עוד ‪ 2‬משפטים המתאימים לקבוצה‪.‬‬
‫________________________________________________________‬
‫________________________________________________________‬
‫________________________________________________________‬
‫‪- 20 -‬‬
‫סיכום ארבעת התרגילים‬
‫בארבעת התרגילים ראינו תופעות שמופע שלהם חוזר שוב ושוב‪ .‬לפעמים קטן יותר‪ ,‬לפעמים גדול יותר ולפעמים אותו‬
‫גודל ואין סופי‪.‬‬
‫לתופעה כזו אנו קוראים רקורסיה‪.‬‬
‫בתחום מדעי המחשב ניתן לבנות פעולות רקורסיביות העוזרות לנו להתמודד עם תופעות אלו‪.‬‬
‫הבה נבחן שלוש הגדרות שיעזרו לנו בהמשך ‪:‬‬
‫הגדרת הרקורסיה ‪ -‬רקורסיה היא תופעה שכל מופע שלה מכיל מופע נוסף שלה‪ ,‬כך שהיא מתרחשת ומשתקפת‬
‫בשלמותה בתוך עצמה שוב ושוב‪.‬‬
‫הגדרה רקורסיבית ‪ -‬היא הגדרת מושג באופן שמצריך פניה אל אותה הגדרה אבל בתנאים שונים‪ .‬לרוב‪ ,‬כדי לא‬
‫להיגרר לרקורסיה אינסופית הגדרה רקורסיבית תכלול גם תנאי עצירה‪.‬‬
‫אלגוריתם רקורסיבי ‪ -‬אלגוריתם רקורסיבי הפותר בעיה מורכבת מפעיל את עצמו על מופע פשוט יותר של הבעיה‬
‫שוב ושוב עד שהיא ניתנת לפתרון באופן פשוט (ישיר)‪.‬‬
‫ניתן לזהות ‪ 4‬אלמנטים החוזרים על עצמם באלגוריתם רקורסיבי הפותר בעיה ‪(.‬שאינו אין סופי)‬
‫‪ .1‬מקרה פשוט (תנאי עצירה)‬
‫‪ .2‬מקרה מורכב‬
‫‪ .3‬התכנסות מן המקרה המורכב אל המקרה הפשוט‪.‬‬
‫‪ .4‬קריאה רקורסיבית ‪ -‬כלומר הפעלה של הפעולה שוב ושוב‬
‫דוגמה‪:‬‬
‫ננסה לזהות את ארבעת המרכיבים האלו בתרגיל הראשון על המבקר והעובדים שענו שמשכורתם ‪ 100‬ש"ח יותר‬
‫ממעובד שהינו בדרגה הנמוכה להם (פרט לדרגה ‪ H‬שאמרו את משכורתם ישירות)‪.‬‬
‫‪ .1‬מקרה פשוט ‪ -‬משכורת של דרגה ‪H‬‬
‫‪ .2‬מקרה מורכב ‪ -‬משכורת של כל עובד שהוא לא בדרגה ‪. H‬‬
‫‪ .3‬התכנסות‪ -‬כל עובד אומר שמשכורות נמוכה מהמשכורת של העובד בדרגה אחת נמוכה יותר כך שבסוף נגיע בהכרח‬
‫לעובד בדרגה ‪.H‬‬
‫‪ .4‬קריאה רקורסיבית ‪ -‬משכורת של ‪ X‬שווה למשכורת של ‪. 100 + Y‬‬
‫‪- 21 -‬‬
‫בתרגיל הבא נתנסה בפתרון רקורסיבי וננסה לזהות את ארבעת המרכיבים‪.‬‬
‫תרגיל ‪.5‬‬
‫א‪ .‬המורה מבקש ממך לפתור את התרגיל ‪ 6‬כפול ‪ 5‬כיצד תפתור אותו כאשר אינך יכול להשתמש בפעולת הכפל עצמה‪.‬‬
‫___________________________________________________________‬
‫___________________________________________________________‬
‫ב‪ .‬אם לא הצלחת האם תצליח לבצע זאת ע"י ביצוע של פעולות חיבור ? _________‬
‫כיצד ?‬
‫___________________________________________________________‬
‫___________________________________________________________‬
‫עתה ננסה לפתור זאת בצורה רקורסיבית‪.‬‬
‫אם נדע מהו הפתרון של ‪ 6‬כפול ‪ 4‬האם נוכל לפתור את ‪ 6‬כפול ‪ 5‬באמצעות חיבור ? ___‬
‫כיצד ? __________________________________________‬
‫אבל מהו הפתרון של ‪ 6‬כפול ‪ ? 4‬אם נדע את ‪ 6‬כפול ‪ 3‬האם נוכל ? __כן ‪ /‬לא__‬
‫אבל מהו הפתרון של ‪ 6‬כפול ‪ ? 3‬אם נדע את ‪ 6‬כפול ‪ 2‬האם נוכל ? __כן ‪ /‬לא__‬
‫אבל מהו הפתרון של ‪ 6‬כפול ‪ ? 2‬אם נדע את ‪ 6‬כפול ‪ 1‬האם נוכל ? __כן ‪ /‬לא__‬
‫כאן נעצור‪..‬‬
‫אנו יודעים בוודאות שכל מספר כפול ‪ 1‬הוא המספר עצמו (המספר פעם אחת) את זה אין צורך לבקש ממישהו שיעשה‬
‫זאת בשבילי‪.‬‬
‫האם גילינו דרך לפתור את ‪ 6‬כפול ‪ 5‬באמצעות אלגוריתם רקורסיבי ? __________‬
‫ננסה לזהות בתרגיל שעשינו את ‪ 4‬המרכיבים שתיארנו קודם‬
‫הסבר מהו המקרה הפשוט ‪___________________________________ :‬‬
‫הסבר מהו המקרה המורכב ‪___________________________________ :‬‬
‫הסבר מהי ההתכנסות‪_______________________________________ :‬‬
‫הסבר מהי הקריאה הרקורסיבית החוזרת על עצמה שוב ושוב‪.‬‬
‫_______________________________________________________‬
‫_______________________________________________________‬
‫עתה נבנה לבעיה אלגוריתם רקורסיבי ‪.‬‬
‫‪- 22 -‬‬
‫אלגוריתם לכפל של ‪ X‬כפול ‪ P‬פעמים‪.‬‬
‫שם הפעולה‪" :‬בצע כפל של (המספר ‪ P , X‬פעמים)"‪.‬‬
‫אם ‪ P‬שווה ‪1‬‬
‫החזר כתשובה את ‪.X‬‬
‫אחרת‬
‫החזר כתשובה את ‪" + X‬בצע כפל של (המספר ‪ P -1 , X‬פעמים)"‪.‬‬
‫המר את האלגוריתם לפעולה והרץ ‪ .‬אם לא הצלחת הפתרון במסגרת בכתב בצבע לבן‬
‫)‪public static int Mul(int x, int p‬‬
‫{‬
‫)‪if (p == 0‬‬
‫;‪return 0‬‬
‫)‪else if (p == 1‬‬
‫;‪return x‬‬
‫;)‪return x + Mul(x, p - 1‬‬
‫}‬
‫בחן את האלגוריתם ‪( .‬האם זה עובד גם במקרי קצה ‪ , 0 ,‬מספרים שליליים אם לא תקן)‬
‫מה יקרה אם ‪ P‬יהיה שלילי ? מדוע ?‬
‫_______________________________________________________‬
‫_______________________________________________________‬
‫האלגוריתם הרקורסיבי מנצל תכונה מיוחדת במחשב המסוגלת לבצע פעולה בתוך פעולה תוך שמירה על ההקשר הנכון‬
‫בכל אחת מהקריאות לפעולה‪.‬‬
‫כאן גם המקום לציין שהמחשב משתמש במשאבי הזיכרון (מחסנית המחשב) בכל פעם שישנה קריאה לפעולה ‪.‬‬
‫כמובן שאם הרקורסיה היא אין סופית המחשב יגיע למגבלת המשאבים שלו ויקרוס‪.‬‬
‫לכן‬
‫א‪ .‬חשוב לבנות פתרון המתכנס בוודאות אל המקרה הפשוט (ולדוגמה ‪ ,‬לא מדלג עליו)‬
‫ב‪ .‬חשוב להבין שלפעמים אין מספיק משאבים למחשב כדי לפתור בעיה מסוימת‪.‬‬
‫‪- 23 -‬‬
‫תרגיל ‪ - 6‬עצרת‬
‫נגדיר עתה עצרת ‪( factorial‬מסומנת בסימן ! )‬
‫עצרת של מספר ‪ X‬היא תוצאת הכפל של כל המספרים השלמים מ ‪ 1‬עד ל ‪X‬‬
‫לדוגמה עצרת של המספר ‪ 5‬היא ‪120 = 5*4*3*2*1 120‬‬
‫אקסיומה ‪ :‬עצרת של ‪ 1‬היא ‪ 1‬וגם עצרת של ‪ 0‬היא ‪.1‬‬
‫ניתן להגדיר עצרת בצורה רקורסיבית‪:‬‬
‫נסה להגדיר _______________________________________‬
‫לאחר שהגדרת שנה את צבע השורה שבמסגרת הבאה לשחור כדי לבחון את תשובתך‪:‬‬
‫עצרת של ‪ X‬היא ‪ X " :‬כפול העצרת של ‪. "X - 1‬‬
‫על פי ההגדרה הרקורסיבית ניתן לכתוב פעולת מחשב המחשבת את העצרת בצורה רקורסיבית‬
‫השלם את הפעולה הרקורסיבית הבאה המחזירה את ערך העצרת של ‪.X‬‬
‫)‪static void Main(string[] args‬‬
‫{‬
‫;)‪int fact = Factorial(6‬‬
‫;)‪Console.WriteLine(" The Factorial of 6 is :" + fact‬‬
‫}‬
‫)‪public static int Factorial(int x‬‬
‫{‬
‫) ______ || ______( ‪if‬‬
‫; ______ ‪return‬‬
‫;) ________( ____________ * _______ ‪return‬‬
‫}‬
‫לאחר השלמת הפעולה מצא וכתוב את ‪ 4‬האלמנטים הקיימים בכל אלגוריתם רקורסיבי‪.‬‬
‫הסבר מהו המקרה הפשוט ‪___________________________________ :‬‬
‫הסבר מהו המקרה המורכב ‪___________________________________ :‬‬
‫הסבר מהי ההתכנסות‪_______________________________________ :‬‬
‫הסבר מהי הקריאה הרקורסיבית החוזרת על עצמה שוב ושוב‪.‬‬
‫_______________________________________________________‬
‫_______________________________________________________‬
‫‪- 24 -‬‬
‫נא בדוק וכתוב מה הערך החוזר מהערכים הבאים ‪ ,17 ,13 ,12 ,10 ,6 ,4 ,1, 0,‬ו ‪40‬‬
‫__?__ = )‪Factoral(0‬‬
‫__?__ = )‪Factoral(1‬‬
‫__?__ = )‪Factoral(4‬‬
‫__?__ = )‪Factoral(6‬‬
‫__?__ = )‪Factoral(10‬‬
‫__?__ = )‪Factoral(12‬‬
‫__?__ = )‪Factoral(13‬‬
‫__?__ = )‪Factoral(17‬‬
‫__?__ = )‪Factoral(40‬‬
‫מדוע לדעתך קיבלת ערך לא נכון ב ‪ 17 13‬ו‪( 40 -‬השווה במחשבון)‪.‬‬
‫___________________________________________‬
‫___________________________________________‬
‫הורד את שתי השורות הראשונות בפעולה ‪ Factorial‬כך שתישאר שורה אחת בלבד בפעולה ‪.‬‬
‫הרץ ‪ .‬מה קרה ? מדוע ? _____________________________________‬
‫כיצד כותבים פעולה רקורסיבית‪" .‬טיפ"‬
‫כאשר אתה מזהה שיש פתרון רקורסיבי לבעיה (לרוב בגלל ההגדרה הרקורסיבית של הבעיה) הדרך לכתוב את הפתרון‬
‫הרקורסיבי היא‪:‬‬
‫‪ )1‬מצא את תנאי העצירה ופתור אותו (די פשוט)‬
‫‪ )2‬אמור לעצמך " "קשה לי למצוא את ‪ f‬של ‪X‬‬
‫אבל אם אדע כמה זה ‪ f‬של "קרוב של ‪ "X‬אעשה ‪ P‬ואז אפתור את ‪ f‬של ‪" X‬‬
‫בדרך כלל משפט זה יעזור לך לבנות את הפתרון הרקורסיבי המורכב‪.‬‬
‫‪ P‬מציין פעולה התלויה בבעיה עצמה (לדוגמה בעצרת זה היה הכפול)‪.‬‬
‫‪- 25 -‬‬
‫תרגיל ‪ 7‬חזקה‬
‫ניתן להגדיר רקורסיבית את פעולה החזקה כך‪:‬‬
‫חזקה של ‪ X‬במעריך ‪ Y‬היא ‪:‬‬
‫‪ X‬כפול‬
‫"‪ X‬בחזקת המעריך (‪ Y‬פחות‪" )1‬‬
‫א‪ .‬כתוב אלגוריתם רקורסיבי לפעולת החזקה‪.‬‬
‫ב‪ .‬כתוב פעולה רקורסיבית על סמך האלגוריתם ‪ -‬הרץ ובדוק‪.‬‬
‫תרגיל ‪ - 8‬הדפסת מספר במהופך‬
‫המטרה להדפיס מספר בצורה הפוכה לדוגמה את המספר ‪ 2015‬להדפיס כך ‪5102 :‬‬
‫ניתן להגדיר את הפתרון בעזרת האלגוריתם הרקורסיבי הבא‪.‬‬
‫פעולת "הדפס במהופך את ‪"X‬‬
‫אם יש רק ספרה אחת הדפס אותה אם לא הדפס את ספרת האחדות וקרא לפעולה "הדפס במהופך את ‪ " X‬עם ‪X‬‬
‫מחולק בעשר (כלומר ללא ספרת האחדות שכבר הודפסה)‬
‫הסבר מהו המקרה הפשוט ‪___________________________________ :‬‬
‫הסבר מהו המקרה המורכב ‪___________________________________ :‬‬
‫הסבר מהי ההתכנסות‪_______________________________________ :‬‬
‫הסבר מהי הקריאה הרקורסיבית החוזרת על עצמה שוב ושוב‪.‬‬
‫_______________________________________________________‬
‫_______________________________________________________‬
‫פסאודו קוד‪:‬‬
‫הדפס‪-‬במהופך (‪)n‬‬
‫אם ‪ ,n<10‬הדפס את ‪n‬‬
‫אחרת‪ :‬הדפס את ‪( n%10‬השארית של חלוקת ‪ n‬ב‪(10-‬‬
‫זמֵן את הדפס‪-‬במהופך (‪)n/10‬‬
‫לפניך חלק מהפתרון‪ ,‬השלם את הפעולה ‪:‬‬
‫‪- 26 -‬‬
‫)‪public static void ReverseNum(int n‬‬
‫{‬
‫)תנאי עצירה ( ‪if‬‬
‫;) __ (‪Console.Write‬‬
‫‪else‬‬
‫{‬
‫;)‪Console.Write(n%10‬‬
‫;) קריאה עם ערך קרוב ל ‪ n‬שמתכנס אל עבר תנאי העצירה (‪ReverseNum‬‬
‫}‬
‫}‬
‫הרץ ובדוק‪.‬‬
‫תרגיל ‪ 9‬פיבונאצ'י‬
‫מתוך ויקיפדיה ‪:‬‬
‫סדרת פיבונאצ'י קרויה על שם לאונרדו מפיזה הידוע בכינוי "פיבונאצ'י"‪.‬‬
‫פיבונאצ'י השתמש בסדרה כדי לתאר את מספר הצאצאים של זוג ארנבים אחד‪ ,‬אם מניחים שכל זוג ארנבים שהגיע‬
‫לגיל חודשיים‪ ,‬ממליט מדי חודש זוג נוסף ‪.‬באוכלוסייה כזו‪ ,‬מספר זוגות הארנבים בחודש ה ‪-n‬יהיה שווה ל‪.‬‬
‫‪-‬‬
‫למעט הסדרות החשבוניות וההנדסיות‪ ,‬ושילובים שלהן‪ ,‬סדרת פיבונאצ'י היא הדוגמה הפשוטה ביותר לסדרה המוגדרת‬
‫ברקורסיה‪.‬‬
‫למספרי פיבונאצ'י יש תכונות רבות ומעניינות‪.‬‬
‫ספרים שלמים נכתבו עליהם ואף קיים כתב עת מתמטי )‪ (Fibonacci quarterly‬שמוקדש כולו לתגליות במספרי‬
‫פיבונאצ'י והכללות שלהם‪ .‬כמו כן‪ ,‬נוסדה אגודת פיבונאצ'י שמטרתה לגלות מופעים חדשים של סדרת פיבונאצ'י‪.‬‬
‫נגדיר עתה איבר בסדרה ‪ -‬איבר בסדרת פיבונאצ'י הינו סכום של שני האיברים הקודמים לו בסדרה‪.‬‬
‫אקסיומה ‪ :‬האיבר הראשון בסדרה הינו ‪ 1‬והשני הינו גם ‪.1‬‬
‫לדוגמה האיבר השישי בסדרה הינו ‪8‬‬
‫(עשרת האיברים הראשונים בסדרה ‪) 1,1,2,3,5,8,13,21,34,55‬‬
‫‪ .A‬כיצד נבנה אלגוריתם רקורסיבי המחזיר את ערך האיבר ה‪ X -‬בסדרה?‬
‫(למי שנתקל בקשיים יש עזרה ב סעיף ‪).C‬‬
‫הסבר מהו המקרה הפשוט ‪___________________________________ :‬‬
‫הסבר מהו המקרה המורכב ‪___________________________________ :‬‬
‫הסבר מהי ההתכנסות‪_______________________________________ :‬‬
‫‪- 27 -‬‬
‫הסבר מהי הקריאה הרקורסיבית החוזרת על עצמה שוב ושוב‪.‬‬
‫_______________________________________________________‬
‫_______________________________________________________‬
‫‪ .B‬בנה פעולה בשם ‪ . Fibonacci‬הרץ ובדוק בלולאה את עשרת האיברים הראשונים‪.‬‬
‫‪ .C‬אם לא הצלחת‪ ,‬נסה בדרך הבאה‪ .‬אמור " איני יודע מהו האיבר ה ‪ n‬של פיבונאצ'י אבל אם אדע את האיבר ה ‪n‬‬
‫פחות אחד של פיבונאצ'י וגם את האיבר ה ‪ n‬פחות שתיים של פיבונאצ'י אחבר בניהם וזאת התוצאה"‬
‫כלומר פיבונאצ'י ‪ n‬הינו חיבור בין פיבנאצי'י ‪ n -1‬ופיבונאצ'י ‪. n-2‬‬
‫‪ .D‬האם מבנה הרקורסיה דומה לפעולות שלמדת בתרגילים הקודמים‬
‫מה דומה ? ____________________________________________‬
‫____________________________________________________‬
‫‪ .E‬מה שונה ? ____________________________________________‬
‫____________________________________________________‬
‫סוגי רקורסיות‪.‬‬
‫ישנם כמה סוגי רקורסיה‬
‫‪ .1‬רקורסיית זנב ‪ -‬רקורסיה לינארית שיש בה הקריאה הרקורסיבית היא הדבר האחרון שמתרחש‪.‬‬
‫ישנה רק קריאה רקורסיבית אחת בגוף הפעולה‪( .‬רקורסיות כמו חזקה‪ ,‬עצרת‪ ,‬כפל‪ ,‬הדפס במהופך שלמדנו)‬
‫‪ .2‬רקורסיה מרובה ‪ -‬ברקורסיה מרובה ישנה יותר מקריאה אחת רקורסיבית בגוף הפעולה‪.‬‬
‫‪ .3‬רקורסיה הדדית ‪ -‬רקורסיה בה פעולה לא קוראת לעצמה אלא לפעולה אחרת שבתוכה יש קריאה לפעולה הראשונה‪.‬‬
‫‪ .F‬מצא את סוג הקריאה הרקורסיבית בתרגיל פיבונאצ'י (תרגיל ‪)9‬‬
‫‪- 28 -‬‬
‫תרגיל ‪ .10‬רקורסיה במחרוזות ‪ -‬האם מחרוזת היא פולינדרום‪.‬‬
‫במחרוזות לרוב נבצע קריאה רקורסיבית עם מחרוזות קרובות (יותר גדולות או יותר קטנות) עד להגעה למקרה‬
‫הקצה‪.‬‬
‫לפניך פעולה המקבלת מחרוזת ומחזירה 'אמת' אם המחרוזת הנתונה היא פלינדרום‪ ,‬ו‪'-‬שקר' אחרת‪ .‬פלינדרום מוגדר כך‬
‫שהחצי הימני של המחרוזת הינו תמונת מראה של החצי השמאלי ‪.‬‬
‫לדוגמה פולינדרום בעל מספר אי זוגי של תוים "‪"dcdamadcd‬‬
‫)‪public static bool Palindrome (string str‬‬
‫{‬
‫)‪if (str.Length <= 1‬‬
‫;‪return true‬‬
‫)]‪if (str[0] != str[str.Length – 1‬‬
‫;‪return false‬‬
‫;))‪return Palindrome (str.Substring(1, str.Length - 2‬‬
‫}‬
‫בתרגיל זה עליך לדבג ‪Debug‬‬
‫נא שים נקודת עצירה בשורה הראשונה של הפעולה ובדוק את ערכו של ‪ str‬בכל פעם שמגיעים לשורה זו‪.‬‬
‫קרא לפעולה עם הערך שבדוגמה "‪"dcdamadcd‬‬
‫עליך למלא את הטבלה הבאה‬
‫מספר הכניסה לפעולה‬
‫‪1‬‬
‫‪2‬‬
‫‪3‬‬
‫‪4‬‬
‫‪5‬‬
‫‪6‬‬
‫‪7‬‬
‫ערך חוזר ‪true/false‬‬
‫ערכו של ‪str‬‬
‫מדוע כמות הכניסות אינה קרובה לאורך המחרוזת ? __________________________‬
‫נסה לנסח כמה פעמים הפעולה תקרא לעצמה‬
‫_____________________________‬
‫‪- 29 -‬‬
‫בצע זאת שוב עם המחרוזת "‪"abcdbba‬‬
‫מספר הכניסה לפעולה‬
‫‪1‬‬
‫‪2‬‬
‫‪3‬‬
‫‪4‬‬
‫‪5‬‬
‫‪6‬‬
‫‪7‬‬
‫ערך חוזר ‪true/false‬‬
‫ערכו של ‪str‬‬
‫הרץ שוב עם מחרוזת ריקה‪ ,‬מחרוזת באורך אחד‪ ,‬ומחרוזת באורך זוגי‪.‬‬
‫ורשום מסקנותיך לגבי כל הרצה‪.‬‬
‫‪__________________________________________________________ .1‬‬
‫‪__________________________________________________________ .2‬‬
‫‪__________________________________________________________ .3‬‬
‫תרגיל ‪ .11‬רקורסיה במערכים ‪ -‬מציאת ערך מקסימאלי‪.‬‬
‫ברקורסיה במערכים לרוב נשלח אינדקסים ‪ low‬ו ‪ high‬או ‪ begin‬ו ‪ end‬כפרמטרים לרקורסיה כדי להתייחס לתת‬
‫מערך בכל פעם‪.‬‬
‫המשימה ‪:‬עליך למצוא את האיבר המקסימלי במערך שאיבריו הינם בסדר אקראי ולא ממוין‪.‬‬
‫עליך לבצע זאת באמצעות קריאה רקורסיבית מרובה על פי הרעיון הבא‪:‬‬
‫האיבר הכי גדול במערך הינו האיבר הגדול יותר מבין האיבר המקסימלי בכל חצי מערך (תת מערך)‪.‬‬
‫המקרה הפשוט ‪" -‬אם אורך תת המערך שווה ‪ 1‬האיבר הינו המקסימאלי"‬
‫המקרה המורכב (נא השלם) ‪ -‬חלק את המערך לשניים וקרא לפעולה שוב עם שני החצאים‪.‬‬
‫כשתקבל את שני הערכים הגבוהים שבכל חצי בצע ______________________‬
‫והחזר את ___________________________________________________‪.‬‬
‫‪- 30 -‬‬
‫השלם את החסר בפעולה‬
‫)‪public static int FindMax (int[] arr, int begin, int end‬‬
‫{‬
‫)‪if (begin == end‬‬
‫;]‪return arr[begin‬‬
‫‪else‬‬
‫{‬
‫;‪int middle = (begin + end) / 2‬‬
‫;)‪int max1 = FindMax (arr, begin, middle‬‬
‫;)‪int max2 = FindMax (arr, middle+1, end‬‬
‫) ________ ( ‪if‬‬
‫;‪return max1‬‬
‫;‪return max2‬‬
‫}‬
‫}‬
‫הרץ ובדוק‪.‬‬
‫כיצד תתבצע הקריאה הראשונה‬
‫;))‪Console.WriteLine(FindMax(arr,0,arr.Length -1‬‬
‫לבסןף הוסף את השורה הבאה בשורה הראשונה של הפעולה (לפני ה ‪)if‬‬
‫;) ‪Console.WriteLine("begin=" + begin + " end=" + end‬‬
‫כמה פעמים תודפס שורה זו ? מדוע ?___________________________________‬
‫_____________________________________________________________‬
‫בדוק‪.‬‬
‫תרגיל ‪ - 12‬המחשת חוזקה של הרקורסיה‬
‫עד כה למדנו רקורסיות פשוטות שברוב במקרים ניתן לפתור אותן גם בפיתרון איטראטיבי (באמצעות לולאה ) וברוב‬
‫המקרים הפתרון יהיה יותר זול במונחים של זמן תכנות‪ ,‬זמן ביצוע וצריכת משאבי זיכרון‪.‬‬
‫אם כן מדוע המבנה המפותל של הרקורסיה עוזר לנו?‬
‫לבעיות שהגדרתן היא רקורסיבית‪ ,‬לרוב‪ ,‬ניתן לבנות פתרון הרבה יותר פשוט והרבה יותר מהיר ברקורסיה מאשר‬
‫פתרון בלולאה‪.‬‬
‫בתרגיל מסכם זה ננסה להראות כיצד פתרון רקורסיבי הינו אינטואיטיבי וקל עשרות מונים על פני פתרון בלולאות‪.‬‬
‫‪- 31 -‬‬
‫תרגיל כמה מדליות יש במשפחה‬
‫נתון המערך ‪ M‬המכיל ‪ N‬שורות ושלוש עמודות‬
‫‪// 0‬‬
‫‪// 1‬‬
‫‪// 2‬‬
‫‪// 3‬‬
‫‪// 4‬‬
‫‪// 5‬‬
‫‪// 6‬‬
‫‪// 7‬‬
‫‪// 8‬‬
‫‪// 9‬‬
‫‪// 10‬‬
‫}‪int [ , ] M = { {-1 ,4,-1‬‬
‫‪{ -1, 5 , -1},‬‬
‫‪{ 8 , 2 , 1 },‬‬
‫‪{ 4 , 1 , -1},‬‬
‫‪{ -1, 8 , -1},‬‬
‫‪{ 7 , 3 , -1},‬‬
‫‪{ 2 , 8 , 4 },‬‬
‫‪{ -1, 6 , -1},‬‬
‫‪{ 10 , 2 , 5 },‬‬
‫}‪{ -1, 2 , -1‬‬
‫}‪{ -1, 0 , -1‬‬
‫;}‬
‫המערך מייצג את כמות המדליות שצברו אנשים שונים בתחרויות שונות וברמות שונות‪ :‬סבים‪ ,‬אבות‪ ,‬בנים‪ ,‬נכדים‪,‬‬
‫נינים וכו' לכל רמה יכולים להיות עד שני בנים‪.‬‬
‫הערך בעמודה המרכזית (אינדקס ‪ )1‬מייצג את כמות המדליות שצבר בן משפחה מסויים ואילו הערכים בעמודות ‪ 0‬ו ‪2‬‬
‫מציינים את השורות במערך בהם נמצאים הבנים של אותה רמה‪( .‬לשם הנוחות נקרא להם בן שמאלי ובן ימני)‬
‫לדוגמה‪ ,‬אם ראש המשפחה הוא בשורה ‪ 6‬הוא צבר בחייו ‪ 8‬מדליות ושני בניו נמצאים בשורות ‪ 4‬ו ‪.2‬‬
‫הערך ‪ -1‬מציין שלרמה זו אין בן ( כלומר אין רמה נמוכה יותר לדוגמה לשורה ‪ 5‬יש רק בן שמאלי אחד בשורה ‪.)7‬‬
‫המשימה ‪ :‬חשב את סכום המדליות שצבר ראש המשפחה (בשורה אינדקס ‪ ) 6‬יחד עם כל צאצאיו בכל הרמות‪.‬‬
‫שים לב לא כל השורות "שייכות" למשפחה המתחילה בשורה ‪ .6‬לדוגמה שורה ‪. 9‬‬
‫א‪ .‬נסה לפתור בעיה זו בדרך הרגילה (לא רקורסיבית) במשך כמה דקות‪.‬‬
‫ב‪ .‬בהנחה שלא הצלחת או שהיה קשה נסה לבנות פתרון רקורסיבי‬
‫עזרה ‪:‬‬
‫הסבר מהו המקרה הפשוט ‪___________________________________ :‬‬
‫הסבר מהו המקרה המורכב ‪___________________________________ :‬‬
‫הסבר מהי ההתכנסות‪_______________________________________ :‬‬
‫הסבר מהי הקריאה הרקורסיבית החוזרת על עצמה שוב ושוב‪.‬‬
‫_______________________________________________________‬
‫_______________________________________________________‬
‫‪- 32 -‬‬
‫אלגוריתם רקורסיבי הפותר את הבעיה‪.‬‬
‫שם הפעולה ‪" :‬סכֹום מדליות של שורה ‪"X‬‬
‫אם הגענו לשורה ‪-1‬‬
‫החזר ‪0‬‬
‫אחרת‬
‫החזר את הערך של השורה הנוכחית ועוד הקריאה ל "סכֹום מדליות של שורה שרשומה בתא ‪( "0‬בן שמאלי)‬
‫ועוד "סכֹום מדליות של שורה שרשומה בתא ‪( "1‬בן ימני)‬
‫כתוב את הפעולה הרץ ובדוק‪.‬‬
‫הפתרון במסגרת באותיות בצבע לבן‬
‫)‪public static int SumRec(int[,] M, int row‬‬
‫}‬
‫)‪if (row == -1‬‬
‫;‪return 0‬‬
‫;)]‪return M[row,1] + SumRec(M, M[row,0]) + SumRec(M, M[row,2‬‬
‫{‬
‫פתרונות‬
‫שאלה ‪5‬‬
‫)‪public static int Mul(int x, int p‬‬
‫{‬
‫)‪if (p == 0‬‬
‫;‪return 0‬‬
‫)‪else if (p == 1‬‬
‫;‪return x‬‬
‫;)‪return x + Mul(x, p - 1‬‬
‫}‬
‫שאלה ‪ - 6‬עצרת של ‪ X‬היא ‪ X " :‬כפול העצרת של ‪. "X - 1‬‬
‫תרגיל ‪12‬‬
‫)‪public static int SumRec(int[,] M, int row‬‬
‫}‬
‫)‪if (row == -1‬‬
‫;‪return 0‬‬
‫;)]‪return M[row,1] + SumRec(M, M[row,0]) + SumRec(M, M[row,2‬‬
‫{‬
‫‪- 33 -‬‬
‫דף עבודה ‪ -‬רקורסיה‬
‫פיתוח‪ :‬דפנה מינסטר ושרה פונק‬
‫‪‬‬
‫קּור ִסיָּ ה – הנחיות לתלמיד‬
‫דף עבודה – ֵר ְ‬
‫‪‬‬
‫*********************************************************‬
‫‪.1‬‬
‫פתח‪/‬י פרוייקט חדש בשם ‪.PrjRec‬‬
‫‪.2‬‬
‫פתח‪/‬י מחלקה בשם ‪ Rec1‬בה תממש‪/‬י את כל הפעולות הרשומות בדף מספר ‪.1‬‬
‫‪.3‬‬
‫פתח‪/‬י מחלקה בשם ‪ TestRec1‬בה תממש‪/‬י פעולה ראשית אשר תזמן את כל הפעולות שמימשת‬
‫בסעיף ‪ 2‬והרץ‪/‬י אותה‪.‬‬
‫‪.4‬‬
‫פתח‪/‬י מחלקה בשם ‪ Rec2‬בה תממש‪/‬י את כל הפעולות הרשומות בדף מספר ‪.2‬‬
‫‪.5‬‬
‫פתח‪/‬י מחלקה בשם ‪ TestRec2‬בה תממש‪/‬י פעולה ראשית אשר תזמן את כל הפעולות שמימשת‬
‫בסעיף ‪ 4‬והרץ‪/‬י אותה‪.‬‬
‫שים‪/‬י לב ♥ ‪ -‬הסימן * ליד מספר התרגיל מציין תרגיל רשות‬
‫‪- 34 -‬‬
‫‪‬‬
‫קּור ִסיָּ ה – פעולות שלא מחזירות ערך‬
‫דף עבודה מס' ‪ֵ – 1‬ר ְ‬
‫‪‬‬
‫************************************************************************‬
‫‪.1‬‬
‫לפניך פעולה בשפת ‪:JAVA‬‬
‫) ‪public static void series1 ( int n‬‬
‫{‬
‫‪//‬‬
‫הפעולה מקבלת מספר טבעי ‪. n‬‬
‫‪//‬‬
‫הפעולה מחשבת ‪. . . . . . . .‬‬
‫) ‪if ( n > = 10‬‬
‫; ) ‪System.out.print ( n‬‬
‫‪else‬‬
‫{‬
‫; ) " " ‪System.out.print ( n +‬‬
‫שורת הדפסה ‪‬‬
‫; ) ‪series1 ( n + 1‬‬
‫}‬
‫}‬
‫לפניך תכנית ראשית בשפת ‪:JAVA‬‬
‫) ‪public static void main ( String [ ] args‬‬
‫{‬
‫; ) ‪series1 ( 1‬‬
‫}‬
‫א‪.‬‬
‫נסה ‪/‬י לעקוב אחר ביצוע התכנית הראשית‪ ,‬רשום‪/‬י מהו הפלט שיתקבל לדעתך‪:‬‬
‫ב‪.‬‬
‫כעת בדק‪/‬י בעזרת הרצה במחשב מהו הפלט ?‬
‫ג‪.‬‬
‫____________________________________________________‬
‫הרץ ‪/‬י את התכנית עבור הקלטים הבאים‪ ,‬ורשום ‪/‬י את הפלט בטבלה הבאה‪:‬‬
‫פלט‬
‫‪mis2‬‬
‫; ) ‪series1 ( 2‬‬
‫; ) ‪series1 ( 7‬‬
‫; ) ‪series1 ( 10‬‬
‫; ) ‪series1 ( 11‬‬
‫‪- 35 -‬‬
‫ד‪.‬‬
‫בתכנית שלעיל מופיעה דרך חדשה‪.‬‬
‫נסה‪/‬י להסביר במילים את הדרך וכיצד היא מתבצעת‪.‬‬
‫__________________________________________________________ _________________________________________________‬
‫__________________________________________________________ _________________________________________________‬
‫__________________________________________________________ _________________________________________________‬
‫__________________________________________________________ _________________________________________________‬
‫__________________________________________________________ _________________________________________________‬
‫__________________________________________________________ _________________________________________________‬
‫‪.2‬‬
‫לפניך פעולה ‪ series2‬בשפת ‪:JAVA‬‬
‫שים‪/‬י לב! לשינוי ‪. . .‬‬
‫) ‪public static void series2 ( int n‬‬
‫{‬
‫) ‪if ( n > = 10‬‬
‫; ) ‪System.out.print ( n‬‬
‫‪else‬‬
‫{‬
‫; ) ‪series2 ( n + 1‬‬
‫; ) " " ‪System.out.print ( n +‬‬
‫}‬
‫}‬
‫שורת הדפסה ‪‬‬
‫א‪.‬‬
‫נסה ‪/‬י ל עקוב אחר ביצוע התכנית הראשית‪ ,‬רשום‪/‬י מהו הפלט שיתקבל לדעתך‪:‬‬
‫ב‪.‬‬
‫כעת בדק‪/‬י בעזרת הרצה במחשב מהו הפלט ?‬
‫ג‪.‬‬
‫מדוע ‪ ,‬לדעתך ‪ ,‬הגיב המחשב בצורה זו ?‬
‫____________________________________________________‬
‫__________________________________________________________ _________________________________________________‬
‫__________________________________________________________ _________________________________________________‬
‫ד‪.‬‬
‫הרץ ‪/‬י את התכנית עבור הקלטים הבאים‪ ,‬ורשום ‪/‬י את הפלט בטבלה הבאה‪:‬‬
‫פלט‬
‫‪mis2‬‬
‫; ) ‪series2 ( 2‬‬
‫; ) ‪series2 ( 7‬‬
‫; ) ‪series2 ( 10‬‬
‫; ) ‪series2 ( 11‬‬
‫‪- 36 -‬‬
‫ה‪ .‬מה יקרה אם נשנה את התנאי בפעולה שלפניך ל‪( n = = 10 ) -‬‬
‫ונריץ את התכנית הראשית עם הזימון‪? series2 ( 11 ) ; :‬‬
‫__________________________________________________________ _________________________________________________‬
‫__________________________________________________________ _________________________________________________‬
‫__________________________________________________________ _________________________________________________‬
‫הסבר‪/‬י ‪:‬‬
‫__________________________________________________________ _________________________________________________‬
‫__________________________________________________________ _________________________________________________‬
‫__________________________________________________________ _________________________________________________‬
‫הגדרה‪:‬‬
‫**************************************************************************‬
‫*‬
‫רקורסיה היא דרך חדשה לפתרון בעיות‪ .‬משימה שקוראת לעצמה‪.‬‬
‫*‬
‫**************************************************************************‬
‫תנאים לקיום רקורסיה‪:‬‬
‫‪.1‬‬
‫הליך רקורסיבי ‪ -‬תת‪-‬משימה המזמנת אותה תת‪-‬משימה‪ ,‬עבור ערך קטן‪/‬גדול יותר‪.‬‬
‫‪.2‬‬
‫תנאי עצירה – עוצר את פעולת הרקורסיה‬
‫(היעדרו של תנאי עצירה יוביל לחזרה אינסופית של הרקורסיה)‪.‬‬
‫הרקורסיה מייצרת שני מצבים‪:‬‬
‫‪.1‬‬
‫שלב פתיחת הרקורסיה – הפעולות המתבצעות לפני הזימון הרקורסיבי (עד תנאי העצירה)‪.‬‬
‫הערכים מעובדים בסדר רגיל‪.‬‬
‫‪.2‬‬
‫שלב סגירת הרקורסיה – הפעולות המתבצעות לאחר הזימון הרקורסיבי‪.‬‬
‫הערכים מעובדים בסדר הפוך‪.‬‬
‫‪- 37 -‬‬
‫דוגמה לתרגיל‪:‬‬
‫) ‪public static void series ( int n‬‬
‫{‬
‫) ‪if ( n > = 7‬‬
‫; ) ‪System.out.print ( n‬‬
‫‪else‬‬
‫{‬
‫; ) " " ‪System.out.print ( n +‬‬
‫תנאי עצירה ‪‬‬
‫‪‬‬
‫שלב פתיחת הרקורסיה‬
‫הערכים מעובדים בסדר רגיל‬
‫זימון‪/‬קריאה רקורסיבית ‪‬‬
‫; ) ‪series ( n + 1‬‬
‫‪‬‬
‫; ) " " ‪System.out.print ( n +‬‬
‫שלב סגירת הרקורסיה‬
‫הערכים מעובדים בסדר הפוך‬
‫}‬
‫}‬
‫עבור הקלט‪ , n = 1 :‬ייתקבל הפלט‪:‬‬
‫‪123456 7 654321‬‬
‫סגירה‬
‫‪.3‬‬
‫‪‬‬
‫פתיחה‬
‫כתב‪/‬י פעולה רקורסיבית לכל אחת מהסדרות הבאות‪:‬‬
‫א‪.‬‬
‫‪1 , 4 , 7 , 10 , 13 , 16 , 19 , 22‬‬
‫(קיימים ‪ 2‬פתרונות שונים)‬
‫ב‪.‬‬
‫‪-10 , -9 , -8 , -7 , -6 , -5 , -4 , -3 , -2 , -1‬‬
‫(קיימים ‪ 2‬פתרונות שונים)‬
‫ג‪.‬‬
‫‪1,1,2,2,3,3,4,4,3,3,2,2,1,1‬‬
‫ד‪.‬‬
‫‪10 , 20 , 30 , 40 , 4 , 3 , 2 , 1‬‬
‫ה‪.‬‬
‫א‪,‬ב‪,‬ג‪,‬ד‪,‬ג‪,‬ב‪,‬א‬
‫ו‪.‬‬
‫‪1,2,3,4,5,6,7,8.9,8,6,4,2‬‬
‫‪- 38 -‬‬
‫‪.4‬‬
‫נתונות ‪ 2‬פעולות והזימון שלהן בתכנית הראשית‪:‬‬
‫) ‪public static void seriesB ( int n‬‬
‫{‬
‫) ‪if ( n > = 4‬‬
‫; ) " " ‪System.out.print ( n +‬‬
‫‪else‬‬
‫{‬
‫; ) ‪seriesB ( n + 1‬‬
‫; ) " " ‪System.out.print ( n +‬‬
‫}‬
‫}‬
‫הזימון‬
‫א‪.‬‬
‫) ‪public static void seriesA ( int n‬‬
‫{‬
‫) ‪if ( n < = 1‬‬
‫; ) " " ‪System.out.print ( n +‬‬
‫‪else‬‬
‫{‬
‫; ) " " ‪System.out.print ( n +‬‬
‫; ) ‪seriesA ( n - 1‬‬
‫}‬
‫}‬
‫הזימון‬
‫; ) ‪seriesB ( 1‬‬
‫; ) ‪seriesA ( 4‬‬
‫הסבר‪/‬י ב‪ 2-3 -‬שורות מה מבצעת הפעולה ‪:seriesA‬‬
‫________________________________________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫ב‪.‬‬
‫האם הפעולות הנ"ל יציגו פלט זהה ?‬
‫ג‪.‬‬
‫הסבר‪/‬י את ההבדל בין הפעולות הנ"ל‪:‬‬
‫_____________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫________________________________________________ ________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫*‪.5.5‬‬
‫חזר‪/‬י לתרגיל ‪ 3‬סעיפים א' ו‪ -‬ב' והוסף‪/‬י את הפתרון השני לסדרה‪.‬‬
‫‪.6‬‬
‫פעולה רקורסיבית שמזמנת פעולה רקורסיבית‪:‬‬
‫א‪.‬‬
‫כתב‪/‬י פעולה רקורסיבית בשם ‪ printStars‬המקבלת מספר שלם ‪ N‬ומדפיסה ‪ N‬כוכביות על‬
‫המסך (כתב‪/‬י פעולה במחלקה)‪.‬‬
‫ב‪.‬‬
‫כתב‪/‬י פעולה רקורסיבית בשם ‪ printRowStars‬המקבלת מספר שלם ‪ M‬ומדפיסה ‪ N‬שורות‬
‫של כוכביות על המסך‪ ,‬כאשר מספר הכוכביות בכל שורה גדל ב‪.1 -‬‬
‫‪‬‬
‫שים‪/‬י לב ! יש להשתמש בפעולה שכתבת בסעיף א'‪.‬‬
‫‪- 39 -‬‬
.printRowStars ‫ ומזמנת את הפעולה‬N ‫י תכנית ראשית הקולטת מספר שלם‬/‫כתב‬
:‫ ייתקבל הפלט‬, N = 6 ‫עבור הקלט‬
.‫ג‬
:‫דוגמה‬
*
**
***
****
*****
******
:6 ‫פתרון לתרגיל‬
public static void printStars ( int n )
{
if ( n < 1 )
System.out.println ( ) ;
else
{
System.out.print ( ' * ' ) ;
printStars ( n - 1 ) ;
}
}
public static void printRowStars ( int m )
{
if ( m > 1 )
System.out.print ( m + " " ) ;
else
{
printRowStars ( m - 1 ) ;
printStars ( m ) ;
}
}
.7
.‫ המדפיסה את לוח הכפל‬multiplicationTable ‫י פעולה רקורסיבית בשם‬/‫כתב‬
.‫משימות‬-‫ רצוי לחלק את המשימה לתת‬:‫רמז‬
:‫ בתכנית הראשית‬printA ‫ פעולות (אחת רקורסיבית) והזימון של הפעולה‬2 ‫נתונות‬
public static void print ( int[ ] A , int i )
{
if ( i > = A.length )
System.out.println ( " <-- ‫; ) " המערך‬
else
{
System.out.print ( A[ i ] + " " ) ;
print ( A , i + 1 ) ;
}
}
public static void printA ( int[ ] A )
{
print ( A , 0 ) ;
}
- 40 -

.8
‫; } ‪int [ ] a = { 1 , 2 , 3 , 4 , 5 , 6‬‬
‫הזימון בתכנית הראשית‪:‬‬
‫; ) ‪printA ( a‬‬
‫א‪.‬‬
‫מה יהיה הפלט של הזימון ; ) ‪? print ( A , 0‬‬
‫________________________________________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫ב‪.‬‬
‫הסבר‪/‬י ב‪ 2-3 -‬שורות מה מבצעת הפעולה ‪:print‬‬
‫________________________________________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫‪.9‬‬
‫כתב‪/‬י פתרון רקורסיבי נוסף לפעולה ‪( print‬מתרגיל ‪.)8‬‬
‫‪ .10‬נתונות ‪ 2‬פעולות והזימון שלהן בתכנית הראשית‪:‬‬
‫) ‪public static void printString1 ( String S , int L , int H‬‬
‫{‬
‫) ‪if ( L > H‬‬
‫; ) " " ( ‪System.out.print‬‬
‫‪else‬‬
‫) ‪if ( L = = H‬‬
‫; ) " " ‪System.out.print ( S.charAt( L ) +‬‬
‫‪else‬‬
‫{‬
‫; ) " " ‪System.out.print ( S.charAt( L ) + " " + S.charAt( H ) +‬‬
‫; ) ‪printString1 ( S , L + 1 , H - 1‬‬
‫}‬
‫}‬
‫‪‬‬
‫שים‪/‬י לב !‬
‫אסור לזמן את הפעולה הרקורסיבית עם ‪ L+ +‬או ‪, H- -‬‬
‫כי זו רקורסיה אינסופית‪.‬‬
‫; "‪String s = "123456‬‬
‫הזימון בתכנית הראשית‪:‬‬
‫; ) ‪printString1 ( s , 0 , s.length( ) – 1‬‬
‫‪- 41 -‬‬
public static void printString2 ( String S )
{
if (S.length( ) == 0 )
System.out.print ( " " ) ;
else
if ( S.length( ) = = 1 )
System.out.print ( S.charAt( 0 ) + " " ) ;
else
{
System.out.print ( S.charAt( 0 ) + " " + S.charAt( S.length( ) – 1 ) + " " ) ;
printString2 ( S.substring( 1 , S.length( ) – 1 ) ) ;
}
}
:‫הזימון בתכנית הראשית‬
String s = "123456" ;
printString2 ( s) ;
? printString1( s , 0 , s.length( ) – 1 ) ; ‫מה יהיה הפלט של הזימון‬
.‫א‬
__________________________________________________________________________________________________ ____
________________________________________________________________________________________________________
:‫ שורות מה מבצעת כל אחת מהפעולות הנ"ל‬2-3 -‫י ב‬/‫הסבר‬
.‫ב‬
________________________________________________________________________________________________________
________________________________________________________________________________________________________
__________________________________________________________ ______________________________________________
‫י תשובתך‬/‫ נמק‬,‫י את הדרך המועדפת עליך‬/‫בחר‬
.‫ג‬
________________________________________________________________________________________________________
________________________________________________________________________________________________________
________________________________________________________________________________________________________
- 42 -
:JAVA ‫ לפניך פעולה בשפת‬.11
public static void printM ( int [ ] [ ] mat , int i , int j )
{
if ( i > = mat.length )
System.out.println ( ) ;
else
10
20
30
40
50
60
System.out.println ( ) ;
70
80
90
printM ( mat , i + 1 , 0 ) ;
100
110
120
if ( j > = mat[ i ].length )
{
}
mat
else
{
System.out.print ( mat[ i ][ j ] + " " ) ;
printM ( mat , i , j + 1 ) ;
}
}
? printM ( mat , 0 , 0 ) ; ‫מה יהיה הפלט של הזימון‬
.‫א‬
________________________________________________________________________________________________________
________________________________________________________________________________________________________
________________________________________________________________________________________________________
________________________________________________________________________________________________________
__________________________________________________________ ______________________________________________
:printM ‫ שורות מה מבצעת הפעולה‬2-3 -‫י ב‬/‫הסבר‬
.‫ב‬
________________________________________________________________________________________________________
_______________________________________________________________ _________________________________________
________________________________________________________________________________________________________
- 43 -
‫‪‬‬
‫קּור ִסיָּ ה – פעולות שמחזירות ערך‬
‫דף עבודה מס' ‪ֵ – 2‬ר ְ‬
‫‪‬‬
‫********************************************************************‬
‫‪.1‬‬
‫המושג עֲצֶ ֶרת (‪ )factorial‬במתמטיקה הוא מכפלת כל המספרים הטבעיים מ‪ 1 -‬ועד למספר נתון‪.‬‬
‫המושג עצרת מסומן ! (סימן קריאה) למשל‪N! = 1 x 2 x 3 x … x N :‬‬
‫דוגמה לחישוב עצרת בעזרת רקורסיה‪:‬‬
‫‪3! x 4‬‬
‫=‬
‫‪4! = 1 x 2 x 3 x 4‬‬
‫‪3! = 1 x 2 x 3‬‬
‫זהו ההליך הרקורסיבי‬
‫‪‬‬
‫‪N! = ( N – 1 )! x N‬‬
‫‪3! x 4 = 6 x 4 = 24‬‬
‫= ‪4! = 1 x 2 x 3 x 4‬‬
‫‪6‬‬
‫‪2! x 3‬‬
‫= ‪3! = 1 x 2 x 3‬‬
‫‪2‬‬
‫‪1! x 2‬‬
‫=‬
‫‪2! = 1 x 2‬‬
‫‪1‬‬
‫אלו הם שני תנאי עצירה אפשריים‬
‫‪‬‬
‫‪1! = 1‬‬
‫‪0! = 1‬‬
‫לפניך פעולה בשפת ‪:JAVA‬‬
‫) ‪public static int factorial ( int n‬‬
‫{‬
‫‪//‬‬
‫הפעולה מקבלת מספר טבעי ‪. n‬‬
‫‪//‬‬
‫הפעולה מחשבת ומחזירה את תוצאת העצרת של ‪.n‬‬
‫) ‪if ( n = = 1‬‬
‫; ) ‪return ( 1‬‬
‫‪else‬‬
‫; ) ‪return ( factorial ( n – 1 ) * n‬‬
‫}‬
‫; ) ) ‪System.out.print ( factorial ( 4‬‬
‫רשום‪/‬י מהו הפלט עבור זימון הפעולה‬
‫__________________________________________________________________________________________________‬
‫‪- 44 -‬‬
‫‪.2‬‬
‫כתב‪/‬י פעולה רקורסיבית המקבלת מספר שלם טבעי ‪ , N‬ומדפיסה את הערכים הבאים‪:‬‬
‫!‪1! , 2! , 3! , 4! , 5! , . . . . , (N-1)! , N‬‬
‫‪.3‬‬
‫לפניך פעולה בשפת ‪:JAVA‬‬
‫) ‪public static int exe1 ( int x , int y‬‬
‫{‬
‫‪//‬‬
‫הפעולה מקבלת מספר טבעי ‪ y‬ומספר שלם ‪.x‬‬
‫‪//‬‬
‫הפעולה מחשבת ומחזירה ‪. . . . .‬‬
‫) ‪if ( y = = 0‬‬
‫; ) ‪return ( x‬‬
‫‪else‬‬
‫; ) ) ‪return ( exe1 ( x + 1 , y – 1‬‬
‫}‬
‫א‪.‬‬
‫נסה‪/‬י לנחש מה יהיה הפלט של הזימון ; ) ) ‪? System.out.println ( "Result: " + exe1 ( 4 , 3‬‬
‫ב‪.‬‬
‫כעת בדק‪/‬י בעזרת הרצה במחשב מהו הפלט של הזימון‬
‫; ) ) ‪? System.out.println ( "Result: " + exe1 ( 4 , 3‬‬
‫________________________________________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫ג‪.‬‬
‫הרץ ‪/‬י את התכנית עבור הקלטים הבאים‪ ,‬ורשום ‪/‬י את הפלט בטבלה הבאה‪:‬‬
‫פלט‬
‫ד‪.‬‬
‫‪mis2‬‬
‫; ) ‪exe1 ( 6 , 3‬‬
‫; ) ‪exe1 ( -6 , 2‬‬
‫; ) ‪exe1 ( 3 , 7‬‬
‫; ) ‪exe1 ( 7 , 3‬‬
‫הסבר‪/‬י ב‪ 2-3 -‬שורות מה מבצעת הפעולה ‪:exe1‬‬
‫________________________________________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫‪- 45 -‬‬
‫ה‪.‬‬
‫מה יקרה אם נריץ את התכנית הראשית עם הזימון‪:‬‬
‫; ) ) ‪? System.out.println ( " Result : " + exe1 ( 4 , -3‬‬
‫________________________________________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫הסבר‪/‬י ‪:‬‬
‫________________________________ ________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫‪.4‬‬
‫לפניך פעולה בשפת ‪:JAVA‬‬
‫) ‪public static int exe2 ( int x , int y‬‬
‫{‬
‫‪//‬‬
‫הפעולה מקבלת מספר טבעי ‪ y‬ומספר שלם ‪.x‬‬
‫‪//‬‬
‫הפעולה מחשבת ומחזירה ‪. . . . .‬‬
‫) ‪if ( y = = 0‬‬
‫; ) ‪return ( x‬‬
‫‪else‬‬
‫; ) ‪return ( exe2 ( x , y – 1 ) + 1‬‬
‫}‬
‫א‪.‬‬
‫נסה‪/‬י לנחש מה יהיה הפלט של הזימון ; ) ) ‪? System.out.println ( "Result: " + exe2 ( 4 , 3‬‬
‫ב‪.‬‬
‫מהו הפלט של הזימון ; ) ) ‪? System.out.println ( "Result: " + exe2 ( 4 , 3‬‬
‫________________________________________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫ג‪.‬‬
‫הסבר‪/‬י ב‪ 2-3 -‬שורות מה מבצעת הפעולה ‪:exe2‬‬
‫________________________________________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫‪- 46 -‬‬
‫ד‪.‬‬
‫הסבר‪/‬י את ההבדל בין הפעולות ‪ exe1 , exe2‬וממה הוא נובע ?‬
‫________________________________________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫_________________________ _______________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫‪.5‬‬
‫א‪.‬‬
‫‪ X‬ו‪Y -‬‬
‫כתב‪/‬י פעולה רקורסיבית המקבלת שני מספרים שלמים‬
‫ומחזירה את מכפלתם‪.‬‬
‫(רמז‪ :‬חישבו כיצד ניתן לממש את פעולת הכפל ‪ ,‬כאשר פעולת הכפל ( * ) לא קיימת)‪.‬‬
‫ב‪.‬‬
‫הרץ‪/‬י את הפעולה שכתבת בסעיף א' עם הערכים ‪. x = 4 , y = 3‬‬
‫ג‪.‬‬
‫האם הפלט שקבלת הוא‪? 12 :‬‬
‫_________________________________________________________________‬
‫אם לא ‪ ,‬מה הייתה הבעיה ?‬
‫_________________________________________________________________‬
‫_______________________________________________________________________________________________________‬
‫_______________________________________________________________________________________________________‬
‫________________________________________________ _______________________________________________________‬
‫ד‪.‬‬
‫האם ניתן לכתוב‪ ,‬בצורה רקורסיבית‪ ,‬את פעולת הכפל בשתי צורות שונות‪,‬‬
‫כפי שניתן לעשות בפעולת החיבור ? הסבר‪/‬י !‬
‫_______________________________________________________________________________________________________‬
‫_______________________________________________________________________________________________________‬
‫_______________________________________________________________________________________________________‬
‫______ _________________________________________________________________________________________________‬
‫‪.6‬‬
‫כתב‪/‬י פעולה רקורסיבית המקבלת שני מספרים שלמים‬
‫‪X‬‬
‫ו‪ Y -‬ומחזירה את ‪.XY‬‬
‫_______________________________________________________________________________________________________‬
‫_______________________________________________________________________________________________________‬
‫________________________________________________ _______________________________________________________‬
‫_______________________________________________________________________________________________________‬
‫_______________________________________________________________________________________________________‬
‫‪- 47 -‬‬
‫‪.7‬‬
‫לפניך פעולה בשפת ‪:JAVA‬‬
‫הפעולה מקבלת מספר שלם ‪.n‬‬
‫הפעולה מחשבת ומחזירה ‪. . . . .‬‬
‫א‪.‬‬
‫) ‪public static int exe3 ( int n‬‬
‫{‬
‫‪//‬‬
‫‪//‬‬
‫) ‪if ( n = = 0‬‬
‫; ) ‪return ( 0‬‬
‫‪else‬‬
‫; ) ) ‪return ( exe3 ( n / 10 ) + 1‬‬
‫}‬
‫מה יהיה הפלט של הזימון ; ) ) ‪? System.out.println ( "Result: " + exe3 ( 2763‬‬
‫________________________________________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫ב‪.‬‬
‫הרץ ‪/‬י את התכנית עבור הקלטים הבאים‪ ,‬ורשום ‪/‬י את הפלט בטבלה הבאה‪:‬‬
‫פלט‬
‫‪mis2‬‬
‫; ) ‪exe3 ( 46‬‬
‫; ) ‪exe3 ( 1‬‬
‫; ) ‪exe3 ( 127‬‬
‫; ) ‪exe3 ( 12345‬‬
‫ג‪.‬‬
‫הסבר‪/‬י ב‪ 2-3 -‬שורות מה מבצעת הפעולה ‪:exe3‬‬
‫________________________________________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫‪.8‬‬
‫כתב‪/‬י פונקציה רקורסיבית המקבלת מספר שלם חיובי ‪ mis‬ומחזירה את סכום הספרות‬
‫המופיעות במספר‪ .‬לדוגמה‪ :‬אם ערכו של ‪ mis‬הוא‪ 1277 :‬אזי הפונקציה מחזירה ‪.17‬‬
‫________________________________________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫___________ _____________________________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫‪- 48 -‬‬
‫‪.9‬‬
‫לפניך פעולה בשפת ‪:JAVA‬‬
‫הפעולה מקבלת מספר שלם ‪.n‬‬
‫הפעולה מחשבת ומחזירה ‪. . . . .‬‬
‫א‪.‬‬
‫) ‪public static int exe4 ( int n‬‬
‫{‬
‫‪//‬‬
‫‪//‬‬
‫) ‪if ( n = = 0‬‬
‫; ) ‪return ( true‬‬
‫‪else‬‬
‫) ‪if ( n % 2 ! = 0‬‬
‫; ) ‪return ( false‬‬
‫‪else‬‬
‫; ) ) ‪return ( exe4 ( n / 10‬‬
‫}‬
‫מה יהיה הפלט של הזימון ; ) ) ‪? System.out.println ( "Result: " + exe4 ( 2764‬‬
‫________________________________________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫ב‪.‬‬
‫הרץ ‪/‬י את התכנית עבור הקלטים הבאים‪ ,‬ורשום ‪/‬י את הפלט בטבלה הבאה‪:‬‬
‫פלט‬
‫‪mis2‬‬
‫; ) ‪exe4 ( 46‬‬
‫; ) ‪exe4 ( 124‬‬
‫; ) ‪exe4 ( 24608‬‬
‫ג‪.‬‬
‫הסבר‪/‬י ב‪ 2-3 -‬שורות מה מבצעת הפעולה ‪:exe4‬‬
‫________________________________________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫______________________________________________ __________________________________________________________‬
‫‪ .10‬שנה‪/‬י את הפעולה בתרגיל ‪9‬‬
‫שתחזיר 'אמת' אם כל הספרות במספר הן אי‪-‬זוגיות‪ ,‬אחרת תחזיר 'שקר'‪.‬‬
‫הערה‪ :‬הספרה ‪ 0‬היא זוגית‪.‬‬
‫________________________________________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫‪- 49 -‬‬
‫‪.11‬‬
‫כתב‪/‬י פעולה רקורסיבית המקבלת מחרוזת ‪ S‬בגודל ‪, 20‬‬
‫מחזירה 'אמת' אם המחרוזת היא פלינדרום ‪ ,‬אחרת מחזירה 'שקר'‪.‬‬
‫________________________________________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫______________________________________________ __________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫‪ .12‬לפניך פעולה בשפת ‪:JAVA‬‬
‫) ‪public static int exe5 ( int n‬‬
‫{‬
‫‪//‬‬
‫‪//‬‬
‫) ‪if ( n > 10‬‬
‫; ) ‪return ( n‬‬
‫; ) ‪int temp = exe5 ( n / 10‬‬
‫הפעולה מקבלת מספר שלם ‪.n‬‬
‫הפעולה מחשבת ומחזירה ‪. . . . .‬‬
‫) ‪if ( n % 10 < temp‬‬
‫; ) ‪return ( n % 10‬‬
‫‪else‬‬
‫; ) ‪return ( temp‬‬
‫}‬
‫א‪.‬‬
‫מה יהיה הפלט של הזימון ; ) ) ‪? System.out.println ( "Result: " + exe5 ( 27164‬‬
‫________________________________________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫ב‪.‬‬
‫הרץ ‪/‬י את התכנית עבור הקלטים הבאים‪ ,‬ורשום ‪/‬י את הפלט בטבלה הבאה‪:‬‬
‫פלט‬
‫‪mis2‬‬
‫; ) ‪exe5 ( 46‬‬
‫; ) ‪exe5 ( 314‬‬
‫; ) ‪exe5 ( 942‬‬
‫; ) ‪exe5 ( 24607‬‬
‫ג‪.‬‬
‫הסבר‪/‬י ב‪ 2-3 -‬שורות מה מבצעת הפעולה ‪:exe5‬‬
‫________________________________________________________________________________________________________‬
‫________________________________________________________________________________________________________‬
‫‪- 50 -‬‬
‫תרגילי סיכום‬
‫*‬
‫‪ .13‬כתב ‪/‬י פעולה רקורסיבית המקבלת מערך ומדפיסה אותו מהסוף להתחלה‪ 2( .‬פתרונות שונים)‪.‬‬
‫‪ .14‬כתב ‪/‬י פעולה רקורסיבית המקבלת מערך ‪ , A‬ומחזירה את סכום האיברים‪.‬‬
‫‪ .15‬כתב ‪/‬י פעולה רקורסיבית המקבלת מערך ‪ A‬ואיבר נוסף ‪ ,X‬ומדפיסה את מיקום האיבר במערך‪.‬‬
‫‪ .16‬כתב ‪/‬י פעולה רקורסיבית המקבלת מערך ממויין ‪ A‬ואיבר נוסף ‪ , X‬ומדפיסה את מיקום האיבר במערך‪( .‬‬
‫הערה‪ :‬החיפוש צריך להיות בינארי ! )‬
‫‪ .17‬כתב ‪/‬י פעולה רקורסיבית המקבלת מערך ‪ , A‬מחזירה 'אמת' אם כל המספרים במערך חיוביים‪ ,‬אחרת‬
‫מחזירה 'שקר'‪.‬‬
‫‪ .18‬כתב‪/‬י פעולה רקורסיבית הקולטת סדרת תווים המסתיימת בנקודה‪ ,‬ומזירה מחרוזת של תווים‪.‬‬
‫(הערה‪ :‬יש להשתמש בפרמטר אחד בלבד)‪.‬‬
‫‪ .19‬כתב ‪/‬י פעולה רקורסיבית המקבלת מערך ‪ , A‬ומחזירה את ערכו של האיבר המינימלי‪.‬‬
‫‪- 51 -‬‬
‫מחלקת חוליה ושרשרת חוליות‬
‫פיתוח‪ :‬רוני אלנקרי‬
‫בס"ד‬
‫נעים להכיר – מחלקת חוליה ‪Node‬‬
‫עד עתה הגדרנו מחלקות שבהן התכונות הן מטיפוסים בסיסיים וכן מחלקות שבהן תכונות הן עצמים אחרים‬
‫(עצמים מורכבים)‪.‬‬
‫‪ .1‬נתונה המחלקה ‪ .Date‬חרוז‪ ,Bead ,‬מיוצג באמצעות התכונות צבע ותאריך ייצור מטיפוס ‪ .Date‬כתבו את‬
‫כותרת המחלקה חרוז ‪ Bead‬ותכונותיה‪.‬‬
‫נתון קטע התוכנית הבא ‪:‬‬
‫;)‪b1 = new Bead("yellow" , new Date(1,1,2000‬‬
‫;)‪b2 = new Bead("red" , null‬‬
‫‪ .2‬ציירו את המבנה של החרוזים שנוצרו ‪.‬‬
‫חרוז ‪ Bead‬הוא עצם שמורכב מעצם אחר‪.‬‬
‫‪ .3‬עתה נחליף את התכונה תאריך ייצור של חרוז ;‪ Date date‬לתכונה ; ‪. Bead next‬‬
‫גם עתה יהיו החרוז עצם מורכב‪.‬‬
‫מה בכל זאת שונה בהגדרת החרוז החדשה?‬
‫‪- 52 -‬‬
.‫אנו רואים כי ניתן להגדיר עצם מורכב שאחת התכונות שלו היא עצם מאותה המחלקה‬
) toString ‫ ו‬set , get ‫ פעולות‬,‫ )שיטה בונה לא ריקה‬Bead ‫הגדירו במחשב את המחלקה‬
.4
public class Bead
{
private String color;
private Bead next;
public Bead(String color, Bead next)
{
...
}
public String getColor()
{
...
}
.setColor ‫שימו לב כי אין צורך בפעולה‬
public Bead getNext()
{
...
}
public void setNext(Bead next)
{
this.next = next;
}
public String toString()
{
...
}
?‫מדוע‬
}
: ‫ את החרוזים הבאים‬main ‫ הגדירו במחלקת‬.‫א‬
b1 = new Bead("yellow" , null);
b2 = new Bead("green" ,null);
b3 = new Bead("red" , null);
______________________________ ? ‫כמה חרוזים נוצרו‬
: )‫ עתה הגדירו את החרוזים באופן הבא (שימו לב לשינוי בהגדרת החרוזים‬.‫ב‬
b1 = new Bead("yellow" , null);
b2 = new Bead("green" ,new Bead("red",null) ;
- 53 -
.5
‫ג‪ .‬ציירו את החרוזים שנוצרו‬
‫‪ .6‬א‪ .‬הוסיפו לתוכנית פקודות מתאימות להדפסת החרוזים‪.‬‬
‫ב‪ .‬האם הצלחתם להדפיס את כל החרוזים שנוצרו ? ___________‬
‫ג‪ .‬מה ההבדל בין ההפניה לחרוז השלישי לעומת ההפניה לחרוז הראשון ____________________‬
‫הוסיפו לתוכנית את הפעולות הבאות‪:‬‬
‫;)‪b1.setNext(b2‬‬
‫;‪b2=null‬‬
‫ד‪ .‬הדפיסו עתה את שלושת החרוזים‪.‬‬
‫אז מה למדנו עד עתה ?‬
‫‪.I‬‬
‫ניתן להגדיר לעצם תכונה שהיא הפניה לעצם מאותה המחלקה‬
‫‪ .II‬עצם כזה אנו מכנים חוליה ‪Node‬‬
‫‪ .III‬ניתן לגשת לחוליה אחת דרך חוליה אחרת‪.‬‬
‫‪ .7‬נתון קטע התוכנית הבא ‪( :‬הוסיפו אותו לתוכנית שלכם)‬
‫;)"הכנס צבע "(‪System.out.println‬‬
‫;)(‪String c = in.next‬‬
‫;)‪b1 = new Bead(c , null‬‬
‫)‪for (int i=0 ; i<5; i++‬‬
‫{‬
‫;)"צבע הכנס"(‪System.out.println‬‬
‫;)(‪c = in.next‬‬
‫;)‪b2 = new Bead(c,null‬‬
‫;)‪b1.setNext(b2‬‬
‫;‪b1=b2‬‬
‫}‬
‫א‪ .‬כמה חוליות נוצרו ? ______________‬
‫‪- 54 -‬‬
‫ב‪ .‬ציירו את המבנה שנוצר‪.‬‬
‫ג‪.‬‬
‫הוסיפו קטע תוכנית שידפיס את כל החוליות שבשרשרת שנוצרה‪ ,‬הריצו ובדקו את הפלט‪.‬‬
‫ד‪.‬‬
‫האם הצלחתם ? ___________________________________________________________‬
‫‪ .8‬הוסיפו את הפקודה הבאה בקטע התוכנית שיוצר את שרשרת החוליות‪.‬‬
‫א‪ .‬מה מטרת הפקודה לדעתכם? _________________________________‬
‫;)"הכנס צבע "(‪System.out.println‬‬
‫הוסיפו את פקודה הבאה‬
‫;)(‪String c = in.next‬‬
‫;)‪b1 = new Bead(c , null‬‬
‫;‪Bead first = b1‬‬
‫)‪for (int i=0 ; i<5; i++‬‬
‫{‬
‫;)"צבע הכנס"(‪System.out.println‬‬
‫;)(‪c = in.next‬‬
‫;)‪b2 = new Bead(c,null‬‬
‫;)‪b1.setNext(b2‬‬
‫;‪b1=b2‬‬
‫}‬
‫ב‪ .‬עתה כתבו קטע תוכנית שידפיס את החוליות שבשרשרת ‪ .‬הריצו ובדקו את הפלט‪.‬‬
‫ג‪ .‬מה תפקידה של ההפניה ‪_______________________ ? first‬‬
‫‪- 55 -‬‬
‫אז מה למדנו עד עתה ?‬
‫‪ .I‬ניתן באמצעות חוליה שיש לה הפניה לחוליה מאותה מחלקה לבנות שרשרת של‬
‫חוליות‬
‫‪ .II‬בשרשרת כזו ניתן לגשת לכל חוליה באמצעות ההפניה אליה מהחוליה הקודמת‬
‫)‪ .(getNext‬לכן אין צורך לשמור את ההפניה לחוליה על ידי משתנה נוסף‪..‬‬
‫‪.III‬‬
‫כיוון שלחוליה הראשונה אין חוליה קודמת יש לשמור את ההפניה אליה ע"י‬
‫משתנה נוסף‪first .‬‬
‫בקטע התוכנית הקודם יצרנו שרשרת עם ‪ 6‬חוליות‪ .‬כמובן שניתן לייצר שרשרת חוליות בכל גודל ‪.‬‬
‫‪.9‬‬
‫א‪ .‬האם יש צורך להגדיר מראש את גודל השרשרת (בדומה למערך?) ________‬
‫ב‪ .‬הוסיפו את הדרוש לקטע התוכנית הבא שמטרתו להדפיס את שרשרת החוליות שייצרנו על ידי לולאת‬
‫‪ .while‬וודאו שהודפסו כל החוליות בשרשרת‪.‬‬
‫הפניה לחוליה הראשונה בשרשרת ‪Bead pos = _______________________ ; //‬‬
‫כל עוד ‪ pos‬מפנה לחוליה קיימת ‪while ( pos ! = _______________ ) //‬‬
‫הדפסת צבע החרוז ‪{ System.out.println (pos.getInfo()) ; //‬‬
‫} התקדם לחוליה הבא ‪pos = ________________ //‬‬
‫ג‪ .‬נתון קטע התוכנית הבא‪:‬‬
‫;‪Bead first = null‬‬
‫)‪for (int i=0 ; i<6; i++‬‬
‫{‬
‫;)"צבע הכנס"(‪System.out.println‬‬
‫;)(‪c = in.next‬‬
‫;)‪b1 = new Bead(c,first‬‬
‫;‪first = b1‬‬
‫}‬
‫עקבו אחר קטע התוכנית וציירו את השרשרת שנוצרה‪.‬‬
‫הריצו על גבי המחשב ובדקו את תשובתכם ע"י הוספת קטע המדפיס את השרשרת שנוצרה‪.‬‬
‫‪- 56 -‬‬
‫אז מה למדנו עד עתה ?‬
‫‪ .I‬ניתן באמצעות חוליה להגדיר מבנה של מספר חוליות‪ .‬שרשרת חוליות‪.‬‬
‫‪ .II‬אין צורך להגדיר מראש את גודל השרשרת‪.‬‬
‫‪.III‬‬
‫אנו נשמור את ההפניה לחוליה הראשונה בשרשרת‪.‬‬
‫המחלקה חוליה <‪Node<T‬‬
‫נתונה המחלקה חוליה‪ .Node -‬העתיקו אותה לפרויקט‪.‬‬
‫המחלקה תשמש לנו לייצר ולעבוד עם שרשרות חוליות מכל טיפוס‪.‬‬
‫לשרשרת כזו נקרא רשימה‪.‬‬
‫בסוף דפי העבודה מצורף ממשק המחלקה‪.‬‬
‫‪ .1‬להלן קטע תוכנית לבניית שרשרת חוליות תוך שימוש במחלקה ‪. Node‬‬
‫הריצו אותו והוסיפו קטע תוכנית המדפיס את השרשרת שנוצרה ע"י לולאת ‪ while‬תוך שימוש בממשק‪.‬‬
‫;‪Node <Integer> first = null‬‬
‫;‪Node <Integer> pos = null‬‬
‫)‪for (int i=1 ; i<=10; i++‬‬
‫{‬
‫החוליה הראשונה ‪if (i==1) //‬‬
‫{‬
‫;)‪pos = new Node<Integer> (i*2‬‬
‫שמירת הפניה לחוליה הראשונה ‪first = pos; //‬‬
‫}‬
‫‪else‬‬
‫{‬
‫;))‪pos.setNext(new Node<Integer> (i*2‬‬
‫;)(‪pos = pos.getNext‬‬
‫}‬
‫}‬
‫‪- 57 -‬‬
‫‪ .2‬א‪ .‬מה יבצע הקטע הבא על השרשרת שנוצרה בקטע הקודם ?‬
‫_____________________________________________________________‬
‫;)‪pos = new Node<Integer> (0‬‬
‫;)‪pos.setNext(first‬‬
‫;‪first = pos‬‬
‫ב‪ .‬הדפיסו את השרשרת החדשה‪.‬‬
‫‪ .3‬מה יבצע הקטע הבא ‪:‬‬
‫;)(‪pos = first.getNext().getNext‬‬
‫;;)‪Node <Integer> p = new Node<Integer> (7‬‬
‫;))(‪p.setNext(pos.getNext‬‬
‫;)‪pos.setNext(p‬‬
‫‪ .4‬להלן שרטוט המדגים את הפעולות בקטע התוכנית האחרון‪.‬‬
‫וודאו שאתם מבינים את השרטוט‪.‬‬
‫מדוע יש לבצע את הפעולות בסדר הכתוב‪ ,‬ראשית יצירת ההפניה שמסומנת ב ‪ 1-‬ואח"כ ההפניה‬
‫המסומנת ב‪________________________ ? 2-‬‬
‫‪6‬‬
‫‪8‬‬
‫‪7‬‬
‫‪- 58 -‬‬
‫אז מה למדנו עד עתה ?‬
‫‪ .I‬ניתן להוסיף לשרשרת חוליות חדשות‬
‫‪ .II‬יש ליצור חוליה חדשה ואז לעדכן את ההפניות בשרשרת‪.‬‬
‫‪.III‬‬
‫אם מכיסים חוליה במקום הראשון יש לעדכן את הפניה לראשון ‪first‬‬
‫‪ .IV‬אם מכניסים חוליה למקום שאינו הראשון יש לעמוד על‬
‫המקום‬
‫שלאחריו תיכנס‬
‫החוליה החדשה‪ ..‬סדר שינוי ההפניות יהיה ‪ :‬ראשית נפנה את החוליה החדשה‬
‫לחוליה הבאה אחריה ושנית נפנה ת החוליה הקודמת לה אליה‪.‬‬
‫אם ברצוננו למחוק חוליה מהשרשרת אין צורך למחוק אותה בפועל‪.‬‬
‫עלינו לשנות את ההפניה שמצביעה על החוליה כך שתצביע על החוליה הבאה בתור‪.‬‬
‫כאשר אין אף איבר בשרשרת שיצביע על החוליה היא נמחקת‪.‬‬
‫("אספן הזבל" של ‪ java‬דואג לפנות אותה בשלב מסוים מהזיכרון)‬
‫‪ .5‬כתבו קטע תוכנית המוחק את החוליה עם הערך ‪ .4‬שימו לב לאיור המדגים את שלבי הפעולות שעליכם‬
‫לעשות‪:‬‬
‫א‪ .‬להציב את ‪ pos‬על החוליה שערכה ______‬
‫ב‪ .‬חוליה זאת הינה חוליה שמיקומה (לפני‪/‬אחרי‪/‬אותה) ___________ החוליה שברצוננו למחוק‬
‫ג‪ .‬לשנות את ההפניה ‪ next‬בחוליה ‪ pos‬כך שתפנה לחוליה שאחרי החוליה שברצוננו למחוק‬
‫וההפניה אליה היא ‪________________________ :‬‬
‫‪pos‬‬
‫‪4‬‬
‫‪6‬‬
‫‪2‬‬
‫‪ .6‬כתבו את הפעולה המוחקת את החוליה הראשונה‪ .‬שימו לב לאיור המדגים את הפעולה שעליכם לבצע‪.‬‬
‫‪- 59 -‬‬
‫…‬
‫אז מה למדנו עד עתה ?‬
‫‪ .I‬ניתן למחוק חוליות מהשרשרת‪.‬‬
‫‪ .II‬אם מוחקים חוליה ראשונה יש לשנות את ‪ first‬כך שיפנה לחוליה השנייה (שהופכת‬
‫עכשיו להיות ראשונה)‪.‬‬
‫‪.III‬‬
‫אם מוחקים חוליה שאינה הראשונה יש לעמוד על החוליה שלפניה ולהפנות‬
‫אותה לחוליה אחת אחרי החוליה שברצוננו למחוק‪( .‬לדלג על החוליה שברצוננו‬
‫לבטל‪) .‬‬
‫‪ .IV‬מנגנון "אספן הזבל" של ‪ java‬יזהה חוליות שאין להן הפניות ויפנה אותן‬
‫מהזיכרון (בתנאי שאין משתנה אחר שמצביע על החוליה הזאת‪ .‬כל חוליה שאין‬
‫עוד אפשרות להגיע אליה ישירות או בעקיפין ממשתנה‪ ,‬תאסף‪).‬‬
‫ממשק המחלקה חוליה <‪Node<T‬‬
‫המחלקה הגנרית >‪Node<T‬‬
‫מייצגת חוליה המכילה ערך מטיפוס גנרי ‪ T‬והפנייה לחוליה או לערך ‪.null‬‬
‫ניתן להשתמש במחלקה זאת כדי לייצג רשימה המורכבת משרשרת של אפס או יותר חוליות‪.‬‬
‫פעולה הבונה חוליה שהערך שלה הינו ‪ x‬וההפניה שלה ל‪null -‬‬
‫פעולה הבונה חוליה שהערך שלה הינו ‪ x‬וההפניה שלה לחוליה‬
‫‪( next‬שיכול להיות ‪)null‬‬
‫> ‪O(1) Node <T x‬‬
‫) ‪O(1) Node <T x> , Node <T> next‬‬
‫)(‪O(1) T getValue‬‬
‫פעולה המחזירה את ערך החוליה‬
‫)(‪O(1) Node <T> getNext‬‬
‫פעולה המחזירה הפניה לחוליה הבאה או ‪null‬‬
‫פעולה הבודקת האם יש חוליה נוספת ?‬
‫)(‪O(1) boolean hasNext‬‬
‫פעולה המחזירה את ערך החוליה כמחרוזת‬
‫)( ‪O(T) String toString‬‬
‫)‪O(1) void setValue(T x‬‬
‫פעולה המשנה את ערך החוליה ל ‪x‬‬
‫)‪O(1) void setNext(Node<T> next‬‬
‫פעולה המשנה את ההפניה לחוליה הבאה‬
‫‪- 60 -‬‬
‫תשובות‬
‫‪.1‬‬
‫{ ‪public class Bead‬‬
‫;‪String color‬‬
‫;‪Date date‬‬
‫‪ .2‬ציירו את המבנה של החרוזים שנוצרו ‪.‬‬
‫‪b2‬‬
‫‪null‬‬
‫‪b1‬‬
‫‪yellow‬‬
‫‪red‬‬
‫‪2000‬‬
‫‪1‬‬
‫‪1‬‬
‫‪ .3‬מה בכל זאת שונה בהגדרת החרוז החדשה?‬
‫יש כאן הגדרה רקורסיבית‪ .‬חרוז הוא עצם שאחת מהתכונות שלו הוא עצם מאותה המחלקה‪.‬‬
‫‪ .5‬א‪ .‬הגדירו במחלקת ‪ main‬את החרוזים הבאים ‪ :‬כמה חרוזים נוצרו ?‬
‫‪3‬‬
‫ה‪ .‬ציירו את החרוזים שנוצרו‬
‫‪b2‬‬
‫‪null‬‬
‫‪red‬‬
‫‪b1‬‬
‫‪green‬‬
‫‪null‬‬
‫‪yellow‬‬
‫‪ .6‬א‪ .‬הוסיפו לתוכנית פקודות מתאימות להדפסת החרוזים‪.‬‬
‫;)‪System.out.printn(b1‬‬
‫;)‪System.out.printn(b2‬‬
‫;))‪System.out.printn(b2.getNext‬‬
‫ג‪ .‬מה ההבדל בין ההפניה לחרוז השלישי לעומת ההפניה לחרוז הראשון ? לחרוז הראשון קיימת הפניה ע"י‬
‫משתנה ‪ b1‬ואילו לחרוז השלישי קיימת הפניה מחרוז אחר‪ ,‬החרוז ‪b2‬‬
‫‪- 61 -‬‬
‫ד‪ .‬הדפיסו עתה את שלושת החרוזים‪.‬‬
‫‪ .7‬א‪ .‬כמה חוליות נוצרו ?‬
‫;)‪System.out.printn(b1‬‬
‫;))(‪System.out.printn(b1.getNext‬‬
‫;))(‪System.out.printn(b1.getNext().getNext‬‬
‫‪6‬‬
‫ב‪ .‬ציירו את המבנה שנוצר‪.‬‬
‫‪b2‬‬
‫‪b1‬‬
‫‪Color6‬‬
‫‪Color4‬‬
‫‪Color5‬‬
‫‪Color3‬‬
‫‪Color2‬‬
‫‪Color1‬‬
‫ד‪ .‬האם הצלחתם ? לא‪ ,‬חסרה הפניה לחוליה הראשונה‬
‫‪ .8‬הוסיפו את הפקודה הבאה בקטע התוכנית שיוצר את שרשרת החוליות‪.‬‬
‫א‪ .‬מה מטרת הפקודה לדעתכם? לשמור במשתנה ‪ first‬הפניה לחוליה הראשונה‬
‫ג‪ .‬תפקידה של ההפניה ‪ ? first‬להפנות לחוליה הראשונה בשרשרת שנוצרה‪.‬‬
‫‪ .9‬א‪ .‬האם יש צורך להגדיר מראש את גודל השרשרת (בדומה למערך?) לא‬
‫ב‪ .‬הוסיפו את הדרוש לקטע התוכנית הבא‬
‫הפניה לחוליה הראשונה בשרשרת ‪Bead pos = ____first________________ ; //‬‬
‫כל עוד ‪ pos‬מפנה לחוליה קיימת ‪while ( pos ! = _null_____________ ) //‬‬
‫הדפסת צבע החרוז ‪{ System.out.println (pos.getInfo()) ; //‬‬
‫} התקדם לחוליה הבא ‪pos = pos.getNext()________ //‬‬
‫המחלקה חוליה <‪Node<T‬‬
‫‪.1‬‬
‫‪202‬‬
‫להלן קטע תוכנית לבניית שרשרת חוליות תוך שימוש במחלקה ‪ . Node‬הריצו אותו והדפיסו ‪...‬‬
‫…‬
‫‪12‬‬
‫‪10‬‬
‫‪- 62 -‬‬
‫‪8‬‬
‫‪6‬‬
‫‪4‬‬
‫‪2‬‬
‫‪ .2‬א‪ .‬מה יבצע הקטע הבא (לאחר יצירת השרשרת בסעיף הקודם) ‪:‬‬
‫תתווסף החוליה שערכה ‪ 0‬להיות החוליה הראשונה‬
‫‪ .3‬מה יבצע הקטע הבא ‪:‬‬
‫תווסף החוליה שערכה‬
‫‪7‬‬
‫לאחר החוליה שערכה ‪6‬‬
‫‪ .4‬מדוע יש לבצע את הפעולות בסדר הכתוב‪ ,‬ראשית יצירת ההפניה שמסומנת ב ‪ 1-‬ואח"כ ההפניה המסומנת‬
‫ב‪ ? 2-‬אם נשנה קודם את ההפניה בחוליה ‪" pos‬נאבד" את החוליה שערכה ‪ 8‬כך שלא נוכל להפנות‬
‫את החוליה ‪ p‬אליה‪.‬‬
‫‪ .5‬כתבו קטע תוכנית המוחק את החוליה עם הערך ‪.4‬‬
‫א‪ .‬להציב את ‪ pos‬על החוליה שערכה ‪2‬‬
‫ב‪ .‬חוליה זאת הינה חוליה שמיקומה (לפני‪/‬אחרי‪/‬אותה) לפני החוליה שברצוננו למחוק‬
‫ג‪ .‬לשנות את ההפניה ‪ next‬בחוליה ‪ pos‬כך שתפנה לחוליה שאחרי החוליה שברצוננו למחוק וההפניה‬
‫אליה היא ‪pos.getNext().getext() :‬‬
‫‪ .6‬כתבו את הפעולה המוחקת את החוליה הראשונה‬
‫;)(‪first = first.getNext‬‬
‫‪- 63 -‬‬
‫שרשרת חוליות‬
‫פיתוח‪ :‬ברכה דאום‪-‬רייטר‪ ,‬גיטה קופרמן‬
‫שרשרת היא אוסף חרוזים הקשורים זה לזה‪ .‬רצף החרוזים יכול להיות קווי או מעגלי‪.‬‬
‫משימה ‪:1‬‬
‫נבנה מחלקה המתארת חרוז‪:‬‬
‫נניח שכל החרוזים שברשותנו הינם בעלי גודל וצורה זהים‪ ,‬אך שונים בצבעם‪.‬‬
‫לפניך תיאור המחלקה‪ ,‬השלימי את הטבלה‪.‬‬
‫המחלקה‪ :‬חרוז‬
‫‪Bead‬‬
‫תכונות‪ :‬צבע‬
‫‪_______ color‬‬
‫פעולות‪ :‬פעולה בונה‬
‫פעולה שמאחזרת את הצבע‬
‫הפעולה ‪ToString‬‬
‫משימה ‪:2‬‬
‫‪ ‬צרי פרויקט ב ‪ ,C#‬הוסיפי את המחלקה ‪ Bead‬והשלימי את חברי המחלקה‪.‬‬
‫‪‬‬
‫כתבי תכנית בדיקה שמייצרת ‪ 4‬חרוזים בצבעים שונים‪.‬‬
‫שרטטי תרשים עצמים עבור התכנית שכתבת‪.‬‬
‫‪‬‬
‫כתבי תכנית שמייצרת רצף של ‪ 10‬חרוזים‪.‬‬
‫שרטטי תרשים עצמים מתאים לתכנית שכתבת‪.‬‬
‫האם החרוזים מהווים שרשרת? כן‪ /‬לא (הסבירי)‬
‫כיצד לדעתך יראה מבנה של שרשרת חרוזים? שרטטי תרשים עצמים מתאים‪.‬‬
‫נגדיר שרשרת חרוזים‪:‬‬
‫שרשרת יכולה להכיל חרוז אחד או‬
‫רצף של חרוזים קשורים זה לזה‬
‫ולכן תרשים עצמים של שרשרת חרוזים יראה כך‪:‬‬
‫חרוז‪1‬‬
‫חרוז‪2‬‬
‫חרוז‪3‬‬
‫‪- 64 -‬‬
‫חרוז‪4‬‬
‫חרוז‪5‬‬
‫התרשים מתאר באופן כללי את מבנה שרשרת החרוזים‪:‬‬
‫חרוז‪ 2‬קשור ל‪________ :‬‬
‫חרוז‪ 4‬קשור ל‪________ :‬‬
‫למי קשור חרוז‪___________ ?1‬‬
‫למי קשור חרוז‪____________ ?5‬‬
‫איזה חרוז לדעתך‪ ,‬נוצר הראשון בשרשרת החרוזים? (הסבירי) ________________________‬
‫הוסיפי עוד חרוז לשרשרת‪.‬‬
‫נתונה השרשרת הבאה‪:‬‬
‫ירוק‬
‫צהוב‬
‫אדום‬
‫צהוב‬
‫כחול‬
‫היעזרי במבנה המחלקה ‪ ,Bead‬ושרטטי תרשים עצמים מתאים‪.‬‬
‫תני דוגמא לעצם אחר (שאינו חרוז) שניתן לתאר אותו כשרשרת של "עצמים"‪ ,‬שרטטי תרשים שמתאר את השרשרת‪.‬‬
‫חסרה לנו האפשרות לתאר את הקשר בין החרוזים‪.‬‬
‫מאיזה טיפוס לדעתך‪ ,‬צריך להיות המשתנה שמגדיר את הקשר בין החרוזים?‬
‫כמה "קשרים" עלינו להגדיר?‬
‫האם הקשר שבין החרוזים הוא חלק מהחרוז?‬
‫אם כן‪ ,‬באיזה חרוז? הוסיפי לתרשים משהו שמתאר את הקשר שבין החרוזים‪.‬‬
‫הוסיפי לפרויקט שלך הגדרות מתאימות כך שכל חרוז יוכל "להיקשר" לחרוז אחר‪.‬‬
‫מה יהיה הערך של המשתנה כאשר החרוז אינו קשור לחרוז אחר?‬
‫מה יהיה ערכו כאשר הוא קשור לחרוז אחר בשרשרת?‬
‫‪- 65 -‬‬
‫אדום‬
‫לכל חרוז יש ‪ 2‬תכונות‪:‬‬
‫תכונה‪ :1‬צבע מטיפוס‪ ___________ :‬בשם ‪color‬‬
‫תכונה‪ :2‬הפניה לחרוז הבא מטיפוס‪ __________ :‬בשם ‪nextBead‬‬
‫שני את המחלקה ‪ Bead‬בהתאם לתרשים הבא‪:‬‬
‫המחלקה‪ :‬חרוז‬
‫‪Bead‬‬
‫תכונות‪ :‬צבע‬
‫‪_______ color‬‬
‫החרוז הבא‬
‫‪_______ nextBead‬‬
‫פעולות בונות‪:‬‬
‫פעולה שמקבלת צבע‬
‫פעולה שמקבלת צבע והפניה לחרוז הבא‬
‫פעולות נוספות‪:‬‬
‫פעולה שמחזירה את הצבע‬
‫פעולה שמחזירה את החרוז הבא בשרשרת‬
‫פעולה שמעדכנת את ההפניה לחרוז הבא‬
‫הפעולה ‪ToString‬‬
‫משימות‪:‬‬
‫‪ .1‬כתבי תכנית בדיקה‪ ,‬המייצרת שרשרת משלושה חרוזים בצבעים שונים ומציגה את רצף החרוזים‪.‬‬
‫‪ .2‬כתבי תכנית שתקלוט את מספר החרוזים בשרשרת ותייצר שרשרת מתאימה‪.‬‬
‫‪ .3‬כתבי פעולה חיצונית שמקבלת "שרשרת" ומחזירה את אורך השרשרת‪.‬‬
‫‪ .4‬כתבי פעולה חיצונית המקבלת "שרשרת" ומחזירה ‪ true‬אם השרשרת מעגלית ו ‪ false‬אם אינה מעגלית‪.‬‬
‫משימות מתקדמות‬
‫‪ .1‬הציעי טיפוס נתונים חדש בעל אותו רעיון‪ ,‬המאפשר למצוא את האיבר האמצעי‪ ,‬בשרשרת (אי זוגית) או צמד האיברים‬
‫האמצעיים בשרשרת(זוגית) בסריקה אחת‪.‬‬
‫‪ .2‬כתבי פעולה המקבלת הפניה לשרשרת חוליות והופכת את הפניות בה כך שהאיבר הראשון יהפוך לאחרון וכך בהתאמה‬
‫עד שהאחרון יהפוך לראשון‪ .‬הפעולה תחזיר הפניה לאיבר הראשון כעת‪.‬‬
‫‪ .3‬כתבי פעולה חיצונית שמקבלת "שרשרת" ומוציאה ממנה את האיברים שנחלקים בחמש ללא שארית‪.‬‬
‫‪- 66 -‬‬
‫מערך של רשימות (שרשרת חוליות)‬
‫פיתוח‪ :‬רחל בן עמי‪ ,‬מושית ולץ‬
‫תאור הרקע‬
‫‪‬‬
‫התלמידים כתבו מחלקות עם תכונות פשוטות ועם תכונות מורכבות‪.‬‬
‫‪‬‬
‫התלמידים כתבו מחלקות עם תכונות מטיפוס מערך ומטיפוס מערך של עצמים‪.‬‬
‫‪‬‬
‫התלמידים למדו על חוליה – עצם שתכונתו מטיפוס עצמו‪ ,‬למדו על רשימה שהיא שרשרת חוליות‪,‬‬
‫הכנסת איבר לרשימה והוצאת איבר מרשימה‪.‬‬
‫‪‬‬
‫פתרו בעיות מילוליות ‪ ,‬שהפתרון כלל ייצוג מחלקה ומימושה‪.‬‬
‫תכנים בהם תעסוק המעבדה‬
‫‪‬‬
‫רענון של תכונה מטיפוס מערך של עצמים פשוטים‪.‬‬
‫‪‬‬
‫יצירת שרשרת חוליות ממוינת באמצעות מיון הכנסה‪.‬‬
‫‪‬‬
‫תכונה שהיא מערך של שרשרת חוליות‪.‬‬
‫‪‬‬
‫כתיבת מחלקה הכוללת תכונה מטיפוס מערך של שרשרת חוליות‪.‬‬
‫חלק ראשון‪ :‬רענון‬
‫‪‬‬
‫בנית מחלקה של עצם פשוט‬
‫‪‬‬
‫בנית מחלקה המכילה תכונה מטיפוס מערך של עצמים‬
‫‪‬‬
‫הגדרה ויצירת שרשרת חוליות‬
‫משימה ‪1‬‬
‫הגדר מחלקה תלמיד ‪ - Student -‬שמאפייניה הם שם‪ ,‬מספר ת"ז ומספר הפעמים שהתלמיד ניגש למבחן‪.‬‬
‫המחלקה מכילה פעולה בונה‪ ,‬פעולות קובעות‪ ,‬פעולות מאחזרות ופעולה המחזירה מחרוזת המתארת את‬
‫פרטי התלמיד‪.‬‬
‫לפניך קטע קוד ממחלקה המתארת קבוצה של ‪ 10‬מורים‪ ,‬לכל מורה תלמיד אחד‪ .‬למחלקה יש תכונה אחת‬
‫מטיפוס מערך של תלמידים‪ .‬מורה מיוצג ע"י מספר בין ‪ 0‬ל‪( 9-‬אינדקס המערך)‬
‫‪public class ArrTech‬‬
‫{‬
‫;‪Private Student[] arr‬‬
‫)(‪public ArrTech‬‬
‫{‬
‫;]‪this.arr = new Student[10‬‬
‫}‬
‫}‬
‫‪- 67 -‬‬
‫התכונה של המחלקה מטיפוס מערך של עצמים‪ .‬העצמים מטיפוס ‪ .Student‬הפעולה הבונה יוצרת מערך ובו‬
‫הפניות מטיפוס ‪ .Student‬ברגע יצירת המערך ההפניות מאותחלות ל ‪ – null‬ערך ברירת המחדל‪.‬‬
‫משימה ‪2‬‬
‫א‪ .‬התחל פרויקט חדש וצרף אליו את המחלקה ‪ Student‬שכתבת במשימה הראשונה‪.‬‬
‫ב‪ .‬הוסף את המחלקה ‪ , ArrStud‬ממשו במחלקה את הפעולה הבאה‪:‬‬
‫)‪ , AddStud(Student stud, int num‬הפעולה מקבלת תלמיד ומספר מורה בין ‪ 0‬ל‪ , 9 -‬אם למורה‬
‫אין תלמיד הפעולה מצרפת את התלמיד למורה אחרת הפעולה לא עושה דבר‪.‬‬
‫לפניך קטע קוד המגדיר רשימה של תלמידים ומכניס לשרשרת תלמיד‪.‬‬
‫;)‪","123456",2‬שגיא"(‪Student stud=new Student‬‬
‫;)‪Node<Student> listStud = new Node<Student>(stud‬‬
‫}‬
‫המשתנה ‪ stud‬מכיל הפניה לעצם מטיפוס ‪.Student‬‬
‫המשתנה ‪ listStud‬מכיל הפניה לחוליה הראשונה ברשימה‪.‬‬
‫משימה ‪3‬‬
‫בנה פעולה בשם )‪InsertToSortList(Node<Student> listStud, Student stud‬‬
‫הפעולה מקבלת שרשרת חוליות ממוינת ותלמיד‪.‬‬
‫הפעולה תשבץ את התלמיד ברשימה לסוף הרצף המתאים‪.‬‬
‫משימה ‪4‬‬
‫הגדר מערך חד ממדי ‪ ar‬בגודל ‪ ,10‬מטיפוס >‪.Node<Student‬‬
‫כל תא במערך ‪ ar‬מייצג רשימה של תלמידים‪.‬‬
‫חלק ב‪ :‬הגדרת מערך של רשימות‬
‫לפניך קטע קוד המגדיר מערך ‪ arr‬בגודל ‪ 10‬מטיפוס >‪ .Node<Student‬כל תא במערך מכיל רשימת תלמידים‪.‬‬
‫;]‪arr = new Node<Student>[10‬‬
‫;)‪Student stud=new Student("Amir","123456",1‬‬
‫;)‪InsertToSortList(arr[0],stud‬‬
‫‪- 68 -‬‬
‫קטע הקוד יוצר מערך ‪ arr‬בגודל ‪ ,10‬בכל תא במערך יש הפניה מטיפוס >‪ Node<Student‬לרשימה‪.‬‬
‫ברגע יצירת המערך ההפניות מאותחלות ל ‪ – null‬ערך ברירת המחדל‪.‬‬
‫המשתנה ‪ stud‬מכיל הפניה לעצם מטיפוס ‪.Student‬‬
‫השורה השלישית בקוד‪ :‬קריאה לפעולה המכניסה לרשימה הנמצאת בתא ‪ 0‬במערך ‪ - aar[0] -‬את‬
‫התלמיד ‪ stud‬למקום המתאים ברשימה‪.‬‬
‫חלק שלישי‪ :‬כתיבת מחלקה הכוללת מערך של רשימות‬
‫בחלק זה תתנסה בכתיבת מחלקה בהתאם למה שתרגלת עד כה‪.‬‬
‫משימה ‪5‬‬
‫במשרד הרישוי בפתח תקוה רשומים ‪ 100‬מורים לנהיגה הרשאים להגיש את תלמידיהם למבחן רישוי‪.‬‬
‫כל מורה מיוצג ע"י מספר בין ‪ 1‬ל‪ 100-‬ולכל מורה רשימת תלמידים המוכנים לגשת למבחן‪.‬‬
‫בכל יום נקבעת במשרד הרישוי רשימת תלמידים שייגשו באותו היום לבחינה‪.‬‬
‫רשימת הנבחנים נקבעת האופן הבא‪ :‬כל מורה יצרף לרשימת הנבחנים לכל היותר חמישה מתלמידיו על פי‬
‫הסדר הבא‪ :‬תלמידים שלא ניגשו כלל לבחינה‪ ,‬תלמידים שניגשו פעם אחת ונכשלו וכך הלאה‪.‬‬
‫הנתונים הנשמרים עבור כל תלמיד הם‪ :‬שם‪ ,‬מספר ת"ז ומספר פעמים שניגש התלמיד לבחינה‪.‬‬
‫להלן ממשק חלקי לניהול המורים במשרד הרישוי ‪:‬‬
‫פעולה המקבלת מספר מורה‪ ,‬ותלמיד‪ ,‬מוסיפה את‬
‫התלמיד לרשימת הנבחנים של המורה‪.‬‬
‫)‪Insert _stud(int techNum,Stud stu‬‬
‫פעולה המחזירה רשימת של שמות הנבחנים ליום‪.‬‬
‫)(‪TestListForDay‬‬
‫א‪ .‬כתוב מחלקה בשם ‪ ,Stud‬בחר ייצוג למחלקה וממש את הפעולה הבונה‪,‬‬
‫פעולות איחזור ‪ ,Get‬פעולות קביעה ‪ Set‬ופעולת ‪.ToString‬‬
‫ב‪ .‬הגדר מחלקה בשם ‪ Techer‬לניהול מורים במשרד רישוי ‪ ,‬בחר ייצוג למחלקה‬
‫וממש את הפעולה הבונה‪.‬‬
‫ג‪ .‬ממש את הפעולות הרשומות בממשק החלקי‪.‬‬
‫‪- 69 -‬‬
)‫מחסנית (חשיפה ראשונה לטיפוס‬
‫ רחל לודמר ורחלי צרניחוב‬:‫פיתוח‬
C# ‫גרסה‬
1 ‫משימה מספר‬
.‫ חשיפה לטיפוס הנתונים המופשט מחסנית‬:‫מטרה‬
.‫ הקלד את התוכנית הבאה ורשום את הפלט כפי שהוא מופיע על צג המחשב‬.‫א‬
using System;
using System.Linq;
using System.Text;
using Unit4.CollectionsLib;
namespace StackMovilim
{
class Program
{
static void Main(string[] args)
{
Stack<int> st = new Stack<int>();
st.Push(5);
Console.WriteLine(st);
__________________
st.Push(1);
Console.WriteLine(st);
__________________
st.Push(34);
Console.WriteLine(st);
__________________
st.Pop();
Console.WriteLine(st);
__________________
st.Push(10);
Console.WriteLine(st);
__________________
st.Pop();
Console.WriteLine(st);
__________________
st.Push(25);
Console.WriteLine(st);
__________________
st.Push(8);
Console.WriteLine(st);
__________________
- 70 -
st.Pop();
Console.WriteLine(st);
__________________
st.Pop();
Console.WriteLine(st);
__________________
}
}
}
.‫ הקלד את התוכנית הבאה ורשום את הפלט כפי שהוא מופיע על צג המחשב‬.‫ב‬
using System;
using System.Linq;
using System.Text;
using Unit4.CollectionsLib;
namespace StackMovilim
{
class Program
{
static void Main(string[] args)
{
Stack<string> st = new Stack<string>();
st.Push("David");
Console.WriteLine(st);
__________________
st.Push("Tamar");
Console.WriteLine(st);
__________________
st.Push("Efrat");
Console.WriteLine(st);
__________________
st.Pop();
Console.WriteLine(st);
__________________
st.Push("Lital");
Console.WriteLine(st);
__________________
st.Pop();
Console.WriteLine(st);
__________________
st.Push("Eli");
Console.WriteLine(st);
__________________
}
}
}
- 71 -
‫סיכום ביניים‬
?Push ‫מהי פעולה‬
___________________________________________________
?Pop ‫מהי פעולת‬
____________________________________________________
2 ‫משימה מספר‬
.‫הקלד את התוכנית הבאה והרץ אותה‬
using System;
using System.Linq;
using System.Text;
using Unit4.CollectionsLib;
namespace StackMovilim
{
class Program
{
static void Main(string[] args)
{
Stack<string> st = new Stack<string>();
st.Push("David");
Console.WriteLine(st);
st.Push("Lital");
Console.WriteLine(st);
st.Pop();
Console.WriteLine(st);
st.Pop();
Console.WriteLine(st);
st.Pop();
Console.WriteLine(st);
}
}
}
- 72 -
‫ תאר מה קרה במהלך הרצת התכנית‬.‫א‬
___________________________________________________________
___________________________________________________________
?Push ‫ מה צריך לדעתך לבדוק (אם בכלל) לפני פעולת‬.‫ב‬
___________________________________________________________
?Pop ‫ מה צריך לדעתך לבדוק (אם בכלל) לפני פעולת‬.‫ג‬
___________________________________________________________
3 ‫משימה מספר‬
.‫הקלד את התוכנית הבאה‬
:‫הוסף לתכנית הוראות במקום המסומן כך שיציגו את הפלטים הבאים‬
.‫ הצבע השני מראש המחסנית‬3.1
colors.IsEmpty(); ‫ היעזר בפעולה הבוליאנית‬.‫ הצבע הנמצא בתחתית המחסנית‬3.2
‫ראש המחסנית‬
‫ראש המחסנית‬
.‫הרץ את התכנית עבור שתי רשימות הצבעים הבאות‬
blue white yellow green .‫א‬
red blue white black yellow green .‫ב‬
using System;
using System.Linq;
using System.Text;
using Unit4.CollectionsLib;
namespace StackMovilim
{
class Program
{
static void Main(string[] args)
{
Stack<string> colors = new Stack<string>();
string col;
Console.WriteLine("Enter color. To finish type 'sof'");
col = Console.ReadLine();
while (col != "sof")
{
- 73 -
‫;)‪colors.Push(col‬‬
‫;)"'‪Console.WriteLine("Enter color. To finish type 'sof‬‬
‫;)(‪col = Console.ReadLine‬‬
‫}‬
‫‪ …….....‬המקום המסומן …………‬
‫}‬
‫}‬
‫}‬
‫‪ 3.3‬אילו שורות קוד יש להוסיף והיכן‪ ,‬אם מעוניינים לדעת כמה את כמות הצבעים במחסנית?‬
‫___________________________________________________________‬
‫___________________________________________________________‬
‫___________________________________________________________‬
‫סיכום ביניים‬
‫א‪ .‬כדי לדעת את ערכו של איבר הנמצא במקום ה ‪ k‬מראש המחסנית‪ ,‬צריך לבצע את ההוראות‬
‫הבאות‪:‬‬
‫___________________________________________________________‬
‫___________________________________________________________‬
‫___________________________________________________________‬
‫___________________________________________________________‬
‫___________________________________________________________‬
‫___________________________________________________________‬
‫ב‪.‬‬
‫בהמשך לסעיף הקודם המחסנית "מתקלקלת" בעת הוצאת האיברים‪.‬‬
‫מה יש להוסיף‪/‬לשנות כדי שניתן יהיה לשחזר את ערכי המחסנית?‬
‫_________________________________________________________‬
‫___________________________________________________________‬
‫___________________________________________________________‬
‫___________________________________________________________‬
‫ג‪.‬‬
‫הסבר במילים את תפקיד הפעולה ;)(‪IsEmpty‬‬
‫___________________________________________________________‬
‫___________________________________________________________‬
‫‪- 74 -‬‬
4 ‫משימה מספר‬
.Top ‫ ו‬Pop ‫ הבחנה בין הפעולות‬:‫מטרה‬
.‫הקלד את התוכנית הבאה ורשום את הפלט‬
using System;
using System.Linq;
using System.Text;
using Unit4.CollectionsLib;
namespace StackMovilim
{
class Program
{
static void Main(string[] args)
{
Stack<int> numbers = new Stack<int>();
int num;
for (int i = 1; i < 6; i++)
{
numbers.Push(i);
}
Console.WriteLine(numbers);
__________________
num = numbers.Top();
Console.WriteLine(num);
__________________
num = numbers.Pop();
Console.WriteLine(num);
__________________
num = numbers.Top();
Console.WriteLine(num);
__________________
num = numbers.Top();
Console.WriteLine(num);
__________________
num = numbers.Pop();
Console.WriteLine(num);
__________________
num = numbers.Pop();
Console.WriteLine(num);
__________________
}
}
}
- 75 -
‫סיכום ביניים‬
‫הסבר במילים את ההבדל בין הפעולות ‪ Pop‬ו ‪Top‬‬
‫___________________________________________________________‬
‫___________________________________________________________‬
‫מחסנית ‪ -‬דף סיכום – גרסת סי שרפ‬
‫מושגים‬
‫מחסנית‬
‫‪Stack‬‬
‫נכנס אחרון יוצא ראשון‬
‫‪Last In First Out - LIFO‬‬
‫פעולה בונה‬
‫‪Stack‬‬
‫דחוף למחסנית‬
‫‪Push‬‬
‫שלוף מראש המחסנית‬
‫‪Pop‬‬
‫הצץ לראש המחסנית‬
‫‪Top‬‬
‫האם המחסנית ריקה‬
‫‪IsEmpty‬‬
‫תיאור המחסנית‬
‫‪ToString‬‬
‫חומר למחשבה‬
‫הצג שני שימושים‪ ,‬מחיי היום‪-‬יום או מתחום המחשבים‪ ,‬המצריכים שימוש במבנה מחסנית‪.‬‬
‫___________________________________________________________‬
‫___________________________________________________________‬
‫___________________________________________________________‬
‫סיפור הרס"ר והנעץ ‪ -‬קרא את הסיפור מהספר‪" :‬עיצוב תוכנה – ספר לתלמיד" המרכז להוראת‬
‫המדעים‪ ,‬אוניברסיטת ירושלים‬
‫‪- 76 -‬‬
‫(המשך הסיפור בעמוד הבא)‬
‫‪- 77 -‬‬
- 78 -
‫איך הסיפור הנ"ל מתקשר לנושא המחסנית?‬
‫___________________________________________________________‬
‫___________________________________________________________‬
‫___________________________________________________________‬
‫תרגול‬
‫‪ .1‬כתוב מחלקה גנרית עבור מחסנית בשם ‪.Stack‬‬
‫יש לממש את הפעולות הבאות‪:‬‬
‫פעולה בונה‬
‫‪Stack‬‬
‫דחוף למחסנית‬
‫‪Push‬‬
‫שלוף מראש המחסנית‬
‫‪Pop‬‬
‫הצץ לראש המחסנית‬
‫‪Top‬‬
‫האם המחסנית ריקה‬
‫‪IsEmpty‬‬
‫תיאור המחסנית‬
‫‪ToString‬‬
‫‪ .2‬סיפור פז"מ (ותק) ‪ -‬קרא את הסיפור מהספר‪" :‬עיצוב תוכנה – ספר לתלמיד" המרכז להוראת‬
‫המדעים‪ ,‬אוניברסיטת ירושלים‬
‫(הסיפור מופיע בעמוד הבא)‬
‫כתוב תוכנית למימוש הסיפור הנ"ל ‪.‬‬
‫‪- 79 -‬‬
- 80 -
‫מחסנית – חשיפה ראשונה לטיפוס – גרסת ג'אווה‬
1 ‫משימה מספר‬
.‫ חשיפה לטיפוס הנתונים המופשט מחסנית‬:‫מטרה‬
.‫ הקלד את התוכנית הבאה ורשום את הפלט (בקו המסומן) כפי שהוא מופיע על צג המחשב‬.‫ג‬
import java.util.*;
import unit4.collectionsLib.Stack;
public class Program
{
static Scanner reader=new Scanner(System.in);
public static void main(String[] args)
{
Stack<Integer> st = new Stack<Integer>();
st.push(5);
System.out.println(st);
__________________
st.push (1);
System.out.println(st);
__________________
st.push (34);
System.out.println(st);
__________________
st.pop();
System.out.println(st);
__________________
st.push(10);
System.out.println(st);
__________________
st.pop();
System.out.println(st);
__________________
st.push(25);
System.out.println(st);
__________________
st.push(8);
System.out.println(st);
__________________
st.pop();
System.out.println(st);
st.pop();
__________________
System.out.println(st);
__________________
}
}
- 81 -
.‫ הקלד את התוכנית הבאה ורשום את הפלט (בקו המסומן) כפי שהוא מופיע על צג המחשב‬.‫ד‬
import java.util.*;
import unit4.collectionsLib.Stack;
public class Program
{
static Scanner reader=new Scanner(System.in);
public static void main(String[] args)
{
Stack<String> st = new Stack<Stringr>();
st.push("David");
System.out.println(st);
__________________
st.push("Tamar");
System.out.println(st);
__________________
st.push("Efrat");
System.out.println(st);
__________________
st.pop();
System.out.println(st);
__________________
st.push("Lital");
System.out.println(st);
__________________
st.pop();
System.out.println(st);
__________________
st.push("Eli");
System.out.println(st);
__________________
}
}
‫סיכום ביניים‬
?push ‫מהי פעולה‬
___________________________________________________
?pop ‫מהי פעולת‬
____________________________________________________
- 82 -
2 ‫משימה מספר‬
.‫הקלד את התוכנית הבאה והרץ אותה‬
import java.util.*;
import unit4.collectionsLib.Stack;
public class Program
{
static Scanner reader=new Scanner(System.in);
public static void main(String[] args)
{
Stack<String> st = new Stack<Stringr>();
st.push("David");
System.out.println(st);
st.push("Lital");
System.out.println(st);
st.pop();
System.out.println(st);
st.pop();
System.out.println(st);
st.pop();
System.out.println(st);
}
}
‫ תאר מה קרה במהלך הרצת התכנית‬.‫ד‬
___________________________________________________________
___________________________________________________________
?push ‫ מה צריך לדעתך לבדוק (אם בכלל) לפני פעולת‬.‫ה‬
___________________________________________________________
?pop ‫מה צריך לדעתך לבדוק (אם בכלל) לפני פעולת‬
___________________________________________________________
- 83 -
.‫ו‬
3 ‫משימה מספר‬
.‫הקלד את התוכנית הבאה‬
:‫הוסף לתכנית הוראות במקום המסומן כך שיציגו את הפלטים הבאים‬
.‫ הצבע השני מראש המחסנית‬3.1
colors.isEmpty(); ‫ היעזר בפעולה הבוליאנית‬.‫ הצבע הנמצא בתחתית המחסנית‬3.2
.‫הרץ את התכנית עבור שתי רשימות הצבעים הבאות‬
‫ראש המחסנית‬
blue white yellow green .‫ג‬
red blue white black yellow green .‫ד‬
‫ראש המחסנית‬
import java.util.*;
import unit4.collectionsLib.Stack;
public class Program
{
static Scanner reader=new Scanner(System.in);
public static void main(String[] args)
{
Stack<String> colors = new Stack<String>();
String col;
System.out.println("Enter color. To finish type 'sof' ");
col = reader.next();
while (!col.equals("sof"))
{
colors.push(col);
System.out.println("Enter color. To finish type 'sof'");
col = reader.next();
}
………… ‫…… המקום המסומן‬.....
}
}
?‫ אם מעוניינים לדעת כמה את כמות הצבעים במחסנית‬,‫ אילו שורות קוד יש להוסיף והיכן‬3.3
___________________________________________________________
___________________________________________________________
___________________________________________________________
- 84 -
‫סיכום ביניים‬
‫ד‪ .‬כדי לדעת את ערכו של איבר הנמצא במקום ה ‪ k‬מראש המחסנית‪ ,‬צריך לבצע את ההוראות‬
‫הבאות‪:‬‬
‫___________________________________________________________‬
‫___________________________________________________________‬
‫___________________________________________________________‬
‫___________________________________________________________‬
‫___________________________________________________________‬
‫___________________________________________________________‬
‫בהמשך לסעיף הקודם המחסנית "מתקלקלת" בעת הוצאת האיברים‪.‬‬
‫ה‪.‬‬
‫מה יש להוסיף‪/‬לשנות כדי שניתן יהיה לשחזר את ערכי המחסנית?‬
‫___________________________________________________________‬
‫___________________________________________________________‬
‫___________________________________________________________‬
‫___________________________________________________________‬
‫ו‪.‬‬
‫הסבר במילים את תפקיד הפעולה ;)(‪isEmpty‬‬
‫___________________________________________________________‬
‫___________________________________________________________‬
‫משימה מספר ‪4‬‬
‫מטרה‪ :‬הבחנה בין הפעולות ‪ Pop‬ו ‪.Top‬‬
‫הקלד את התוכנית הבאה ורשום את הפלט (בקו המסומן)‪.‬‬
‫;*‪import java.util.‬‬
‫;‪import unit4.collectionsLib.Stack‬‬
‫‪public class Program‬‬
‫{‬
‫;)‪static Scanner reader=new Scanner(System.in‬‬
‫)‪public static void main(String[] args‬‬
‫{‬
‫;)(>‪Stack<Integer> st = new Stack<Integer‬‬
‫;‪int num‬‬
‫)‪for (int i = 1; i < 6; i++‬‬
‫‪- 85 -‬‬
{
numbers.push(i);
}
System.out.println(numbers);
__________________
num = numbers.top();
System.out.println(num);
__________________
num = numbers.pop();
System.out.println(num);
__________________
num = numbers.top();
System.out.println(num);
__________________
num = numbers.top();
System.out.println(num);
__________________
num = numbers.pop();
System.out.println(num);
__________________
num = numbers.pop();
System.out.println(num);
__________________
}
}
‫סיכום ביניים‬
top ‫ ו‬pop ‫הסבר במילים את ההבדל בין הפעולות‬
___________________________________________________________
___________________________________________________________
‫מושגים‬
- ‫מחסנית – דף סיכום‬
‫מחסנית‬
‫נכנס אחרון יוצא ראשון‬
‫פעולה בונה‬
‫דחוף למחסנית‬
‫שלוף מראש המחסנית‬
‫הצץ לראש המחסנית‬
‫האם המחסנית ריקה‬
‫תיאור המחסנית‬
Stack
Last In First Out - LIFO
Stack
push
pop
top
isEmpty
toString
- 86 -
‫חומר למחשבה‬
‫הצג שני שימושים‪ ,‬מחיי היום‪-‬יום או מתחום המחשבים‪ ,‬המצריכים שימוש במבנה מחסנית‪.‬‬
‫___________________________________________________________‬
‫___________________________________________________________‬
‫___________________________________________________________‬
‫סיפור הרס"ר והנעץ ‪ -‬קרא את הסיפור מהספר‪" :‬עיצוב תוכנה – ספר לתלמיד" המרכז להוראת המדעים‪,‬‬
‫אוניברסיטת ירושלים‬
‫איך הסיפור הנ"ל מתקשר לנושא המחסנית?‬
‫___________________________________________________________‬
‫___________________________________________________________‬
‫___________________________________________________________‬
‫___________________________________________________________‬
‫תרגול‬
‫‪ .1‬כתוב מחלקה גנרית עבור מחסנית בשם ‪.Stack‬‬
‫יש לממש את הפעולות הבאות‪:‬‬
‫פעולה בונה‬
‫דחוף למחסנית‬
‫שלוף מראש המחסנית‬
‫הצץ לראש המחסנית‬
‫האם המחסנית ריקה‬
‫תיאור המחסנית‬
‫‪Stack‬‬
‫‪push‬‬
‫‪pop‬‬
‫‪top‬‬
‫‪isEmpty‬‬
‫‪toString‬‬
‫‪ .2‬סיפור פז"מ (ותק) ‪ -‬קרא את הסיפור מהספר‪" :‬עיצוב תוכנה – ספר לתלמיד" המרכז להוראת‬
‫המדעים‪ ,‬אוניברסיטת ירושלים‬
‫כתוב תוכנית למימוש הסיפור הנ"ל ‪.‬‬
‫‪- 87 -‬‬
‫מחלקת שירות הכוללת אוסף פעולות שימושיות‬
‫המטפלות ברשימה מקושרת של מספרים שלמים‬
‫פיתוח‪ :‬אוי גרינולד‪ ,‬דורית כהן‪ ,‬משה שטיינר‬
‫מדריך למורה‬
‫מתאים לשתי שפות התכנות‪ Java :‬ו‪C# -‬‬
‫מטרת המשימה‪ :‬בניית מחלקת שירות המכילה אוסף פעולות שימושיות על רשימה של מספרים שלמים‪.‬‬
‫מבנה המסמך‪:‬‬
‫● מטרות ודגשים‬
‫● הוראות לתלמיד‬
‫● ממשק המחלקה חוליה >‪Node<T‬‬
‫● הנחיות עבודה‬
‫מטרות ודגשים‪:‬‬
‫‪‬‬
‫הכרות עם מבנה נתונים דינמי רשימה‪.‬‬
‫‪‬‬
‫לחדד את המושג של הפנייה ועצם המכיל תכונה שהיא הפנייה לאותו העצם‪,‬‬
‫שבעזרתו ניתן לבנות את המבנה רשימה‪.‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫הפנייה לחוליה מקבלת משמעויות שונות בהקשרים שונים‪:‬‬
‫‪o‬‬
‫רשימה‪ ,‬כאשר הכוונה הפנייה לחוליה הראשונה ברשימה‬
‫‪o‬‬
‫חוליה בודדת להוספה או מחיקה‬
‫‪o‬‬
‫מיקום ברשימה‬
‫אין חוליה ריקה אבל יש רשימה ריקה‪ :‬זוהי רשימה ללא חוליות‪ .‬בהפניה אליה נציב את הערך ‪. null‬‬
‫יש לתת את הדעת לכך שבפעולות היוצרות שינוי על הרשימה נכתוב פעולות המחזירות הפנייה לרשימה‬
‫חדשה ולא ‪ . void‬בניגוד למה שהכרנו במערכים וזאת עקב בעייתיות של טיפול בחוליה ראשונה‬
‫ברשימה או ברשימה ריקה‪.‬‬
‫‪‬‬
‫לשם פשטות‪ ,‬החלטנו‪ ,‬באופן שרירותי‪ ,‬לבנות מחלקת שירות לטיפול ברשימה של שלמים‪ .‬בסיכום‬
‫המעבדה מומלץ לערוך דיון עם התלמידים‪ ,‬המברר אילו פעולות ניתן ליישם על חוליה גנרית‪ ,‬ומהם‬
‫השינויים הדרושים לכך‪.‬‬
‫‪- 88 -‬‬
‫ממשק המחלקה ‪Node<T> :‬‬
‫תיאור הפעולה‬
‫יעילות‬
‫כותרת הפעולה – ‪#C‬‬
‫)‪public Node(T x‬‬
‫כותרת הפעולה ‪Java -‬‬
‫)‪public Node(T x‬‬
‫יוצרת חוליה בעלת ערך ‪x‬‬
‫והפנייה לחוליה ‪next‬‬
‫‪public Node(T x,‬‬
‫)‪Node<T> next‬‬
‫‪public Node(T x,‬‬
‫)‪Node<T> next‬‬
‫)‪O(1‬‬
‫מחזירה את ערך החוליה‬
‫)(‪public T GetValue‬‬
‫)(‪public T getValue‬‬
‫)‪O(1‬‬
‫>‪public T Node<T‬‬
‫)(‪GetNext‬‬
‫>‪public Node<T‬‬
‫)(‪getNext‬‬
‫)‪O(1‬‬
‫משנה את ערך החוליה ל ‪x‬‬
‫‪public void SetValue (T‬‬
‫)‪x‬‬
‫‪public void setValue‬‬
‫)‪(T x‬‬
‫)‪O(1‬‬
‫משנה את ההפניה לחוליה‬
‫הבאה ל ‪next‬‬
‫‪public void SetNext‬‬
‫)‪(Node<T> next‬‬
‫‪public void setNext‬‬
‫)‪(Node<T> next‬‬
‫)‪O(1‬‬
‫)(‪public bool HasNext‬‬
‫‪public boolean‬‬
‫)(‪hasNext‬‬
‫)‪O(1‬‬
‫)(‪public String ToString‬‬
‫‪public String‬‬
‫)(‪toString‬‬
‫)‪O(1‬‬
‫יוצרת חוליה בעלת ערך ‪x‬‬
‫והפנייה ל ‪null‬‬
‫מחזירה את ההפניה לחוליה‬
‫העוקבת או ‪null‬‬
‫מחזירה 'אמת' אם יש חוליה‬
‫עוקבת‪' ,‬שקר'‪-‬אחרת‪.‬‬
‫מחזירה מחרוזת המתארת‬
‫את ערך החוליה‬
‫)‪O(1‬‬
‫הנחיות והערות לתלמיד‬
‫(‪ )1‬ביצירת המחלקות יש להשתמש בטיפוס >‪Node<T‬‬
‫‪Java‬‬
‫לשם כך ייבא את המחלקה מחבילת התוכנות ‪unit4‬‬
‫‪C#‬‬
‫לשם כך הוסף את ספרית ‪ unit4.dll‬לרשימת ה‪,reference-‬‬
‫;‪import unit4.collectionsLib.Node‬‬
‫בנוסף‪ ,‬יש להוסיף התייחסות לספריה בראש הקובץ‪:‬‬
‫זכרו למחוק את כל משפטי ה‪ using-‬האחרים למעט‬
‫;‪using Unit4.CollectionsLib‬‬
‫;‪using System‬‬
‫(‪ )2‬הוסף בכל פעם מימוש של פעולה אחת ובדוק אותה‪ .‬לאחר שבדקת שהיא עובדת ‪ -‬עבור לפעולה הבאה וכך הלאה‪.‬‬
‫(‪ )3‬ממש את הפעולות שמסומנות ב (*) הן באופן איטרטיבי (בלולאה) והן באופן רקורסיבי‪.‬‬
‫הוסף לשם הפעולה ‪ ,R‬למשל‪:‬‬
‫‪ Java‬הפעולה האיטרטיבית ‪ sum‬תיקרא ‪ sumR‬בצורתה הרקורסיבית‪.‬‬
‫‪C#‬‬
‫הפעולה האיטרטיבית ‪ Sum‬תיקרא ‪ SumR‬בצורתה הרקורסיבית‪.‬‬
‫‪- 89 -‬‬
‫(‪ )4‬לכל אחת מהפעולות‪ ,‬נתח את היעילות‪ .‬נמק תשובתך‪.‬‬
‫(‪ )5‬באומרנו "רשימה" ‪ ,‬הכוונה להפניה לחוליה ראשונה ברשימה או ‪ null‬אם היא ריקה‪.‬‬
‫(‪ )6‬הקפד לתת שמות שמרמזים על תפקיד ההפניה לעצם מטיפוס <‪. Node<T‬‬
‫▪‬
‫אם משמעותו רשימה ‪ ,‬קבע שם כגון‪ lst, list :‬וכדומה‪.‬‬
‫▪‬
‫אם משמעותו חוליה בודדת‪ ,‬קבע שם כגון‪. node :‬‬
‫▪‬
‫אם משמעותו מקום ברשימה‪ ,‬קבע שם כגון‪ position, pos, p :‬וכדומה‪.‬‬
‫הנחיות והערות למורה‬
‫(‪ )1‬אוסף הפעולות המופיעות במסמך לתלמיד מדורגות מהקל לקשה‪.‬‬
‫(‪ )2‬הפעולות ‪ 1-13‬הן בסיסיות ומומלץ שכל תלמיד יממש אותן‪.‬‬
‫(‪ )3‬מומלץ לוודא שהתלמידים מגוונים את מימוש הפעולות‪ ,‬חלק באופן איטרטיבי וחלק באופן רקורסיבי‪.‬‬
‫(‪ )4‬אוסף פעולות זה הוא בגדר המלצה‪ .‬כל מורה יכול לבחור כראות עיניו אילו פעולות לתת למעבדה בכתה‪ ,‬איזה‬
‫לשיעורי בית ואיזה לבחנים או מבחנים‪.‬‬
‫(‪ )5‬הפעולות חולקו לקבוצות על פי סוגים שונים‪.‬‬
‫(‪ )6‬מומלץ שהתלמיד יממש לפחות פעולה אחת מכל קבוצה‪.‬‬
‫(‪ )7‬לגבי פעולות מורכבות יותר‪ ,‬מומלץ לערוך דיון עם התלמידים על אופן המימוש ולהציג פתרונות שונים בפני‬
‫הכתה‪ .‬חשוב לדון ביעילות הפעולות על פי המימוש הנבחר‪.‬‬
‫(‪ )8‬יש לשים לב למימוש פשוט של פעולה תוך זימון פעולה אחרת מאוסף הפעולות‪.‬‬
‫לדוגמה בשפת ‪ :Java‬מימוש הפעולה ‪ isSameValues‬ישתמש בפעולה ‪. isAllExist‬‬
‫בשפת ‪ : C#‬מימוש הפעולה ‪ IsSameValues‬ישתמש בפעולה ‪. IsAllExist‬‬
‫(‪ )9‬במימוש רקורסיבי‪ ,‬ניתן לזמן פעולת עזר רקורסיבית עם פרמטרים נוספים לפתרון פשוט וקל‪.‬‬
‫(‪)10‬‬
‫באוסף הפעולות קיימים שני סוגים של מיון‪ :‬מיון‪-‬הכנסה ומיון‪-‬בחירה‪.‬‬
‫מיון‪-‬הכנסה משתמש בפעולה הכנס‪-‬לרשימה‪-‬ממוינת ולכן הפעולה תחזיר הפנייה לרשימה חדשה‪.‬‬
‫לעומת זאת‪ ,‬במיון‪-‬בחירה יש למצוא בכל שלב את המיקום של הערך הקטן ביותר מהמיקום הנוכחי ועד לסוף‬
‫הרשימה ולבצע החלפה‪.‬‬
‫‪- 90 -‬‬
‫במקרה זה הפעולה לא תחזיר רשימה חדשה אלא תשנה את הקיימת‪ .‬כלומר‪ ,‬הפעולה תוגדר כ‪. void -‬‬
‫התייחסות למימוש חלק מהפעולות‬
‫פעולה ‪ :12‬סכום ערכים במקומות אי‪-‬זוגיים‪.‬‬
‫יש לשים לב שלא יבצעו פעמיים קידום על הרשימה מבלי לברר קודם שניתן‪.‬‬
‫פעולות ‪ :26+27‬מיזוג וחיתוך רשימות ממוינות‬
‫הציגו בפני התלמידים שתי אפשרויות‪:‬‬
‫האחת‪ ,‬שיוצרת רשימה חדשה ויוצרת חוליות חדשות עם ערכים מהרשימות המקוריות תוך שמירה על סדר‬
‫ממוין‪.‬‬
‫השנייה‪ ,‬מחזירה הפנייה לרשימת המיזוג או רשימת החיתוך תוך שימוש בחוליות הקיימות של שתי‬
‫הרשימות‪.‬‬
‫פעולה ‪ :28‬האם כל ערכי רשימה ‪ 2‬נמצאים ברשימה ‪.1‬‬
‫בשפת ‪ : Java‬שימוש בפעולה ‪isExist‬‬
‫בשפת ‪ : C#‬שימוש בפעולה ‪IsExist‬‬
‫פעולה ‪ :29‬האם הערכים בשתי הרשימות זהים ‪ ,‬לא חשוב הסדר‪.‬‬
‫בשפת ‪ :Java‬שימוש בפעולה ‪isAllExists‬‬
‫בשפת ‪ : C#‬שימוש בפעולה ‪IsAllExists‬‬
‫פעולה ‪ :30‬האם אין ערכים משותפים בשתי הרשימות‬
‫בשפת ‪ : Java‬שימוש ב ‪isExist‬‬
‫בשפת ‪ : C#‬שימוש בפעולה ‪IsExist‬‬
‫שאלה לדיון‪ :‬איך היית משנה את מימוש הפעולה אם שתי הרשימות היו ממוינות בסדר עולה?‬
‫תשובה‪:‬‬
‫שימוש בפועלה ‪ cut‬העובדת על רשימות ממוינות‪.‬‬
‫פעולה ‪ :32‬האם רשימה ‪ 2‬מוכלת ברשימה ‪1‬‬
‫הפעולה משתמשת בפעולה ‪ :30‬האם רשימה ‪ 2‬מוכלת ברשימה ‪ 1‬מראשיתה‪.‬‬
‫‪- 91 -‬‬
‫מחלקת שירות הכוללת אוסף פעולות שימושיות‬
‫המטפלות ברשימה מקושרת של מספרים שלמים‬
‫גירסת ‪C#‬‬
‫מטרת המשימה‪:‬‬
‫בניית מחלקת שירות המכילה אוסף פעולות שימושיות על רשימת חוליות מקושרת של מספרים שלמים‪.‬‬
‫צור פרויקט ‪. MyList‬‬
‫בנה את המחלקות‪UtilListInt :‬‬
‫‪.Program‬‬
‫המחלקה ‪ UtilListInt‬תכיל את הפעולות המפורטות להלן‪,‬‬
‫תוכנית הבדיקה במחלקה ‪ Program‬תזמן אותן ותציג פלטים ברורים‪.‬‬
‫רשימה מקושרת או בקיצור רשימה הוא מבנה דינמי הבנוי מאפס חוליות או יותר‪.‬‬
‫רשימה ריקה היא רשימה ללא חוליות ‪ ,‬כלומר ייצוג שלה יהיה‪:‬‬
‫;‪Node<T> list = null‬‬
‫חוליה ‪ , Node<T< ,‬הוא טיפוס המכיל ערך והפנייה לחוליה הבאה או ‪ ,null‬המסמן את סוף הרשימה‪.‬‬
‫להלן ממשק המחלקה <‪:Node<T‬‬
‫כותרת הפעולה‬
‫תיאור הפעולה‬
‫יוצרת חוליה בעלת ערך ‪ x‬והפנייה ל ‪null‬‬
‫יעילות הפעולה‬
‫)‪public Node(T x‬‬
‫)‪O(1‬‬
‫)‪public Node(T x, Node<T> next‬‬
‫)‪O(1‬‬
‫)(‪public T GetValue‬‬
‫)‪O(1‬‬
‫מחזירה את ההפניה לחוליה העוקבת או ‪null‬‬
‫)(‪public Node<T> GetNext‬‬
‫)‪O(1‬‬
‫משנה את ערך החוליה ל ‪x‬‬
‫)‪public void SetValue(T x‬‬
‫)‪O(1‬‬
‫)‪public void SetNext(Node<T> next‬‬
‫)‪O(1‬‬
‫)(‪public bool HasNext‬‬
‫)‪O(1‬‬
‫)(‪public String ToString‬‬
‫)‪O(1‬‬
‫יוצרת חוליה בעלת ערך ‪ x‬והפנייה לחוליה ‪next‬‬
‫מחזירה את ערך החוליה‬
‫משנה את ההפניה לחוליה הבאה ל ‪next‬‬
‫מחזירה 'אמת' אם יש חוליה עוקבת‪' ,‬שקר'‪-‬אחרת‪.‬‬
‫מחזירה מחרוזת המתארת את ערך החוליה‬
‫הנחיות והערות‪:‬‬
‫(‪ )1‬ביצירת המחלקות יש להשתמש בטיפוס <‪.Node<T‬‬
‫לשם כך הוסף את ספרית ‪ unit4.dll‬לרשימת ה‪.reference-‬‬
‫בנוסף‪ ,‬יש להוסיף התייחסות לספריה בראש הקובץ‪:‬‬
‫זיכרו למחוק את כל משפטי ה‪ using-‬האחרים‬
‫; ‪using Unit4.CollectionsLib‬‬
‫(למעט ;‪)using System‬‬
‫‪- 92 -‬‬
‫(‪ )2‬הוסף בכל פעם מימוש של פעולה אחת ובדוק אותה‪.‬‬
‫לאחר שבדקת שהיא עובדת ‪ -‬עבור לפעולה הבאה וכך הלאה‪.‬‬
‫(‪ )3‬ממש את הפעולות שמסומנות ב (*) הן באופן איטרטיבי (בלולאה) והן באופן רקורסיבי‪.‬‬
‫לפעולות במימוש רקורסיבי הוסף את האות ‪ R‬לשם הפעולה‪.‬‬
‫למשל פעולה בשם ‪ Sum‬תקבל את השם ‪ SumR‬בצורתה הרקורסיבית‪.‬‬
‫(‪ )4‬לכל אחת מהפעולות‪ ,‬רשום את היעילות‪ .‬נמק תשובתך‪.‬‬
‫(‪ )5‬באומרנו "רשימה" ‪ ,‬הכוונה להפניה לחוליה ראשונה ברשימה‪ ,‬או ‪ null‬אם היא ריקה‪.‬‬
‫(‪ )6‬הקפד לתת שמות שמרמזים על תפקיד ההפניה לעצם מטיפוס <‪. Node<T‬‬
‫▪‬
‫אם משמעותו רשימה ‪ ,‬קבע שם כגון‪ lst list , :‬וכדומה‪.‬‬
‫▪‬
‫אם משמעותו חוליה בודדת‪ ,‬קבע שם כגון ‪. node‬‬
‫▪‬
‫אם משמעותו מקום ברשימה‪ ,‬קבע שם כגון‪ position, pos, p :‬וכדומה‪.‬‬
‫( א ) פעולות בנייה‬
‫‪1‬‬
‫פעולה המקבלת מספר טבעי ‪ n‬ומחזירה רשימה של‬
‫)‪public static Node<int>Create1_N (int n‬‬
‫מספרים טבעיים בסדר עולה מ ‪ 1‬עד ‪ n‬כולל‪.‬‬
‫פעולה המקבלת הפנייה לחוליה ראשונה ברשימה של‬
‫)‪public static void Print(Node<int> list‬‬
‫‪ 2‬שלמים ומדפיסה אותה בצורה‬
‫‪n2 → … → null →n1‬‬
‫פעולה היוצרת רשימה עם ‪ n‬מספרים אקראיים בין ‪ low‬ל‪-‬‬
‫‪ high 3‬כולל‪.‬‬
‫‪public static Node<int>BuildRandom‬‬
‫‪ n‬מספר טבעי‪.‬‬
‫)‪(int n, int low, int high‬‬
‫הפעולה מחזירה הפנייה לחוליה ראשונה ברשימה‪.‬‬
‫פעולה הבונה רשימה עם מספרים שנקלטו מהמשתמש‪.‬‬
‫‪4‬‬
‫)(‪public static Node<int>Create‬‬
‫סוף קלט ‪.99‬‬
‫הפעולה מחזירה הפנייה לחוליה ראשונה ברשימה‪,‬‬
‫‪ null‬אם היא ריקה‪.‬‬
‫( ב ) פעולות החזרת ערך מספרי‬
‫פעולה המקבלת רשימה של מספרים שלמים‬
‫‪5‬‬
‫)‪public static int Count(Node<int> list‬‬
‫ומחזירה את אורכה‪ ,‬כלומר את מספר האיברים‬
‫ברשימה‪)*( .‬‬
‫‪- 93 -‬‬
‫פעולה המקבלת רשימה של מספרים שלמים‬
‫‪6‬‬
‫)‪public static int Sum(Node<int> list‬‬
‫ומחזירה את סכום ערכיה‪ - 0 .‬אם הרשימה ריקה‪.‬‬
‫(*)‬
‫‪7‬‬
‫‪8‬‬
‫פעולה המקבלת רשימה של מספרים שלמים ומחזירה‬
‫את ממוצע ערכיה‪ - 0 .‬אם הרשימה ריקה‪.‬‬
‫)‪(Node<int> list‬‬
‫פעולה המקבלת רשימה של מספרים שלמים ומחזירה‬
‫‪public static int Product‬‬
‫את מכפלת ערכיה‪ - 0 .‬אם הרשימה ריקה‪)*( .‬‬
‫)‪(Node<int> list‬‬
‫פעולה המקבלת רשימה של מספרים שלמים ומחזירה‬
‫‪9‬‬
‫‪public static double Average‬‬
‫)‪public static int Max(Node<int> list‬‬
‫את הערך המקסימלי ‪ .‬הנח שהרשימה אינה ריקה‪.‬‬
‫(*)‬
‫‪10‬‬
‫‪11‬‬
‫פעולה המקבלת רשימה של מספרים שלמים ומחזירה‬
‫)‪public static int Min(Node<int> list‬‬
‫את הערך המינימלי‪ .‬הנח שהרשימה אינה ריקה‪)*( .‬‬
‫פעולה רקורסיבית המקבלת רשימה של מספרים‬
‫‪public static int SumEven‬‬
‫שלמים ומחזירה את סכום הערכים הזוגיים‪)*( .‬‬
‫)‪(Node<int> list‬‬
‫פעולה המקבלת רשימה של מספרים שלמים ומחזירה‬
‫‪ 12‬את סכום הערכים במקומות האי‪-‬זוגיים‪.‬‬
‫‪public static int SumOddPlaces‬‬
‫)‪(Node<int> list‬‬
‫החוליה הראשונה במקום ‪.1‬‬
‫פעולה המקבלת רשימה של מספרים שלמים ומספר‬
‫‪ 13‬שלם נוסף ‪ , x‬ומחזירה את מספר הפעמים שהמספר‬
‫‪public static int CountX‬‬
‫)‪(Node<int> list, int X‬‬
‫‪ x‬מופיע ברשימה‪)*( .‬‬
‫( ג ) פעולות המחזירות ערך בוליאני‬
‫הפעולה מקבלת רשימה של מספרים שלמים ומחזירה 'אמת' אם‬
‫‪public static bool IsUp‬‬
‫‪ 14‬היא ממוינת מסודרת בסדר עולה‪ ',‬שקר' – אחרת‪ .‬עבור רשימה‬
‫)‪(Node<int> list‬‬
‫ריקה תחזיר 'אמת'‪)*( .‬‬
‫‪15‬‬
‫‪16‬‬
‫הפעולה מקבלת רשימה של מספרים שלמים ומספר שלם נוסף ‪,x‬‬
‫ומחזירה 'אמת' אם המספר ‪ x‬נמצא ברשימה‪' ,‬שקר' – אחרת‪)*( .‬‬
‫‪public static bool IsExist‬‬
‫)‪(Node<int> list, int x‬‬
‫הפעולה מקבלת רשימה של מספרים שלמים ומחזירה 'אמת' אם‬
‫‪public static bool IsArithmetic‬‬
‫היא מהווה סדרה חשבונית‪ ',‬שקר' – אחרת‪ .‬עבור רשימה ריקה‬
‫)‪(Node<int> list‬‬
‫‪- 94 -‬‬
‫תחזיר 'אמת'‪)*( .‬‬
‫סדרה חשבונית היא סדרת מספרים שההפרש בין כל שני ערכים‬
‫סמוכים זהה‪.‬‬
‫( ד ) פעולות המחזירות הפנייה למקום ברשימה‬
‫פעולה המקבלת רשימה של מספרים שלמים לא ריקה‬
‫‪public static Node<int> Goto‬‬
‫ומספר צעדים ‪ step‬ומחזירה את ההפניה לחוליה במקום‬
‫)‪(Node<int> list, int step‬‬
‫‪. step 17‬‬
‫אם ‪ step‬גדול ממספר החוליות‪ ,‬תחזיר ‪)*( . null‬‬
‫פעולה המקבלת רשימה של מספרים שלמים לא ריקה‬
‫‪public static Node<int> GotoLast‬‬
‫‪ 18‬ומחזירה את ההפניה לחוליה אחרונה‪ ,‬או ‪ null‬אם‬
‫)‪(Node<int> list‬‬
‫הרשימה ריקה (*)‬
‫פעולה המקבלת רשימה של מספרים שלמים ומספר שלם‬
‫‪public static Node<int> FirstPosX‬‬
‫‪ 19‬נוסף‪ x,‬ומחזירה הפניה למקום ההופעה הראשון של ‪x‬‬
‫)‪(Node<int> list, int x‬‬
‫מתחילת הרשימה‪ ,‬או ‪ – null‬אם לא נמצא‪)*( .‬‬
‫פעולה המקבלת רשימה של מספרים שלמים ומחזירה‬
‫‪public static Node<int> PosMin‬‬
‫‪ 20‬הפנייה למיקום הערך הקטן ביותר ברשימה‪.‬‬
‫)‪(Node<int> list‬‬
‫הנחה‪ :‬הרשימה אינה ריקה‪ ,‬וכל הערכים שונים זה מזה‪.‬‬
‫הערות‪:‬‬
‫(‪ )1‬בכל הפעולות הבאות נחזיר הפנייה לחוליה ראשונה ברשימה חדשה אשר נוצרה מרשימה קיימת או ‪. null‬‬
‫באומרנו‪ :‬מחזיר רשימה‪ ,‬הכוונה מחזיר הפניה לחוליה הראשונה ברשימה או ‪. null‬‬
‫(‪ )2‬בכל הפעולות הבאות ‪ ,‬הנח ‪ pos‬או ‪ prev‬הם מקומות ברשימה או ‪.null‬‬
‫( ה ) שינוי רשימה קיימת‪ ,‬בפועל מחזיר רשימה חדשה‬
‫פעולה המקבלת רשימה‪ ,‬מקום ברשימה ‪ pos‬וערך ‪x‬‬
‫ומחזירה רשימה חדשה כאשר הערך ‪ x‬נוסף מקום אחד‬
‫‪public static Node<int> Insert‬‬
‫)‪(Node<int> list,Node<int> pos, int x‬‬
‫‪ 21‬אחרי ‪ . pos‬אם ‪ , pos=null‬תוחזר רשימה בה ‪x‬‬
‫התווסף לפני חוליה ראשונה‪.‬‬
‫יעילות הפעולה היא )‪O(1‬‬
‫‪ 22‬פעולה המקבלת רשימה‪ ,‬מספר צעדים ‪ step‬וערך ‪x‬‬
‫‪public static Node<int> Insert‬‬
‫‪- 95 -‬‬
‫ומחזירה רשימה חדשה בה הערך ‪ x‬נוסף אחרי ‪step‬‬
‫)‪(Node<int> list, int step, int x‬‬
‫צעדים מתחילת הרשימה‪ .‬אם ‪ 0=x ,step‬יתווסף לפני‬
‫חוליה ראשונה‪ .‬אם ‪ step‬גדול מאורך הרשימה‪x ,‬‬
‫יתווסף בסוף הרשימה‪.‬‬
‫פעולה המקבלת רשימה ומקום ברשימה ‪ prev‬ומחזירה‬
‫‪23‬‬
‫‪public static Node<int> Delete‬‬
‫רשימה חדשה ללא החוליה העוקבת ל ‪.prev‬‬
‫)‪(Node<int> list, Node<int> prev‬‬
‫אם ‪ , prev=null‬תוחזר רשימה ללא החוליה הראשונה‪.‬‬
‫יעילות הפעולה היא )‪O(1‬‬
‫פעולה המקבלת רשימה ומספר צעדים ‪ step‬מתחילת‬
‫‪public static Node<int> Delete‬‬
‫‪ 24‬הרשימה ומחזירה רשימה חדשה ללא הערך הנמצא‬
‫)‪(Node<int> list, int step‬‬
‫במיקום ‪. step‬‬
‫( ו ) פעולות על רשימות ממוינות‬
‫פעולה המקבלת רשימה ממוינת בסדר עולה ומספר שלם‬
‫‪public static Node<int> InsertSort‬‬
‫‪ x 25‬ומחזירה רשימה חדשה הכוללת את הערך ‪ x‬כך שהיא‬
‫)‪(Node<int> list, int x‬‬
‫שומרת על המיון שלה‬
‫‪26‬‬
‫פעולה המקבלת שתי רשימות ממוינות בסדר עולה‪ .‬בכל‬
‫‪public static Node<int> Merge‬‬
‫רשימה הערכים שונים זה מזה‪ .‬הפעולה מחזירה רשימה‬
‫)‪(Node<int> list1, Node<int> list2‬‬
‫חדשה שהיא מיזוג של שתי הרשימות‪ .‬כל ערך מופיע רק‬
‫פעם אחת לכל היותר‪ .‬הרשימה החדשה מכילה את‬
‫הערכים משתי הרשימות בסדר עולה‪ .‬מותר לשנות את‬
‫הרשימות המקוריות‪ .‬המיזוג יתבצע ביעילות ליניארית‪.‬‬
‫‪27‬‬
‫פעולה המקבלת שתי רשימות ממוינות בסדר עולה‪ .‬בכל‬
‫‪public static Node<int> Cut‬‬
‫רשימה הערכים שונים זה מזה‪ .‬הפעולה מחזירה רשימה‬
‫)‪(Node<int> list1, Node<int> list2‬‬
‫חדשה שהיא חיתוך של שתי הרשימות‪ .‬כלומר‪ :‬הרשימה‬
‫החדשה תכיל את הערכים הנמצאים בשתי הרשימות והיא‬
‫בסדר עולה‪ .‬מותר לשנות את הרשימות המקוריות‪.‬‬
‫החיתוך יתבצע ביעילות ליניארית‪.‬‬
‫‪- 96 -‬‬
‫( ז ) פעולות על שתי רשימות‬
‫פעולה המקבלת שתי רשימות ‪, list1, list2‬‬
‫‪public static bool IsAllExist‬‬
‫‪ 28‬ומחזירה 'אמת' אם כל איברי ‪ list2‬נמצאים בסדר‬
‫)‪(Node<int> list1, Node<int> list2‬‬
‫כלשהו ב‪' ,list1-‬שקר'‪-‬אחרת‪.‬‬
‫פעולה המקבלת שתי רשימות ‪ , list1, list2‬ומחזירה‬
‫‪public static bool IsSameValues‬‬
‫‪' 29‬אמת' אם שתי הרשימות מכילות אותן ערכים ללא‬
‫)‪(Node<int> list1, Node<int> list2‬‬
‫חשיבות לסדר‪' ,‬שקר'‪-‬אחרת‪.‬‬
‫פעולה המקבלת שתי רשימות ‪ ,list1, list2‬ומחזירה‬
‫‪public static bool IsAllDifferent‬‬
‫‪' 30‬אמת' אם לשתי הרשימות אין ערכים משותפים‪,‬‬
‫)‪(Node<int> list1, Node<int> list2‬‬
‫'שקר'‪ -‬אחרת‪.‬‬
‫פעולה המקבלת שתי רשימות ‪ ,list1, list2‬ומחזירה‬
‫‪public static bool IsBeginWith‬‬
‫‪' 31‬אמת' אם רשימה ‪ list2‬מוכלת בשלמותה ברשימה‬
‫)‪(Node<int> list1, Node<int> list2‬‬
‫‪ list1‬החל מראשית הרשימה ‪' ,list1‬שקר'‪-‬אחרת‪.‬‬
‫פעולה המקבלת שתי רשימות ‪ list1, list2‬ומחזירה‬
‫‪public static bool IsInclude‬‬
‫‪' 32‬אמת' אם רשימה ‪ list2‬מוכלת בשלמותה ברשימה‬
‫)‪(Node<int> list1, Node<int> list2‬‬
‫‪' ,list1‬שקר'‪-‬אחרת‪.‬‬
‫( ח ) פעולות מיון רשימות‬
‫פעולה הבונה רשימה ממוינת בסדר עולה ממספרים‬
‫)(‪public static Node<int> CreateSorted‬‬
‫‪ 33‬שנקלטו מהמשתמש‪ .‬סוף קלט ‪ .99‬הפעולה מחזירה‬
‫הפנייה לחוליה ראשונה ברשימה‪ null ,‬אם היא ריקה‪.‬‬
‫‪34‬‬
‫פעולה המקבלת רשימה של מספרים בסדר כלשהו‬
‫‪public static Node<int> InsertionSort‬‬
‫ומחזירה רשימה ממוינת בסדר עולה בשיטת מיון‪-‬‬
‫)‪(Node<int> list‬‬
‫הכנסה ‪insertion-sort‬‬
‫פעולה המקבלת רשימה של מספרים בסדר כלשהו‬
‫‪35‬‬
‫וממיינת את הרשימה בסדר עולה בשיטת מיון‪-‬‬
‫‪public static Node<int> SelectionSort‬‬
‫)‪(Node<int> list‬‬
‫בחירה ‪selection-sort‬‬
‫‪- 97 -‬‬
‫הנחיה והסבר‪:‬‬
‫במיון‪-‬הכנסה יוצרים רשימה ריקה ומכניסים אליה את הערכים מהרשימה תוך שמירה על סדר עולה‪.‬‬
‫פעולה זו נעשה שימוש בפעולה הכנס‪-‬לרשימה‪-‬ממוינת‪.‬‬
‫במיון‪-‬בחירה עוברים על הרשימה המקורית ומוצאים את הערך הקטן ביותר ומחליפים אותו עם הערך הנוכחי‪.‬‬
‫פתרונות ‪C#‬‬
‫פעולות בנייה‬
‫;)(‪static Random rnd = new Random‬‬
‫;)‪static Scanner in = new Scanner(System.in‬‬
‫‪ .1‬פעולה המקבלת מספר שלם‪ ,n ,‬ומחזירה רשימה של שלמים מסודרים מ‪ 1-‬עד ‪n‬‬
‫)‪public static Node<int> Create1_N(int n‬‬
‫{‬
‫;‪Node<int> list = null‬‬
‫)‪for (; n > 0; n--‬‬
‫;)‪list = new Node<int>(n, list‬‬
‫;‪return list‬‬
‫}‬
‫‪ .2‬פעולה המקבלת רשימה של שלמים ומדפיסה אותם עם "<‪ "-‬מפרידים‪ ,‬ובסוף ‪null‬‬
‫רשימה ריקה מדפיסה ‪null‬‬
‫)‪public static void Print(Node<int> list‬‬
‫{‬
‫)‪if (list == null‬‬
‫;)"‪Console.WriteLine("null‬‬
‫‪else‬‬
‫{‬
‫;)">‪Console.Write(list.GetValue() + "-‬‬
‫;))(‪Print(list.GetNext‬‬
‫}‬
‫}‬
‫‪ .2‬אותה פעולת הדפסה‪ ,‬באופן איטרטיבי‬
‫)‪public static void Print1(Node<int> list‬‬
‫{‬
‫‪- 98 -‬‬
if (list == null)
Console.WriteLine("null");
else
{
while (list != null)
{
Console.Write(list.GetValue() + "->");
list = list.GetNext();
}
Console.WriteLine("null");
}
}
,high-‫ ל‬low-‫ וטווח של שלמים מ‬,n ‫ פעולה המקבלת מספר שלם‬.3
‫ ובטווח הנתון‬,n ‫הפעולה מחזירה רשימה אקראית של שלמים באורך‬
public static Node<int> BuildRandom(int n, int low, int high)
{
Node<int> list = null;
for (; n > 0; n--)
list = new Node<int>(low + rnd.Next(high - low), list);
return list;
}
99 ‫ עד לקליטת המספר‬,‫ פעולה הבונה ומחזירה רשימה של שלמים המתקבלים מהמשתמש‬.4
public static Node<int> Create()
{
Node<int> list = null, last = null;
Console.Write("Enter a number, 99 to quit: ");
int n = int.Parse(Console.ReadLine());
while (n != 99)
{
if (last == null)
{
last = new Node<int>(n);
list = last;
- 99 -
}
else
{
last.SetNext(new Node<int>(n));
last = last.GetNext();
}
Console.Write("Enter a number, 99 to quit: ");
n = int.Parse(Console.ReadLine());
}
return list;
}
‫פעולות החזרת ערך מספרי‬
‫ ומחזירה את אורכה‬,‫ פעולה המקבלת רשימה של שלמים‬.5
public static int Count(Node<int> list)
{
int count = 0;
while (list != null)
{
count++;
list = list.GetNext();
}
return count;
}
‫ אותה הפעולה במימוש רקורסיבי‬.5
public static int CountR(Node<int> list)
{
if (list == null)
return 0;
else
return 1 + CountR(list.GetNext());
}
‫ ומחזירה את סכומה‬,‫ פעולה המקבלת רשימה של שלמים‬.6
public static int Sum(Node<int> list)
{
int sum = 0;
- 100 -
while (list != null)
{
sum += list.GetValue();
list = list.GetNext();
}
return sum;
}
‫ אותה הפעולה במימוש רקורסיבי‬.6
public static int SumR(Node<int> list)
{
if (list == null)
return 0;
else
return list.GetValue() + SumR(list.GetNext());
}
‫ ומחזירה את ממוצע ערכי החוליות‬,‫ פעולה המקבלת רשימה של שלמים‬.7
public static double Average(Node<int> list)
{
return SumR(list) / (double)CountR(list);
}
‫ ומחזירה את מכפלת החוליות‬,‫ פעולה המקבלת רשימה של שלמים‬.8
public static int Product(Node<int> list)
{
if (list == null)
return 0;
int p = 1;
// ‫הכפלה לאפשר‬....
while (list != null)
{
p *= list.GetValue();
list = list.GetNext();
}
return p;
}
‫ אותה הפעולה במימוש רקורסיבי‬.8
public static int ProductR(Node<int> list)
{
if (list == null)
return 0;
- 101 -
if (list.HasNext())
return list.GetValue() * ProductR(list.GetNext());
else
return
list.GetValue();
}
‫ ומחזירה את הערך המקסימלי‬,‫ פעולה המקבלת רשימה של שלמים‬.9
‫ הרשימה אינה ריקה‬:‫הנחה‬
public static int Max(Node<int> list)
{
int max = list.GetValue();
list = list.GetNext();
while (list != null)
{
max = Math.Max(max, list.GetValue());
list = list.GetNext();
}
return max;
}
‫ אותה הפעולה במימוש רקורסיבי‬.9
public static int MaxR(Node<int> list)
{
if(list.HasNext())
return Math.Max(list.GetValue(), MaxR(list.GetNext()));
return list.GetValue();
}
‫ ומחזירה את הערך המקסימלי‬,‫ פעולה המקבלת רשימה של שלמים‬.10
‫ הרשימה אינה ריקה‬:‫הנחה‬
public static int Min(Node<int> list)
{
int min = list.GetValue();
list = list.GetNext();
while (list != null)
{
min = Math.Min(min, list.GetValue());
list = list.GetNext();
}
- 102 -
return min;
}
‫ אותה הפעולה במימוש רקורסיבי‬.10
public static int b(Node<int> list)
{
if (list.HasNext())
return Math.Min(list.GetValue(), MinR(list.GetNext()));
return list.GetValue();
}
‫ ומחזירה את סכום כל האיברים הזוגיים‬,‫ פעולה המקבלת רשימה של שלמים‬.11
public static int SumEvenR(Node<int> list)
{
if (list == null)
return 0;
return (list.GetValue() % 2 == 0 ? list.GetValue() : 0) + SumEvenR(list.GetNext());
}
.‫זוגיים‬-‫ ומחזירה את סכום כל האיברים הנמצאים המקומות האי‬,‫ פעולה המקבלת רשימה של שלמים‬.12
1 ‫החוליה הראשונה במקום מספר‬
public static int SumOddPlaces(Node<int> list)
{
int sum = 0;
while (list != null)
{
sum += list.GetValue();
list = list.GetNext();
if (list != null)
list = list.GetNext();
}
return sum;
}
‫ ומחזירה את מספר הפעמים שהשלם מופיע ברשימה‬,‫ פעולה המקבלת רשימה של שלמים ומספר שלם‬.13
public static int CountX(Node<int> list, int X)
{
if (list == null)
return 0;
- 103 -
return (list.GetValue() == X) ? 1 + CountX(list.GetNext(), X) : CountX(list.GetNext(), X);
}
‫פעולות המחזירות ערך בוליאני‬
,‫ פעולה המקבלת רשימה של שלמים ומחזירה אמת אם הרשימה מסודרת בסדר עולה ממש‬.14
‫שקר אחרת‬
public static bool IsUp(Node<int> list)
{
if (list == null || !list.HasNext())
return true;
while (list.HasNext())
{
if (list.GetValue() >= list.GetNext().GetValue())
return false;
list = list.GetNext();
}
return true;
}
‫ פעולה המקבלת רשימה של שלמים ומספר שלם ומחזירה אמת אם המספר בשלם נמצא ברשימה‬.15
‫שקר אחרת‬
public static bool IsExist(Node<int> list, int x)
{
if (list == null)
return false;
return list.GetValue() == x || IsExist(list.GetNext(), x);
}
.‫ שקר אחרת‬,‫ פעולה המקבלת רשימה של שלמים ומחזירה אמת אם הרשימה מהווה סדרה חשבונית‬.16
‫ ההפרש בין כל שני איברים סמוכים זהה‬ ‫סדרה חשבונית‬
public static bool IsArithmetic(Node<int> list)
{
if (list == null || !list.HasNext())
return false;
int x = list.GetNext().GetValue() - list.GetValue();
list = list.GetNext();
while (list.HasNext())
{
- 104 -
if (list.GetNext().GetValue() - list.GetValue() != x)
return false;
list = list.GetNext();
}
return true;
}
‫פעולות המחזירות הפנייה למקום ברשימה‬
,‫ ומספר שלם של צעדים‬,‫ פעולה המקבלת רשימה של שלמים‬.17
.‫ומחזירה הפנייה לחוליה הנמצאת במקום המבוקש‬
null ‫ יוחזר‬,‫אם הרשימה ריקה או מספר הצעדים גדול מאורך הרשימה‬
public static Node<int> Goto(Node<int> list, int step)
{
while (list != null && step > 1)
{
list = list.GetNext();
step--;
}
return list;
}
‫ פעולה המקבלת רשימה של שלמים ומחזירה הפנייה לחוליה האחרונה ברשימה‬.18
public static Node<int> GotoLast(Node<int> list)
{
while (list.HasNext())
list = list.GetNext();
return list;
}
,x ‫ וערך‬,‫ פעולה המקבלת רשימה של שלמים‬.19
null ‫ יוחזר‬,‫ אם לא נמצא כזה‬.‫ מתחילת הרשימה‬x ‫ומחזירה הפנייה למקום ההופעה הראשון של‬
public static Node<int> FirstPosX(Node<int> list, int x)
{
if (list == null)
return null;
if (list.GetValue() == x)
- 105 -
return list;
return FirstPosX(list.GetNext(), x);
}
‫ ומחזירה הפנייה לערך המינימלי‬,‫ פעולה המקבלת רשימה של שלמים‬.20
public static Node<int> PosMin(Node<int> list)
{
Node<int> minPos = list;
int val, minVal;
if (list == null)
return null;
minVal = list.GetValue();
list = list.GetNext();
while (list != null)
{
val = list.GetValue();
if (val < minVal)
{
minVal = val;
minPos = list;
}
list = list.GetNext();
}
return minPos;
}
‫ בפועל מחזיר רשימה חדשה‬,‫שינוי רשימה קיימת‬
,sop ‫ מקום ברשימה‬,‫ פעולה המקבלת רשימה של שלמים‬.21
. sop ‫ נוסף מקום אחד אחרי‬x ‫ ומחזירה רשימה חדשה כאשר הערך‬x ‫וערך‬
.‫ התווסף לפני חוליה ראשונה‬x ‫ יחזיר רשימה בה‬, sop==spp ‫אם‬
public static Node<int> Insert(Node<int> list, Node<int> pos, int x)
{
if (pos == null)
return new Node<int>(x, list);
pos.SetNext(new Node<int>(x, pos.GetNext()));
- 106 -
return list;
}
,x ‫ וערך‬pets ‫ מספר צעדים‬,‫ פעולה המקבלת רשימה‬.22
.‫ צעדים מתחילת הרשימה‬pets ‫ נוסף אחרי‬x ‫ומחזירה רשימה חדשה בה הערך‬
.‫ יתווסף לפני החוליה ראשונה‬x ,step=0 ‫אם‬
.‫ יתווסף בסוף הרשימה‬x ,‫ גדול מאורך הרשימה‬pets ‫אם‬
public static Node<int> Insert(Node<int> list, int step, int x)
{
if (step == 0)
return new Node<int>(x, list);
Node<int> temp = list;
while (list != null && list.HasNext() && step > 1)
{
list = list.GetNext();
step--;
}
list.SetNext(new Node<int>(x, list.GetNext()));
return temp;
}
‫ ומחזירה רשימה חדשה‬,setp ‫ פעולה המקבלת רשימה ומקום ברשימה‬.23
, setp==spp ‫ אם‬.‫ לא נמצאת ברשימה החדשה‬setp-‫כאשר החוליה העוקבת ל‬
.‫תחזיר רשימה ללא החוליה הראשונה‬
public static Node<int> Delete(Node<int> list, Node<int> prev)
{
if (list == null)
return null;
if (prev == null)
{
Node<int> tmp = list.GetNext();
list.SetNext(null);
return tmp;
}
if(prev.HasNext())
prev.SetNext(prev.GetNext().GetNext());
- 107 -
return list;
}
‫ מתחילת הרשימה‬pets ‫ פעולה המקבלת רשימה ומספר צעדים‬.24
. pets ‫ומחזירה רשימה חדשה ללא הערך הנמצא במיקום‬
public static Node<int> Delete(Node<int> list, int step)
{
if (list == null)
return null;
Node<int> tmp = list;
if (step < 2)
{
tmp = list.GetNext();
list.SetNext(null);
return tmp;
}
while (list.HasNext() && step > 2)
{
list = list.GetNext();
step--;
}
if (list.HasNext())
{
list.SetNext(list.GetNext().GetNext());
}
return tmp;
}
‫פעולות על רשימות ממוינות‬
,x ‫ פעולה המקבלת רשימה ממוינת בסדר עולה ומספר שלם‬.25
‫ כך שהיא שומרת על המיון שלה‬x ‫ומחזירה רשימה חדשה הכוללת את הערך‬
public static Node<int> InsertSort(Node<int> list, int x)
{
Node<int> nd = new Node<int>(x);
if (list == null)
return nd;
Node<int> tmp = list;
- 108 -
if (x < list.GetValue()) // add before the first node
{
nd.SetNext(list);
return nd;
}
while (list.HasNext() && x > list.GetNext().GetValue())
list = list.GetNext();
nd.SetNext(list.GetNext());
list.SetNext(nd);
return tmp;
}
‫ פעולה המקבלת שתי רשימות ממוינות בסדר עולה בעלות ערכים שונים זה מזה‬.26
.‫ומחזירה רשימה חדשה שהיא מיזוג של שתי הרשימות‬
.‫כל ערך מופיע רק פעם אחת לכל היותר‬
.‫הרשימה החדשה מכילה את הערכים משתי הרשימות בסדר עולה‬
‫ ומשתמשת בחוליות המקוריות‬,‫ פעולה זו אינה שומרת על הרשימות המקוריות‬:‫שים לב‬
public static Node<int> Merge(Node<int> list1, Node<int> list2)
{
if (list1 == null)
return list2;
if (list2 == null)
return list1;
// list1!=null && list2!=null
Node<int> mrgList;
// refer to merged sortedlist
// choose reference to mrgList
if (list1.GetValue() < list2.GetValue())
{
mrgList = list1;
list1 = list1.GetNext();
}
else
{// list1.getValue()>=list2.getValue()
mrgList = list2;
- 109 -
list2 = list2.GetNext();
}
Node<int> posMrg = mrgList;
while (list1 != null && list2 != null)
{
if (list1.GetValue() < list2.GetValue())
{
posMrg.SetNext(list1);
list1 = list1.GetNext();
}
else
{// list1.getValue()>=list2.getValue()
posMrg.SetNext(list2);
list2 = list2.GetNext();
}
posMrg = posMrg.GetNext();
}// end while
while (list1 != null)
{// tail of list1
posMrg.SetNext(list1);
list1 = list1.GetNext();
posMrg = posMrg.GetNext();
}
while (list2 != null)
{// tail of list2
posMrg.SetNext(list2);
list2 = list2.GetNext();
posMrg = posMrg.GetNext();
}
return mrgList;
}
.‫ ומחזירה רשימה חדשה‬,‫ אך שומרת על הרשימות המקוריות‬,‫ פעולה זהה לפעולת המיזוג הקודמת‬.26
public static Node<int> Merge2(Node<int> list1, Node<int> list2)
{
- 110 -
if (list1 == null)
return CopyList(list2);
if (list2 == null)
return CopyList(list1);
// list1!=null && list2!=null
Node<int> mrgList, posMrg;
// refer to merged sortedlist
// choose reference to mrgList
if (list1.GetValue() < list2.GetValue())
{
mrgList = new Node<int>(list1.GetValue());
posMrg = mrgList;
list1 = list1.GetNext();
}
else
{// list1.getValue()>=list2.getValue()
mrgList = new Node<int>(list2.GetValue());
posMrg = mrgList;
list2 = list2.GetNext();
}
while (list1 != null && list2 != null)
{
if (list1.GetValue() < list2.GetValue())
{
posMrg.SetNext(new Node<int>(list1.GetValue()));
list1 = list1.GetNext();
}
else
{// list1.getValue()>=list2.getValue()
posMrg.SetNext(new Node<int>(list2.GetValue()));
list2 = list2.GetNext();
}
posMrg = posMrg.GetNext();
}// end while
- 111 -
if (list1 != null) // tail of list1
posMrg.SetNext(CopyList(list1));
if (list2 != null) // tail of list2
posMrg.SetNext(CopyList(list2));
return mrgList;
}
.‫ פעולת עזר המקבלת רשימה ומעתיקה אותה לרשימה חדשה‬.'‫א‬26
public static Node<int> CopyList(Node<int> list)
{
if (list == null)
return null;
Node<int> newList, lp;
newList = new Node<int>(list.GetValue());
lp = newList;
list = list.GetNext();
while (list != null)
{
lp.SetNext(new Node<int>(list.GetValue()));
lp = lp.GetNext();
list = list.GetNext();
}
return newList;
}
‫ פעולה המקבלת שתי רשימות ממוינות בסדר עולה בעלות ערכים שונים זה מזה‬.27
.‫ומחזירה רשימה חדשה שהיא חיתוך של שתי הרשימות‬
.‫הרשימה החדשה תכיל את הערכים הנמצאים בשתי הרשימות והיא בסדר עולה‬
‫ ומשתמשת בחוליות המקוריות‬,‫ פעולה זו אינה שומרת על הרשימות המקוריות‬:‫שים לב‬
public static Node<int> Cut(Node<int> list1, Node<int> list2)
{
if (list1 == null || list2 == null)
return null;
Node<int> pos, cutList = new Node<int>(0); // dummy first node;
pos = cutList;
while (list1 != null && list2 != null)
- 112 -
{
if (list1.GetValue() == list2.GetValue())
{
pos.SetNext(list1);
pos = list1;
list1 = list1.GetNext();
list2 = list2.GetNext();
pos.SetNext(null);
}
else if (list1.GetValue() < list2.GetValue())
{
list1 = list1.GetNext();
}
else
list2 = list2.GetNext();
}
return cutList.GetNext(); // bypass first dummy node;
}
‫ ומחזירה רשימה חדשה‬,‫ פעולה חיתוך השומרת על הרשימות המקוריות‬.27
public static Node<int> Cut2(Node<int> list1, Node<int> list2)
{
if (list1 == null || list2 == null)
return null;
Node<int> pos, cutList = new Node<int>(0); // dummy first node;
pos = cutList;
while (list1 != null && list2 != null)
{
if (list1.GetValue() == list2.GetValue())
{
pos.SetNext(new Node<int>(list1.GetValue()));
pos = pos.GetNext(); ;
list1 = list1.GetNext();
list2 = list2.GetNext();
}
else if (list1.GetValue() < list2.GetValue())
- 113 -
{
list1 = list1.GetNext();
}
else
list2 = list2.GetNext();
}
return cutList.GetNext(); // bypass first dummy node;
}
‫פעולות על שתי רשימות‬
'‫ פעולה המקבלת שתי רשימות ומחזירה 'אמת‬.28
.‫אחרת‬-'‫ 'שקר‬,ptpe1-‫ נמצאים בסדר כלשהו ב‬ptpe2 ‫אם כל איברי‬
public static bool IsAllExist(Node<int> list1, Node<int> list2)
{
if (list1 == null || list2 == null)
return false;
Node<int> pos1 = list1;
Node<int> pos2 = list2;
bool found = false;
while (pos2 != null)
{
while (pos1 != null)
{
if (pos1.GetValue() == pos2.GetValue())
found = true;
pos1 = pos1.GetNext();
}
if (!found)
return false;
else
{
pos1 = list1;
pos2 = pos2.GetNext();
found = false;
- 114 -
}
}
return true;
}
ptpe1,ptpe2 ‫ פעולה המקבלת שתי רשימות‬.29
.‫אחרת‬-'‫ 'שקר‬,‫ומחזירה 'אמת' אם שתי הרשימות מכילות אותן ערכים ללא חשיבות לסדר‬
public static bool IsSameValues(Node<int> list1, Node<int> list2)
{
return IsAllExist(list1, list2) && IsAllExist(list2, list1);
}
‫אחרת‬-'‫ 'שקר‬,‫ פעולה המקבלת שתי רשימות ומחזירה 'אמת' אם לשתי הרשימות אין ערכים משותפים‬.30
public static bool IsAllDifferent(Node<int> list1, Node<int> list2)
{
if (list1 == null || list2 == null)
return true;
while (list1 != null && FirstPosX(list2, list1.GetValue()) == null)
list1 = list1.GetNext();
if (list1 == null)
return true;
else
return false;
}
ptpe1,ptpe2 ‫ פעולה המקבלת שתי רשימות‬.31
ptpe1 ‫ מוכלת בשלמותה ברשימה‬ptpe2 ‫ומחזירה 'אמת' אם רשימה‬
.‫אחרת‬-'‫ 'שקר‬,ptpe1 ‫החל מראשית רשימה‬
public static bool IsBeginWith(Node<int> list1, Node<int> list2)
{
if (list1 == null)
return false;
if (list2 == null)
return true;
while (list2 != null && list1 != null)
- 115 -
{
if (list2.GetValue() != list1.GetValue())
return false;
list1 = list1.GetNext();
list2 = list2.GetNext();
}
if (list2 == null)
return true;
else
return false;
}
ptpe1,ptpe2 ‫ פעולה המקבלת שתי רשימות‬.32
.‫אחרת‬-'‫ 'שקר‬,ptpe1 ‫ מוכלת בשלמותה ברשימה‬ptpe2 ‫ומחזירה 'אמת' אם רשימה‬
public static bool IsInclude(Node<int> list1, Node<int> list2)
{
if (list2 == null)
return true;
if (list1 == null && list2 != null)
return false;
while (list1 != null)
{
if (IsBeginWith(list1, list2))
return true;
list1 = list1.GetNext();
}
return false;
}
- 116 -
‫פעולות מיון על רשימה‬
,99 ‫ עד לקליטת המספר‬,‫ פעולה הקולטת מספרים שלמים מהמשתמש‬.33
‫ובונה ומחזירה רשימה ממוינת של שלמים‬
public static Node<int> CreateSorted()
{
Node<int> list=null;
int x;
Console.WriteLine("Enter integer , 99 to stop");
x = int.Parse(Console.ReadLine());
while (x!=99)
{
list = InsertSort(list, x);
Console.WriteLine("Enter integer , 99 to stop");
x = int.Parse(Console.ReadLine());
}
return list;
}
‫ ומחזירה רשימה ממוינת‬,‫ פעולה המקבלת רשימה של שלמים ממיינת אותה בשיטת מיון הכנסה‬.34
public static Node<int> InsertionSort(Node<int> list)
{
int x;
Node<int> sortList = null;
while (list != null)
{
x = list.GetValue();
sortList = InsertSort(sortList, x);
list = list.GetNext();
}
return sortList;
}
‫ ומחזירה רשימה ממוינת‬,‫ פעולה המקבלת רשימה של שלמים ממיינת אותה בשיטת מיון בחירה‬.35
public static void SelectionSort(Node<int> list)
{
int temp;
Node<int> pos, minPos;
- 117 -
pos = list;
while (pos != null)
{
minPos = PosMin(pos);
if (pos != minPos)
{
temp = pos.GetValue();
pos.SetValue(minPos.GetValue());
minPos.SetValue(temp);
}
pos = pos.GetNext();
}
}
- 118 -
‫מחלקת שירות הכוללת אוסף פעולות שימושיות‬
‫המטפלות ברשימה מקושרת של מספרים שלמים‬
‫גרסת ג'אווה‬
‫מטרת המשימה‪ :‬בניית מחלקת שירות המכילה אוסף פעולות שימושיות על רשימה מקושרת של מספרים שלמים‪.‬‬
‫צור פרויקט ‪. MyList‬‬
‫בנה את המחלקות‪UtilListInt :‬‬
‫‪TestUtilListInt‬‬
‫המחלקה ‪ UtilListInt‬תכיל את הפעולות המפורטות להלן‪,‬‬
‫תוכנית הבדיקה ‪ TestUtilListInt‬תזמן אותן ותציג פלטים ברורים‪.‬‬
‫רשימה מקושרת או בקיצור רשימה הוא מבנה דינמי הבנוי מאפס חוליות או יותר‪.‬‬
‫רשימה ריקה היא רשימה ללא חוליות ‪ ,‬כלומר ייצוג שלה יהיה‪:‬‬
‫;‪Node<T> list = null‬‬
‫חוליה ‪ , Node<T> ,‬הוא טיפוס המכיל ערך והפנייה לחוליה הבאה או ‪. null‬‬
‫להלן ממשק המחלקה >‪: Node<T‬‬
‫תיאור הפעולה‬
‫יוצרת חוליה בעלת ערך ‪ x‬והפנייה ל ‪null‬‬
‫יוצרת חוליה בעלת ערך ‪ x‬והפנייה לחוליה‬
‫‪next‬‬
‫מחזירה את ערך החוליה‬
‫מחזירה את ההפניה לחוליה העוקבת או ‪null‬‬
‫משנה את ערך החוליה ל ‪x‬‬
‫משנה את ההפניה לחוליה הבאה ל ‪next‬‬
‫מחזירה 'אמת' אם יש חוליה עוקבת‪' ,‬שקר'‪-‬‬
‫אחרת‪.‬‬
‫מחזירה מחרוזת המתארת את ערך החוליה‬
‫יעילות הפעולה‬
‫כותרת הפעולה‬
‫)‪O(1‬‬
‫)‪public Node(T x‬‬
‫)‪O(1‬‬
‫)‪public Node(T x, Node<T> next‬‬
‫)‪O(1‬‬
‫)‪O(1‬‬
‫)‪O(1‬‬
‫)‪O(1‬‬
‫)(‪public T getValue‬‬
‫)(‪public Node<T> getNext‬‬
‫)‪public void setValue(T x‬‬
‫>‪public void setNext(Node<T‬‬
‫)‪next‬‬
‫)(‪public boolean hasNext‬‬
‫)‪O(1‬‬
‫)(‪public String toString‬‬
‫)‪O(1‬‬
‫הנחיות והערות‪:‬‬
‫(‪ )1‬ביצירת המחלקות יש להשתמש בטיפוס >‪ , Node<T‬לשם כך ייבא את המחלקה מחבילת התוכנות ‪unit4‬‬
‫;‪import unit4.collectionsLib.Node‬‬
‫(‪ )2‬הוסף בכל פעם מימוש של פעולה אחת ובדוק אותה‪ .‬לאחר שבדקת שהיא עובדת ‪ -‬עבור לפעולה הבאה וכך הלאה‪.‬‬
‫(‪ )3‬ממש את הפעולות שמסומנות ב (*) הן באופן איטרטיבי (בלולאה) והן באופן רקורסיבי‪.‬‬
‫לפעולות במימוש רקורסיבי הוסף את האות ‪ R‬לשם הפעולה‪.‬‬
‫‪- 119 -‬‬
‫למשל פעולה בשם ‪ sum‬תקבל את השם ‪.sumR‬‬
‫(‪ )4‬לכל אחת מהפעולות‪ ,‬רשום את היעילות‪ .‬נמק תשובתך‪.‬‬
‫(‪ )5‬באומרנו "רשימה" ‪ ,‬הכוונה להפניה לחוליה ראשונה ברשימה‪ ,‬או ‪ null‬אם היא ריקה‪.‬‬
‫(‪ )6‬הקפד לתת שמות שמרמזים על תפקיד ההפניה לעצם מטיפוס >‪. Node<T‬‬
‫‪‬‬
‫אם משמעותו רשימה ‪ ,‬קבע שם כגון‪ list , lst :‬וכדומה‪.‬‬
‫‪‬‬
‫אם משמעותו חוליה בודדת‪ ,‬קבע שם כגון ‪. node‬‬
‫‪‬‬
‫אם משמעותו מקום ברשימה‪ ,‬קבע שם כגון‪ position, pos, p, nextPos, prevPos :‬וכדומה‪.‬‬
‫( א ) פעולות בנייה‬
‫‪1‬‬
‫פעולה המקבלת מספר טבעי ‪ n‬ומחזירה רשימה‬
‫של מספרים טבעיים בסדר עולה מ ‪ 1‬עד ‪ n‬כולל‪.‬‬
‫פעולה המקבלת הפנייה לחוליה ראשונה ברשימה‬
‫‪2‬‬
‫)‪public static Node<Integer> create1_N(int n‬‬
‫)‪public static void print (Node<Integer> list‬‬
‫של מספרים שלמים ומדפיסה אותה כך‪:‬‬
‫‪n1  n2  …  null‬‬
‫פעולה היוצרת רשימה עם ‪ n‬מספרים אקראיים בין‬
‫‪3‬‬
‫‪public static Node<Integer> buildRandom‬‬
‫‪ low‬ל ‪ up‬כולל כאשר ‪ n‬מספר טבעי ומחזירה‬
‫)‪(int n, int low, int up‬‬
‫הפנייה לחוליה הראשונה ברשימה‪.‬‬
‫פעולה הבונה רשימה של מספרים שנקלטים‬
‫‪4‬‬
‫)(‪public static Node<Integer> create‬‬
‫מהמשתמש‪ .‬סוף קלט ‪.99‬‬
‫הפעולה מחזירה הפנייה לחוליה ראשונה ברשימה‪,‬‬
‫‪ null‬אם היא ריקה‪.‬‬
‫( ב ) פעולות המחזירות ערך מספרי‬
‫פעולה המקבלת רשימה של מספרים שלמים‬
‫‪5‬‬
‫)‪public static int count (Node<Integer> list‬‬
‫ומחזירה את אורכה‪ ,‬כלומר את מספר האיברים‬
‫ברשימה‪)*( .‬‬
‫פעולה המקבלת רשימה של מספרים שלמים‬
‫‪6‬‬
‫)‪public static int sum (Node<Integer> list‬‬
‫ומחזירה את סכום ערכיה‪)*( .‬‬
‫פעולה המקבלת רשימה של מספרים שלמים‬
‫‪7‬‬
‫‪public static double average‬‬
‫ומחזירה את ממוצע ערכיה‪ - 0 .‬אם הרשימה ריקה‪.‬‬
‫)‪(Node<Integer> list‬‬
‫‪- 120 -‬‬
‫‪8‬‬
‫פעולה המקבלת רשימה של מספרים שלמים‬
‫>‪public static int product (Node<Integer‬‬
‫ומחזירה את מכפלת ערכיה‪ .‬הנחה‪ :‬הרשימה אינה‬
‫)‪list‬‬
‫ריקה‪)*( .‬‬
‫פעולה המקבלת רשימה של מספרים שלמים‬
‫‪9‬‬
‫)‪public static int max (Node<Integer> list‬‬
‫ומחזירה את הערך המקסימלי ‪ .‬הנחה‪ :‬הרשימה‬
‫אינה ריקה‪)*( .‬‬
‫פעולה המקבלת רשימה של מספרים שלמים‬
‫‪10‬‬
‫)‪public static int min (Node<Integer> list‬‬
‫ומחזירה את הערך הכי קטן ‪ .‬הנחה‪ :‬הרשימה אינה‬
‫ריקה‪)*( .‬‬
‫פעולה המקבלת רשימה של מספרים שלמים‬
‫‪11‬‬
‫ומחזירה את סכום הערכים הזוגיים‪.‬‬
‫‪12‬‬
‫פעולה המקבלת רשימה של מספרים שלמים‬
‫>‪public static int sumEven (Node<Integer‬‬
‫(*)‬
‫)‪list‬‬
‫‪public static int sumOddPlaces‬‬
‫ומחזירה את סכום הערכים במקומות האי‪-‬זוגיים‪.‬‬
‫)‪(Node<Integer> list‬‬
‫פעולה המקבלת רשימה של מספרים שלמים ומספר‬
‫‪13‬‬
‫‪public static int countX‬‬
‫שלם נוסף ‪ , x‬ומחזירה את מספר הפעמים‬
‫)‪(Node<Integer> list, int x‬‬
‫שהמספר ‪ x‬מופיע ברשימה‪)*( .‬‬
‫( ג ) פעולות המחזירות ערך בוליאני‬
‫הפעולה מקבלת רשימה של מספרים שלמים‬
‫‪14‬‬
‫>‪public static boolean isUp (Node<Integer‬‬
‫ומחזירה 'אמת' אם היא ממוינת מסודרת בסדר‬
‫)‪list‬‬
‫עולה‪ ',‬שקר' – אחרת‪ .‬עבור רשימה ריקה תחזיר‬
‫'אמת'‪)*( .‬‬
‫הפעולה מקבלת רשימה של מספרים שלמים ומספר‬
‫>‪public static boolean isExist(Node<Integer‬‬
‫‪ 15‬שלם נוסף ‪ ,x‬ומחזירה 'אמת' אם המספר ‪ x‬נמצא‬
‫)‪list, int x‬‬
‫ברשימה‪' ,‬שקר' – אחרת‪)*( .‬‬
‫‪ 16‬הפעולה מקבלת רשימה של מספרים שלמים‬
‫‪public static boolean isArithmetic‬‬
‫ומחזירה 'אמת' אם היא מהווה סדרה חשבונית‪',‬‬
‫)‪(Node<Integer> list‬‬
‫שקר' – אחרת‪ .‬עבור רשימה ריקה תחזיר 'אמת'‪.‬‬
‫(*)‬
‫‪- 121 -‬‬
‫סדרה חשבונית היא סדרת מספרים שההפרש בין‬
‫כל שני ערכים סמוכים זהה‪.‬‬
‫( ד ) פעולות המחזירות הפנייה למקום ברשימה‬
‫פעולה המקבלת רשימה של מספרים שלמים לא‬
‫‪public static Node<Integer> goto‬‬
‫‪ 17‬ריקה ומספר צעדים ‪ step‬ומחזירה את ההפניה‬
‫)‪(Node<Integer> list, int step‬‬
‫לחוליה במקום ‪.step‬‬
‫אם ‪ step‬גדול ממספר החוליות‪ ,‬תחזיר ‪)*( . null‬‬
‫‪ 18‬פעולה המקבלת רשימה של מספרים שלמים לא‬
‫‪public static Node<Integer> gotoLast‬‬
‫ריקה ומחזירה את ההפניה לחוליה אחרונה‪ ,‬או‬
‫)‪(Node<Integer> list‬‬
‫‪ null‬אם הרשימה ריקה (*)‬
‫פעולה המקבלת רשימה של מספרים שלמים ומספר‬
‫‪19‬‬
‫>‪public static Node<Integer‬‬
‫שלם נוסף ‪ x‬ומחזירה הפניה למקום ההופעה‬
‫)‪firstPosX(Node<Integer> list, int x‬‬
‫הראשון של ‪ x‬מתחילת הרשימה‪ ,‬או ‪ – null‬אם לא‬
‫נמצא‪)*( .‬‬
‫פעולה המקבלת רשימה של מספרים שלמים‬
‫‪public static Node<Integer> posMin‬‬
‫ומחזירה הפנייה למיקום הערך הקטן ביותר‬
‫)‪(Node<Integer> list‬‬
‫‪ 20‬ברשימה‪.‬‬
‫הנחות‪ :‬הרשימה אינה ריקה‪ .‬כל הערכים שונים זה‬
‫מזה‪.‬‬
‫הערות‪ )1( :‬בכל הפעולות הבאות נחזיר הפנייה לחוליה ראשונה ברשימה חדשה אשר נוצרה מרשימה קיימת או ‪. null‬‬
‫באומרנו‪ :‬מחזיר רשימה‪ ,‬הכוונה מחזיר הפניה לחוליה הראשונה ברשימה או ‪. null‬‬
‫(‪ )2‬בכל הפעולות הבאות ‪ ,‬הנח ‪ pos‬או ‪ prev‬הם מקומות ברשימה או ‪.null‬‬
‫( ה ) שינוי רשימה קיימת‪ ,‬בפועל מחזיר רשימה חדשה‬
‫פעולה המקבלת רשימה‪ ,‬מקום ברשימה ‪ pos‬וערך‬
‫>‪public static Node<Integer‬‬
‫‪ x‬ומחזירה רשימה חדשה כאשר הערך ‪ x‬נוסף‬
‫>‪insert(Node<Integer> list, Node<Integer‬‬
‫‪ 21‬מקום אחד אחרי ‪ . pos‬אם ‪ , pos=null‬תוחזר‬
‫)‪pos, int x‬‬
‫רשימה בה ‪ x‬התווסף לפני חוליה ראשונה‪.‬‬
‫יעילות הפעולה היא )‪O(1‬‬
‫‪- 122 -‬‬
‫פעולה המקבלת רשימה‪ ,‬מספר צעדים ‪ step‬וערך ‪x‬‬
‫>‪public static Node<Integer‬‬
‫ומחזירה רשימה חדשה בה הערך ‪ x‬נוסף אחרי‬
‫‪insert(Node<Integer> list,‬‬
‫‪ step 22‬צעדים מתחילת הרשימה‪ .‬אם ‪x , step=0‬‬
‫)‪int step, int x‬‬
‫יתווסף לפני חוליה ראשונה‪ .‬אם ‪ step‬גדול מאורך‬
‫הרשימה‪ x ,‬יתווסף בסוף הרשימה‪.‬‬
‫פעולה המקבלת רשימה ומקום ברשימה ‪prev‬‬
‫‪23‬‬
‫ומחזירה רשימה חדשה ללא החוליה העוקבת ל‬
‫>‪public static Node<Integer‬‬
‫>‪delete(Node<Integer> list, Node<Integer‬‬
‫‪ .prev‬אם ‪ , prev=null‬תוחזר רשימה ללא החוליה‬
‫)‪prev‬‬
‫הראשונה‪ .‬יעילות הפעולה היא )‪O(1‬‬
‫פעולה המקבלת רשימה ומספר צעדים ‪step‬‬
‫>‪public static Node<Integer‬‬
‫‪ 24‬מתחילת הרשימה ומחזירה רשימה חדשה ללא‬
‫‪delete(Node<Integer> list,‬‬
‫הערך הנמצא במיקום ‪. step‬‬
‫)‪int step‬‬
‫( ו ) פעולות על רשימות ממוינות‬
‫פעולה המקבלת רשימה ממוינת בסדר עולה ומספר‬
‫>‪public static Node<Integer‬‬
‫‪ 25‬שלם ‪ x‬ומחזירה רשימה חדשה הכוללת את הערך‬
‫)‪insertSort(Node<Integer> list, int x‬‬
‫‪ x‬כך שהיא שומרת על המיון שלה‪.‬‬
‫פעולה המקבלת שתי רשימות ממוינות בסדר עולה‪.‬‬
‫>‪public static Node<Integer‬‬
‫בכל רשימה הערכים שונים זה מזה‪ .‬הפעולה‬
‫‪merge(Node<Integer> list1,‬‬
‫מחזירה רשימה חדשה שהיא מיזוג של שתי‬
‫‪26‬‬
‫)‪Node<Integer> list1‬‬
‫הרשימות‪ .‬כל ערך מופיע רק פעם אחת לכל היותר‪.‬‬
‫הרשימה החדשה מכילה את הערכים משתי‬
‫הרשימות בסדר עולה‪.‬‬
‫מותר לשנות את הרשימות המקוריות‪.‬‬
‫המיזוג יתבצע ביעילות ליניארית‪.‬‬
‫פעולה המקבלת שתי רשימות ממוינות בסדר עולה‪.‬‬
‫>‪public static Node<Integer‬‬
‫בכל רשימה הערכים שונים זה מזה‪ .‬הפעולה‬
‫‪cut(Node<Integer> list1,‬‬
‫‪ 27‬מחזירה רשימה חדשה שהיא חיתוך של שתי‬
‫)‪Node<Integer> list1‬‬
‫הרשימות‪ .‬כלומר‪ :‬הרשימה החדשה תכיל את‬
‫הערכים הנמצאים בשתי הרשימות והיא בסדר‬
‫‪- 123 -‬‬
‫עולה‪ .‬מותר לשנות את הרשימות המקוריות‪.‬‬
‫החיתוך יתבצע ביעילות ליניארית‪.‬‬
‫הערה‪ :‬בפעולות הבאות הכוונה לערכים שבחוליות ולא הפניות לחוליות עצמן‪.‬‬
‫( ז ) פעולות על שתי רשימות‬
‫‪public static boolean isAllExist‬‬
‫פעולה המקבלת שתי רשימות ‪, list1, list2‬‬
‫‪ 28‬ומחזירה 'אמת' אם כל איברי ‪ list2‬נמצאים בסדר‬
‫‪(Node<Integer> list1, Node<Integer> list2‬‬
‫כלשהו ב‪' ,list1-‬שקר'‪-‬אחרת‪.‬‬
‫פעולה המקבלת שתי רשימות ‪ list1, list2‬ומחזירה‬
‫‪public static boolean isSameValues‬‬
‫‪' 29‬אמת' אם שתי הרשימות מכילות אותן ערכים ללא‬
‫‪(Node<Integer> list1,‬‬
‫חשיבות לסדר‪' ,‬שקר'‪-‬אחרת‪.‬‬
‫)‪Node<Integer> list2‬‬
‫‪public static boolean isAllDifferent‬‬
‫פעולה המקבלת שתי רשימות ‪ list1, list2‬ומחזירה‬
‫‪' 30‬אמת' אם לשתי הרשימות אין ערכים משותפים‪,‬‬
‫(‪(Node<Integer> list1, Node<Integer> list2‬‬
‫'שקר'‪-‬אחרת‪.‬‬
‫פעולה המקבלת שתי רשימות ‪ list1,list2‬ומחזירה‬
‫‪public static boolean isIncludeStart‬‬
‫‪' 31‬אמת' אם הרשימה ‪ list2‬מוכלת בשלמותה ברשימה‬
‫‪(Node<Integer> list1,‬‬
‫‪ list1‬החל מראשית הרשימה ‪' ,list1‬שקר'‪-‬אחרת‪.‬‬
‫)‪Node<Integer> list2‬‬
‫פעולה המקבלת שתי רשימות ‪ list1,list2‬ומחזירה‬
‫‪public static boolean isInclude‬‬
‫‪' 32‬אמת' אם רשימה ‪ list2‬מוכלת בשלמותה ברשימה‬
‫‪(Node<Integer> list1,‬‬
‫‪' ,list1‬שקר'‪-‬אחרת‪.‬‬
‫)‪Node<Integer> list2‬‬
‫( ח ) פעולות מיון רשימות‬
‫פעולה הבונה רשימה ממוינת בסדר עולה ממספרים‬
‫‪33‬‬
‫)(‪public static Node<Integer> createSorted‬‬
‫שנקלטו מהמשתמש‪ .‬סוף קלט ‪.99‬‬
‫הפעולה מחזירה הפנייה לחוליה הראשונה ברשימה‪,‬‬
‫‪ null‬אם היא ריקה‪.‬‬
‫‪34‬‬
‫פעולה המקבלת רשימה של מספרים בסדר כלשהו‬
‫‪public static Node<Integer> insertionSort‬‬
‫ומחזירה רשימה ממוינת בסדר עולה בשיטת מיון‪-‬‬
‫)‪(Node<Integer> list‬‬
‫הכנסה ‪insertion-sort‬‬
‫‪- 124 -‬‬
‫‪35‬‬
‫פעולה המקבלת רשימה של מספרים בסדר כלשהו‬
‫‪public static void selectionSort‬‬
‫ומחזירה רשימה ממוינת בסדר עולה בשיטת מיון‪-‬‬
‫)‪(Node<Integer> list‬‬
‫בחירה ‪selection-sort‬‬
‫הנחיה והסבר‪:‬‬
‫במיון‪-‬הכנסה יוצרים רשימה ריקה ומכניסים אליה את הערכים מהרשימה תוך שמירה על סדר עולה‪.‬‬
‫בפעולה זו נעשה שימוש בפעולה הכנס‪-‬לרשימה‪-‬ממוינת‪.‬‬
‫במיון‪-‬בחירה עוברים על הרשימה המקורית ומוצאים את הערך הקטן ביותר ומחליפים אותו עם הערך הנוכחי‪.‬‬
‫פתרונות בג'אווה‬
‫פעולות בנייה‬
‫‪ .1‬פעולה המקבלת מספר טבעי ‪ n‬ומחזירה רשימה של מספרים טבעיים בסדר עולה מ ‪ 1‬עד ‪ n‬כולל‪.‬‬
‫יעילות‪O(n) :‬‬
‫)‪public static Node<Integer> create1_N(int n‬‬
‫{‬
‫;‪Node<Integer> list=null‬‬
‫)‪for (int k=n; k>0;k--‬‬
‫{‬
‫;)‪list = new Node<Integer>(k,list‬‬
‫}‬
‫;‪return list‬‬
‫}‬
‫‪ .2‬פעולה המקבלת הפנייה לחוליה ראשונה ברשימה של מספרים שלמים ומדפיסה אותה כך‪:‬‬
‫‪ . n1  n2  …  null‬אם הרשימה ריקה – יודפס רק ‪ .null‬יעילות‪O(n) :‬‬
‫)‪public static void print(Node<Integer> list‬‬
‫{‬
‫)‪while (list!=null‬‬
‫{‬
‫;)" >‪System.out.print(list.getValue()+" --‬‬
‫;)(‪list = list.getNext‬‬
‫}‬
‫;)"‪System.out.println("null‬‬
‫}‬
‫‪- 125 -‬‬
‫ כולל‬up ‫ ל‬low ‫ מספרים אקראיים בין‬n ‫ פעולה היוצרת רשימה עם‬.3
O(n) :‫יעילות‬
.‫ מספר טבעי ומחזירה הפנייה לחוליה הראשונה ברשימה‬n ‫כאשר‬
public static Node<Integer> buildRandom(int n,int low,int up)
{
Random rnd = new Random();
int num;
Node<Integer> list = null;
for (int k=1; k<=n; k++)
{
num = rnd.nextInt(up-low+1)+low;
//System.out.println("num = "+num);
list = new Node<Integer>(num,list);
}
return list;
}
.99 ‫ סוף קלט‬.‫ פעולה הבונה רשימה של מספרים שנקלטים מהמשתמש‬.4
O(n) :‫ יעילות‬.‫ אם היא ריקה‬null ,‫הפעולה מחזירה הפנייה לחוליה ראשונה ברשימה‬
public static Node<Integer> create()
{
Scanner in = new Scanner(System.in);
int x;
Node<Integer> first, node, pos;
System.out.println("Enter integer , 99 to stop");
x = in.nextInt();
if (x==99)
{// an empty linked-list
return null;
}
// list is not empty
first = new Node<Integer>(x);
pos = first;
// save reference to first node
System.out.println("Enter integer value, 99 to stop");
x = in.nextInt();
- 126 -
while (x!=99)
{
node = new Node<Integer>(x); // create new node
pos.setNext(node);
pos = node;
// connect previous node to current node
// pos refer to last node added
System.out.println("Enter integer value, 99 to stop");
x = in.nextInt();
}
return first;
}
‫פעולות החזרת ערך מספרי‬
O(n) :‫יעילות‬
.‫ פעולה המקבלת רשימה של מספרים שלמים ומחזירה את אורכה‬.5
public static int count(Node<Integer> list)
{
int counter = 0;
Node<Integer> pos = list;
while (pos!=null)
{
counter++;
pos = pos.getNext();
}
return counter;
}
O(n) :‫יעילות‬
public static int countR(Node<Integer> list)
{
if (list == null)
return 0;
return 1 + countR(list.getNext());
}
- 127 -
.‫ אותה פעולה במימוש רקורסיבי‬.5
O(n) :‫ יעילות‬.‫ פעולה המקבלת רשימה של מספרים שלמים ומחזירה את סכום ערכיה‬.6
public static int sum(Node<Integer> list)
{
int sum = 0;
Node<Integer> pos = list;
while (pos!=null)
{
sum = sum + pos.getValue();
pos = pos.getNext();
}
return sum;
}
O(n) :‫יעילות‬
.‫ אותה פעולה במימוש רקורסיבי‬.6
public static int sumR(Node<Integer> list)
{
if (list == null)
return 0;
return list.getValue() + sumR(list.getNext());
}
.‫ פעולה המקבלת רשימה של מספרים שלמים ומחזירה את ממוצע ערכיה‬.7
O(n) :‫יעילות‬
.‫ אם הרשימה ריקה‬- 0
public static double average(Node<Integer> list)
{
if (count(list) != 0)
return (double)(sum(list))/count(list);
return 0;
}
O(n) :‫יעילות‬
public static double averageR(Node<Integer> list)
{
if (countR(list) != 0)
return (double)(sumR(list))/countR(list);
return 0;
}
- 128 -
.‫ אותה פעולה במימוש רקורסיבי‬.7
.‫ פעולה המקבלת רשימה של מספרים שלמים ומחזירה את מכפלת ערכיה‬.8
O(n) :‫יעילות‬
.‫ הרשימה אינה ריקה‬:‫הנחה‬
public static int product(Node<Integer> list)
{
int prod;
if (list == null)
prod = 0;
prod = 1;
Node<Integer> pos = list;
while (pos!=null)
{
prod = prod * pos.getValue();
pos = pos.getNext();
}
return prod;
}
O(n) :‫יעילות‬
.‫ אותה פעולה במימוש רקורסיבי‬.8
public static int productR(Node<Integer> list)
{
if (list == null)
return 0;
if (!list.hasNext())
return list.getValue();
return list.getValue() * productR(list.getNext());
}
. ‫ פעולה המקבלת רשימה של מספרים שלמים ומחזירה את הערך המקסימלי‬.9
O(n) :‫יעילות‬
public static int max(Node<Integer> list)
{
- 129 -
.‫ הרשימה אינה ריקה‬:‫הנחה‬
int max = list.getValue();
Node<Integer> pos = list.getNext();
while (pos!=null)
{
if (pos.getValue() > max)
max = pos.getValue();
pos = pos.getNext();
}
return max;
}
O(n) :‫יעילות‬
.‫ מימוש רקורסיבי של אותה פעולה‬.9
public static int maxR(Node<Integer> list)
{
if (!list.hasNext())
return list.getValue();
return Math.max(list.getValue(), maxR(list.getNext()));
}
. ‫ פעולה המקבלת רשימה של מספרים שלמים ומחזירה את הערך הכי קטן‬.10
O(n) :‫יעילות‬
.‫ הרשימה אינה ריקה‬:‫הנחה‬
public static int min(Node<Integer> list)
{
int min = list.getValue();
Node<Integer> pos = list.getNext();
while (pos!=null)
{
if (pos.getValue() < min)
min = pos.getValue();
pos = pos.getNext();
}
return min;
}
O(n) :‫יעילות‬
public static int minR(Node<Integer> list)
- 130 -
.‫ מימוש רקורסיבי של אותה פעולה‬.10
{
if (!list.hasNext())
return list.getValue();
return Math.min(list.getValue(), minR(list.getNext()));
}
.‫ פעולה המקבלת רשימה של מספרים שלמים ומחזירה את סכום הערכים הזוגיים‬.11
O(n) :‫יעילות‬
public static int sumEven(Node<Integer> list)
{
int sum = 0;
Node<Integer> pos = list;
while (pos!=null)
{
if (pos.getValue()%2 == 0)
sum = sum + pos.getValue();
pos = pos.getNext();
}
return sum;
}
O(n) :‫יעילות‬
.‫ מימוש רקורסיבי של אותה פעולה‬.11
public static int sumEvenR(Node<Integer> list)
{
if (list == null)
return 0;
if (list.getValue()%2 == 0)
return list.getValue() + sumEvenR(list.getNext());
return sumEvenR(list.getNext());
}
.‫זוגיים‬-‫ פעולה המקבלת רשימה של מספרים שלמים ומחזירה את סכום הערכים במקומות האי‬.12
O(n) :‫יעילות‬
public static int sumOddPlaces(Node<Integer> list)
{
int sum = 0;
- 131 -
Node<Integer> pos = list;
while (pos!=null)
{
sum = sum + pos.getValue();
pos = pos.getNext();
if (pos!=null)
pos = pos.getNext();
}
return sum;
}
O(n) :‫יעילות‬
.‫ מימוש רקורסיבי של אותה פעולה‬.12
public static int sumOddPlacesR(Node<Integer> list)
{
if (list==null)
return 0;
return sumOddPlacesR(list, 1);
}
private static int sumOddPlacesR(Node<Integer> list, int place)
{
if (list==null)
return 0;
if (place%2==1)
return list.getValue()+ sumOddPlacesR(list.getNext(), place+1);
return sumOddPlacesR(list.getNext(), place+1);
}
, x ‫ פעולה המקבלת רשימה של מספרים שלמים ומספר שלם נוסף‬.13
O(n) :‫יעילות‬
.‫ מופיע ברשימה‬x ‫ומחזירה את מספר הפעמים שהמספר‬
public static int countX(Node<Integer> list, int x)
{
int counter = 0;
Node<Integer> pos = list;
while (pos!=null)
{
- 132 -
if (pos.getValue() == x)
counter++;
pos = pos.getNext();
}
return counter;
}
O(n) :‫יעילות‬
.‫ מימוש רקורסיבי של אותה פעולה‬.13
public static int countXR(Node<Integer> list, int x)
{
if (list==null)
return 0;
if (list.getValue() == x)
return 1 + countXR(list.getNext(), x);
return countXR(list.getNext(), x);
}
‫פעולות המחזירות ערך בוליאני‬
'‫ הפעולה מקבלת רשימה של מספרים שלמים ומחזירה 'אמת‬.14
.‫ 'שקר' – אחרת‬,‫אם היא ממוינת מסודרת בסדר עולה‬
O(n) :‫ יעילות‬.'‫עבור רשימה ריקה תחזיר 'אמת‬
public static boolean isUp(Node<Integer> list)
{
if (list==null)
return true;
if (!list.hasNext())
return true;
while (list.hasNext())
{
if (list.getValue()>=list.getNext().getValue())
return false;
list = list.getNext();
}
return true;
}
O(n) :‫יעילות‬
- 133 -
.‫ מימוש רקורסיבי של אותה פעולה‬.14
public static boolean isUpR(Node<Integer> list)
{
if (list==null)
return true;
if (!list.hasNext())
return true;
return (list.getValue() < list.getNext().getValue()) &&
isUpR(list.getNext());
}
,x ‫ הפעולה מקבלת רשימה של מספרים שלמים ומספר שלם נוסף‬.15
O(n) :‫ יעילות‬.‫ 'שקר' – אחרת‬,‫ נמצא ברשימה‬x ‫ומחזירה 'אמת' אם המספר‬
public static boolean isExist(Node<Integer> list, int x)
{
while (list!=null)
{
if (list.getValue()==x)
return true;
list = list.getNext();
}
return false;
}
O(n) :‫יעילות‬
.‫ מימוש רקורסיבי של אותה פעולה‬.15
public static boolean isExistR(Node<Integer> list, int x)
{
if (list==null)
return false;
if (list.getValue() == x)
return true;
return isExistR(list.getNext(), x);
}
'‫ הפעולה מקבלת רשימה של מספרים שלמים ומחזירה 'אמת‬.16
.‫' שקר' – אחרת‬,‫אם היא מהווה סדרה חשבונית‬
- 134 -
O(n) :‫ יעילות‬.'‫עבור רשימה ריקה תחזיר 'אמת‬
.‫סדרה חשבונית היא סדרת מספרים שההפרש בין כל שני ערכים סמוכים זהה‬
public static boolean isArithmetic(Node<Integer> list)
{
if (list==null)
return true;
if (!list.hasNext())
return true;
int first, second, diff;
// at least 2 values
first = list.getValue();
list= list.getNext();
second = list.getValue();
diff = second - first;
while (list.hasNext())
{
first = second;
list = list.getNext();
second = list.getValue();
if (second - first != diff)
return false;
}
return true;
}
O(n) :‫יעילות‬
.‫ מימוש רקורסיבי של אותה פעולה‬.16
public static boolean isArithmeticR(Node<Integer> list)
{
if (list==null)
return true;
if (!list.hasNext())
return true;
int diff = list.getNext().getValue()-list.getValue();
return isArithmeticR(list.getNext(), diff);
- 135 -
}
private static boolean isArithmeticR(Node<Integer> list, int d)
{
if (!list.hasNext())
return true;
if ( list.getNext().getValue() - list.getValue() != d)
return false;
return isArithmeticR(list.getNext(), d);
}
‫פעולות המחזירות הפנייה למקום ברשימה‬
‫ פעולה המקבלת רשימה של מספרים שלמים לא ריקה‬.17
.step ‫ ומחזירה את ההפניה לחוליה במקום‬step ‫ומספר צעדים‬
O(n) :‫ יעילות‬. null ‫ תחזיר‬,‫ גדול ממספר החוליות‬step ‫אם‬
public static Node<Integer> goTo(Node<Integer> list, int step)
{
while (list!=null && step>1)
{
list = list.getNext();
step--;
}
return list;
}
O(n) :‫ יעילות‬.‫ מימוש רקורסיבי של אותה פעולה‬.17
public static Node<Integer> gotoR(Node<Integer> list, int step)
{
if (step==1 || list==null)
return list;
return gotoR(list.getNext(), step-1);
}
,‫ פעולה המקבלת רשימה של מספרים שלמים לא ריקה ומחזירה את ההפניה לחוליה אחרונה‬.18
O(n) :‫יעילות‬
public static Node<Integer> gotoLast(Node<Integer> list)
{
- 136 -
.‫ אם הרשימה ריקה‬null ‫או‬
if (list==null)
return null;
while (list.hasNext())
list = list.getNext();
return list;
}
O(n) :‫יעילות‬
.‫ מימוש רקורסיבי של אותה פעולה‬.18
public static Node<Integer> gotoLastR(Node<Integer> list)
{
if (list==null)
return null;
if (!list.hasNext())
return list;
return gotoLastR(list.getNext());
}
x ‫ פעולה המקבלת רשימה של מספרים שלמים ומספר שלם נוסף‬.19
.‫ – אם לא נמצא‬null ‫ או‬,‫ מתחילת הרשימה‬x ‫ומחזירה הפניה למקום ההופעה הראשון של‬
O(n) :‫יעילות‬
public static Node<Integer> firstPosX(Node<Integer> list, int x)
{
while (list!=null && list.getValue()!=x)
list= list.getNext();
return list;
}
‫ מימוש רקורסיבי של אותה פעולה‬.19
public static Node<Integer> firstPosX_R(Node<Integer> list, int x)
{
if (list==null || list.getValue()==x)
return list;
return firstPosX_R(list.getNext(), x);
}
.‫ פעולה המקבלת רשימה של מספרים שלמים ומחזירה הפנייה למיקום הערך הקטן ביותר ברשימה‬.20
- 137 -
O(n) :‫ יעילות‬.‫ כל הערכים שונים זה מזה‬.‫ הרשימה אינה ריקה‬:‫הנחות‬
public static Node<Integer> posMin(Node<Integer> list)
{
Node<Integer> minPos = list;
int val, minVal;
if (list == null)
return null;
minVal = list.getValue();
list = list.getNext();
while (list!=null)
{
val = list.getValue();
if (val<minVal)
{
minVal = val;
minPos = list;
}
list = list.getNext();
}
return minPos;
}
‫ בפועל מחזיר רשימה חדשה‬,‫שינוי רשימה קיימת‬
x ‫ וערך‬pos ‫ מקום ברשימה‬,‫ פעולה המקבלת רשימה‬.21
. pos ‫ נוסף מקום אחד אחרי‬x ‫ומחזירה רשימה חדשה כאשר הערך‬
.‫ התווסף לפני חוליה ראשונה‬x ‫ תוחזר רשימה בה‬, pos=null ‫אם‬
O(1) ‫יעילות הפעולה היא‬
public static Node<Integer> insert(Node<Integer> list, Node<Integer> pos, int x)
{
Node<Integer> node = new Node<Integer>(x);
if (list == null)
{// list is empty, return list with one value x
return node;
}
if (pos==null)
{// insert before first
- 138 -
node.setNext(list);
return node;
}
// insert after pos
node.setNext(pos.getNext());
pos.setNext(node);
return list;
}
x ‫ וערך‬step ‫ מספר צעדים‬,‫ פעולה המקבלת רשימה‬.22
.‫ צעדים מתחילת הרשימה‬step ‫ נוסף אחרי‬x ‫ומחזירה רשימה חדשה בה הערך‬
.‫ יתווסף בסוף הרשימה‬x ,‫ גדול מאורך הרשימה‬step ‫ אם‬.‫ יתווסף לפני חוליה ראשונה‬x , step=0 ‫אם‬
O(n) :‫יעילות‬
public static Node<Integer> insert(Node<Integer> list, int step, int x)
{
Node<Integer> node = new Node<Integer>(x);
if (list==null)
return node;
if (step==0)
{
node.setNext(list);
return node;
}
Node<Integer> pos = list;
while (step>1 && pos!=null)
{
pos = pos.getNext();
step--;
}
// insert after pos
node.setNext(pos.getNext());
pos.setNext(node);
return list;
}
- 139 -
.prev ‫ ומחזירה רשימה חדשה ללא החוליה העוקבת ל‬prev ‫ פעולה המקבלת רשימה ומקום ברשימה‬.23
.‫ תוחזר רשימה ללא החוליה הראשונה‬, prev=null ‫אם‬
O(1) ‫יעילות הפעולה היא‬
public static Node<Integer> delete(Node<Integer> list, Node<Integer> prev)
{
if (list==null)
return list;
if (prev==null)
return list.getNext();
if (prev.hasNext())
{
Node<Integer> pos = prev.getNext();
prev.setNext(pos.getNext());
pos.setNext(null);
}
return list;
}
‫ מתחילת הרשימה‬step ‫ פעולה המקבלת רשימה ומספר צעדים‬.24
O(n) :‫ יעילות‬. step ‫ומחזירה רשימה חדשה ללא הערך הנמצא במיקום‬
public static Node<Integer> delete(Node<Integer> list, int step)
{
if (list==null)
return list;
if (step<=1)
return list.getNext();
Node<Integer> prev = list;
while (step >2 && prev.hasNext())
{
prev = prev.getNext();
step--;
}
if (prev.hasNext())
{
- 140 -
Node<Integer> pos = prev.getNext();
prev.setNext(pos.getNext());
pos.setNext(null);
}
return list;
}
‫פעולות על רשימות ממוינות‬
x ‫ פעולה המקבלת רשימה ממוינת בסדר עולה ומספר שלם‬.25
O(n) :‫יעילות‬
.‫ כך שהיא שומרת על המיון שלה‬x ‫ומחזירה רשימה חדשה הכוללת את הערך‬
public static Node<Integer> insertSort(Node<Integer> list, int x)
{
Node<Integer> node = new Node<Integer>(x);
if (list==null)
return node;
Node<Integer>pos = list;
if (x<pos.getValue())
{// add before first node
node.setNext(pos);
return node;
}
while (pos.hasNext() && x > pos.getNext().getValue())
pos = pos.getNext();
node.setNext(pos.getNext());
pos.setNext(node);
return list;
}
.‫ בכל רשימה הערכים שונים זה מזה‬.‫ פעולה המקבלת שתי רשימות ממוינות בסדר עולה‬.26
.‫הפעולה מחזירה רשימה חדשה שהיא מיזוג של שתי הרשימות‬
.‫כל ערך מופיע רק פעם אחת לכל היותר‬
.‫הרשימה החדשה מכילה את הערכים משתי הרשימות בסדר עולה‬
O(n+m) .‫ המיזוג יתבצע ביעילות ליניארית‬.‫מותר לשנות את הרשימות המקוריות‬
- 141 -
.‫ ללא שינוי הרשימות המקוריות‬,‫ מימוש ראשון‬.26
.‫ תוך יצירת חוליות חדשות‬,‫מוחזרת רשימה חדשה שהיא רשימת המיזוג‬
public static Node<Integer> merge (Node<Integer> list1, Node<Integer> list2)
{
if (list1==null)
return list2;
if (list2==null)
return list1;
Node<Integer> mergedList = null;
Node<Integer> pos1, pos2, pos3;
pos1 = list1;
pos2 = list2;
pos3 = mergedList;
while (pos1 != null && pos2 != null)
{
if (pos1.getValue() < pos2.getValue())
{
mergedList = insert(mergedList, pos3, pos1.getValue());
pos1 = pos1.getNext();
}
else
{
if (pos1.getValue() > pos2.getValue())
{
mergedList = insert(mergedList, pos3, pos2.getValue());
pos2 = pos2.getNext();
}
else
{
mergedList = insert(mergedList, pos3, pos2.getValue());
pos1 = pos1.getNext();
pos2 = pos2.getNext();
}
}
if (pos3 == null) // first node in merged list
- 142 -
pos3 = mergedList;
else
pos3 = pos3.getNext();
}
while (pos1 != null)
{// tail of list1
mergedList = insert(mergedList, pos3, pos1.getValue());
pos1 = pos1.getNext();
pos3 = pos3.getNext();
}
while (pos2 != null)
{// tail of list2
mergedList = insert(mergedList, pos3, pos2.getValue());
pos2 = pos2.getNext();
pos3 = pos3.getNext();
}
return mergedList;
}
.‫ יש שימוש בחוליות קיימות‬.‫ בה הרשימה הראשונה מוחזרת כרשימת המיזוג‬, ‫ מימוש שני‬.26
public static Node<Integer> merge1(Node<Integer> list1, Node<Integer> list2)
{
if (list1==null)
return list2;
if (list2==null)
return list1;
// list1!=null && list2!=null
int x,y;
Node<Integer> mrgList;
// refer to merged sortedlist
// choose reference to mrgList
if (list1.getValue()<list2.getValue())
{
mrgList = list1;
- 143 -
list1 = list1.getNext();
}
else
{// list1.getValue()>=list2.getValue()
mrgList = list2;
list2 = list2.getNext();
}
Node<Integer> posMrg = mrgList;
while (list1!=null && list2!=null)
{
if (list1.getValue()<list2.getValue())
{
posMrg.setNext(list1);
list1 = list1.getNext();
}
else
{// list1.getValue()>=list2.getValue()
posMrg.setNext(list2);
list2 = list2.getNext();
}
posMrg = posMrg.getNext();
}// end while
while (list1!=null)
{// tail of list1
posMrg.setNext(list1);
list1 = list1.getNext();
posMrg = posMrg.getNext();
}
while (list2!=null)
{// tail of list2
posMrg.setNext(list2);
list2 = list2.getNext();
posMrg = posMrg.getNext();
- 144 -
}
return mrgList;
}
.‫ פעולה המקבלת שתי רשימות ממוינות בסדר עולה‬.27
.‫בכל רשימה הערכים שונים זה מזה‬
.‫הפעולה מחזירה רשימה חדשה שהיא חיתוך של שתי הרשימות‬
.‫ הרשימה החדשה תכיל את הערכים הנמצאים בשתי הרשימות והיא בסדר עולה‬:‫כלומר‬
O(n+m) .‫ החיתוך יתבצע ביעילות ליניארית‬.‫מותר לשנות את הרשימות המקוריות‬
.‫ ללא שינוי הרשימות המקוריות ומוחזרת רשימה חדשה תוך יצירת חוליות חדשות‬,‫מימוש ראשון‬
public static Node<Integer> cut(Node<Integer> list1, Node<Integer> list2)
{
Node<Integer> listCut=null;
Node<Integer> posCut=listCut;
while (list1!=null && list2!=null)
{
if (list1.getValue()<list2.getValue())
list1 = list1.getNext();
else
if (list1.getValue()>list2.getValue())
list2 = list2.getNext();
else
{// list1.getValue()==list2.getValue()
listCut = insert(listCut, posCut, list1.getValue());
list1 = list1.getNext();
list2 = list2.getNext();
if (posCut==null) // first node
posCut = listCut;
else
posCut = posCut.getNext();
}
}// end while
return listCut;
}
- 145 -
.‫ יש שימוש בחוליות קיימות‬.‫ בה הרשימה הראשונה מוחזרת כרשימת החיתוך‬, ‫ מימוש שני‬.27
public static Node<Integer> cut1(Node<Integer> list1, Node<Integer> list2)
{
Node<Integer> listCut;
Node<Integer> posCut;
Node<Integer> tempPos;
// search first common value
while (list1!=null && list2!=null &&
list1.getValue()!=list2.getValue())
{
if (list1.getValue()<list2.getValue())
list1 = list1.getNext();
else // list1.getValue()>list2.getValue()
list2 = list2.getNext();
}
if (list1==null || list2==null)
return null;
// list1.getValue()==list2.getValue()
listCut = list1;
// for example
posCut = listCut;
int val1,val2;
while (posCut.hasNext())
{
val1 = posCut.getNext().getValue();
val2=list2.getValue();
if (val1==val2)
{// leave this value in list1
posCut = posCut.getNext();
list2 = list2.getNext();
}
else
{
- 146 -
if (val1<val2)
{// removes value from list1
tempPos = posCut.getNext();
posCut.setNext(tempPos.getNext());
tempPos.setNext(null);
}
else // go on with list2
list2 = list2.getNext();
}
}
return listCut;
}
‫פעולות על שתי רשימות‬
'‫ ומחזירה 'אמת‬, list1, list2 ‫ פעולה המקבלת שתי רשימות‬.28
O(n*m) :‫יעילות‬
.‫אחרת‬-'‫ 'שקר‬,list1-‫ נמצאים בסדר כלשהו ב‬list2 ‫אם כל איברי‬
public static boolean isAllExist(Node<Integer> list1, Node<Integer> list2)
{
if (list2==null)
return true;
if (list1==null)
return false;
int x = list2.getValue();
return isExistR(list1, x) && isAllExist(list1, list2.getNext());
}
‫ ומחזירה 'אמת' אם שתי הרשימות‬list1, list2 ‫ פעולה המקבלת שתי רשימות‬.29
O(n*m) :‫יעילות‬
.‫אחרת‬-'‫ 'שקר‬,‫מכילות אותן ערכים ללא חשיבות לסדר‬
public static boolean isSameValues(Node<Integer> list1, Node<Integer> list2)
{
return isAllExist(list1, list2) &&
isAllExist(list2, list1) ;
}
- 147 -
'‫ ומחזירה 'אמת‬list1, list2 ‫ פעולה המקבלת שתי רשימות‬.30
O(n*m) :‫ יעילות‬.‫אחרת‬-'‫ 'שקר‬,‫אם לשתי הרשימות אין ערכים משותפים‬
public static boolean isAllDifferent(Node<Integer> list1, Node<Integer> list2)
{
int x;
while (list1!=null)
{
x = list1.getValue();
if (isExist(list2, x))
return false;
list1 = list1.getNext();
}
return true;
}
O(n*m) :‫יעילות‬
)27 ‫ (שנכתבה בסעיף‬cut ‫ מימוש בעזרת הפעולה‬.a30
public static boolean isAllDifferentSort (Node<Integer> list1, Node<Integer> list2)
{
return ( cut(list1,list2)==null);
}
‫ מוכלת‬list2 ‫ ומחזירה 'אמת' אם הרשימה‬list1, list2 ‫ פעולה המקבלת שתי רשימות‬.31
.‫אחרת‬-'‫ 'שקר‬,list1 ‫ החל מראשית הרשימה‬list1 ‫בשלמותה ברשימה‬
.list2 ‫ הוא אורך הרשימה‬n ‫ כאשר‬,O(n) :‫יעילות‬
public static boolean isIncludeStart(Node<Integer> list1,Node<Integer> list2)
{
int val1,val2;
while (list1!=null && list2!=null)
{
if (list1.getValue()!=list2.getValue())
return false;
list1 = list1.getNext();
list2 = list2.getNext();
}
return list2==null;
}
- 148 -
'‫ ומחזירה 'אמת‬list1, list2 ‫ פעולה המקבלת שתי רשימות‬.32
O(n*m) :‫יעילות‬
.‫אחרת‬-'‫ 'שקר‬,list1 ‫ מוכלת בשלמותה ברשימה‬list2 ‫אם רשימה‬
public static boolean isInclude (Node<Integer> list1, Node<Integer> list2)
{
while (list1!=null)
{
if (isIncludeStart(list1, list2))
return true;
list1 = list1.getNext();
}
return false;
}
‫פעולות מיון רשימות‬
.99 ‫ סוף קלט‬.‫ פעולה הבונה רשימה ממוינת בסדר עולה ממספרים שנקלטו מהמשתמש‬.33
2
O(n ) :‫יעילות‬
.‫ אם היא ריקה‬null ,‫הפעולה מחזירה הפנייה לחוליה הראשונה ברשימה‬
public static Node<Integer> createSorted()
{
Scanner in = new Scanner(System.in);
Node<Integer> list=null;
int x;
System.out.println("Enter integer , 99 to stop");
x = in.nextInt();
while (x!=99)
{
list = insertSort(list, x);
System.out.println("Enter integer , 99 to stop");
x = in.nextInt();
}
return list;
}
‫ פעולה המקבלת רשימה של מספרים בסדר כלשהו ומחזירה רשימה ממוינת בסדר עולה בשיטת‬.34
O(n2) :‫ יעילות‬.insertion-sort ‫הכנסה‬-‫מיון‬
public static Node<Integer> insertionSort(Node<Integer> list)
- 149 -
{
int x;
Node<Integer> sortList = null;
while (list!=null)
{
x = list.getValue();
sortList = insertSort(sortList, x);
list = list.getNext();
}
return sortList;
}
‫ פעולה המקבלת רשימה של מספרים בסדר כלשהו ומחזירה רשימה ממוינת בסדר עולה בשיטת‬.35
O(n2) :‫ יעילות‬. selection-sort ‫בחירה‬-‫מיון‬
public static void selectionSort(Node<Integer> list)
{
int temp;
Node<Integer> pos, minPos;
pos = list;
while (pos!=null)
{
minPos = posMin(pos);
if (pos!=minPos)
{
temp = pos.getValue();
pos.setValue(minPos.getValue());
minPos.setValue(temp);
}
pos = pos.getNext();
}
}
- 150 -
‫דפים מדורגים‪ :‬מיון מיזוג‬
‫פיתוח‪ :‬גלית שריקי וחני טוראל‬
‫דף מספר ‪1‬‬
‫חישבו על גישה שונה לפתרון הבעיה של מיון מערך‬
‫כך שיעילותו תהיה קטנה מ‪.O(n²) -‬‬
‫רמז‪:‬‬
‫היזכרו בתהליך המיזוג אותו למדתם בשנה שעברה‪ .‬כדי למיין מערך ניתן לחלקו לשני תתי‬
‫מערכים שווים בגודלם פחות או יותר‪ ,‬למיין כל אחד מהם‪ ,‬ולאחר מכן למזג בין המערכים‬
‫הממוינים‪.‬‬
‫דף מספר ‪2‬‬
‫השתמשו ברקורסיה בכדי למיין מערכים‪,‬‬
‫כך שיעילות המיון שלהם תהיה פחותה מ‪,O(n²) -‬‬
‫בצורה הבאה‪:‬‬
‫נחלק כל אחד מחלקי המערך לשני מערכים נוספים עד אשר נגיע לקטע מערך באורך ‪ 1‬ואז נמזג‬
‫את המערכים בצורה ממוינת (מערך בגודל ‪ 1‬הינו מערך ממוין)‪.‬‬
‫דף מספר ‪3‬‬
‫לפניכם האלגוריתם למיון מיזוג‪ ,‬ממשו אותו‪.‬‬
‫מיון‪-‬מיזוג(‪)arr‬‬
‫אם גודל המערך גדול מ‪ 1-‬בצע‪:‬‬
‫(‪)1‬‬
‫חלק את המערך לשני תתי מערכים ‪arr1‬ו‪ ,arr2 -‬המכילים כל אחד‬
‫כמחצית מאיברי המערך‬
‫(‪)2‬‬
‫מיון‪-‬מיזוג(‪)arr1‬‬
‫(‪)3‬‬
‫מיון‪-‬מיזוג(‪)arr2‬‬
‫(‪)4‬‬
‫מזג את ‪ arr1‬ואת ‪ arr2‬לתוך ‪arr‬‬
‫‪- 151 -‬‬
‫דף מספר ‪4‬‬
‫האיור הבא מתאר את ריצת האלגוריתם על מערך שבו ארבעה איברים‪:‬‬
‫ממשו את שלבים (‪ )1‬ו‪ )4( -‬באמצעות פעולות עזר‪.‬‬
‫‪- 152 -‬‬
5 ‫דף מספר‬
.)‫) באלגוריתם למיון מיזוג‬4( ‫לפניכם פעולה למיזוג מערכים ממוינים (שלב‬
.‫ממשו את שאר הפקודות באלגוריתם‬
public static void sort(int[] arr, int[] arr1, int[] arr2)
{
int i=0,j=0;
while (i < arr1.length && j<arr2.length)
{
if (arr1[i]<arr2[j])
{
arr[i+j]=arr1[i];
i++;
}
else
{
arr[i+j]=arr2[j];
j++;
}
}
if (i < arr1.length)
while (i < arr1.length)
{
arr[i+j]=arr1[i];
i++;
}
else
while (j < arr2.length)
{
arr[i+j]=arr2[j];
j++;
}
}
- 153 -
6 ‫דף מספר‬
‫) של‬1( ‫ (שלב‬arr2 -‫ ו‬arr1 ‫ לשני מערכים‬arr ‫לפניכם פעולת עזר המחלקת את המערך‬
.)‫האלגוריתם‬
public static void divide (int[] arr, int[] arr1, int[] arr2)
{
for (int i = 0; i < arr1.length; i++)
{
arr1[i]=arr[i];
}
for (int i = 0; i < arr2.length; i++)
{
arr2[i]=arr[arr.length/2+i];
}
}
divide ‫ ואת גודלם לפני הזימון של הפעולה‬arr2 -‫ ו‬arr1 ‫ הגדירו את המערכים‬.‫א‬
.‫) של האלגוריתם‬4( -‫) ו‬3( ‫ השלימו את שלבים‬.‫ב‬
7 ‫דף מספר‬
‫ השלימו את הסעיפים החסרים והריצו את‬,‫לפניכם האלגוריתם הכמעט מלא לפתרון הבעיה‬
‫התכנית‬
public static void mergeSort(int []arr)
{
if (arr.length!=1)
{
int[] arr1=new int[arr.length/2];
int[] arr2=new int[arr.length-arr1.length];
devide(arr,arr1,arr2);
)2(
)3(
sort(arr,arr1,arr2(;
}
}
- 154 -
‫דף מספר ‪8‬‬
‫תרגיל המשך‪:‬‬
‫לפניכם האלגוריתם המוצא את המכנה המשותף הגבוה ביותר (ממ"ג) שיעילותו היא )‪o(n‬‬
‫שפרו את היעילות בעזרת אלגוריתם רקורסיבי‪.‬‬
‫)‪public static int mamag(int a, int b‬‬
‫{‬
‫)‪for (int i=a-1;i>1;i--‬‬
‫{‬
‫)‪if (b%i == 0 && a%i == 0‬‬
‫;‪return i‬‬
‫}‬
‫;‪return 1‬‬
‫}‬
‫‪- 155 -‬‬
‫דפים מדורגים‪ :‬שמונה מלכות‬
‫פיתוח‪ :‬ענת שלוס‪-‬סגל‬
‫דף מספר ‪1‬‬
‫בעיית שמונה המלכות‬
‫מלכה (‪ )Queen‬במשחק שח‪-‬מט יכולה לנועה בשורה‪ ,‬בטור או באלכסון יחסית למקום שהיא עומדת בו‪.‬‬
‫המלכה יכולה לנוע מספר בלתי מוגבל של משבצות בכיוון הנבחר‪ ,‬כל עוד כלי אחר אינו חוסם את דרכה‪ ,‬וכן כל עוד‬
‫לא יצאה מהלוח‪.‬‬
‫מלכה יכולה להכות כל כלי העומד בדרכה אך אחרי שהכתה כלי (כלומר הוציאה אותו מהמשחק ונעמדה במקומו)‬
‫היא אינה יכולה לנוע יותר עד לתור הבא‪.‬‬
‫מלכה מאיימת על כל הכלים הנמצאים בשורה‪ ,‬בעמודה או באלכסון של המשבצת בה היא ניצבת (כלומר יכולה‬
‫להוציאם בתורה)‪.‬‬
‫כתבו פעולה רקורסיבית שתציב שמונה מלכות על לוח שחמט ריק (מערך דו‪0‬ממדי בגודל ‪ ,)8X8‬כך שאף אחת‬
‫לא תאיים על האחרות‪.‬‬
‫(מתוך הספר עיצוב תוכנה מבוסס עצמים פרק ‪ – 4‬שאלה ‪)31‬‬
‫דף מספר ‪2‬‬
‫כל מלכה תמוקם בשורה נפרדת‪ ,‬הבעיה הנותרת היא למצוא עבור כל מלכה את העמודה הנכונה‪.‬‬
‫כדי לדמות לוח נעשה שימוש במערך דו‪-‬ממדי של ערכים בוליאניים‪ .‬בכל משבצת בה תמוקם מלכה יושם הערך‬
‫‪.true‬‬
‫מקמו את המלכה הראשונה על הלוח במקום הפנוי הראשון‪.‬‬
‫המשיכו בהצבת שאר המלכות בשורות הבאות כך שאף אחת לא תאיים על האחרות‪.‬‬
‫‪- 156 -‬‬
‫דף מספר ‪3‬‬
‫לפניכם שלד הפעולה ‪ PlaceQueens‬המציבה את המלכות על הלוח‪:‬‬
‫)‪static bool PlaceQueens(bool[,] board, int row‬‬
‫{‬
‫‪...‬‬
‫;‪board[row, ?] = true‬‬
‫‪...‬‬
‫}‬
‫הפעולה תקבל את מספר השורה של המלכה אותה אנו רוצים למקם כעת על הלוח‪.‬‬
‫הפעולה תחזיר ‪ true‬במידה וההצבה הצליחה‪ ,‬אחרת במידה ואין פתרון לבעיה הפעולה תחזיר ‪.false‬‬
‫נתחיל בהצבת המלכה הראשונה בשורה ‪:0‬‬
‫)‪static void Main(string[] args‬‬
‫{‬
‫;]‪bool[,] board = new bool[8, 8‬‬
‫))‪if (PlaceQueens(board, 0‬‬
‫יש פתרון ‪//‬‬
‫}‬
‫המשיכו בהצבת שאר המלכות על הלוח באופן רקורסיבי‪.‬‬
‫דף מספר ‪4‬‬
‫מה קורה כאשר המיקום של המלכה בעמודה אינו בטוח (מלכות אחרות מאיימות עליה)?‬
‫כיצד נמצא את העמודה הנכונה?‬
‫מה קורה אם לא ניתן למקם את המלכה באף אחת מהעמודות בשורה הנתונה?‬
‫אולי המיקום שבחרנו לאחת מהמלכות הקודמות שגוי?‬
‫צפו בסרטון הבאה והמשיכו במשימה‪:‬‬
‫‪https://www.youtube.com/watch?v=ZM7RGa8W2KA‬‬
‫‪- 157 -‬‬
‫דף מספר ‪5‬‬
‫מה קורה כאשר המיקום של המלכה בעמודה אינו בטוח?‬
‫נעבור לעמודה הבאה‪.‬‬
‫* איך בודקים אם המיקום בטוח? נשאיר זאת להמשך‬
‫מה קורה אם לא ניתן למקם את המלכה באף אחת מהעמודות בשורה?‬
‫אין פתרון‪ ,‬עלינו להחזיר ‪.false‬‬
‫אולי המיקום שבחרנו לאחת מהמלכות הקודמות שגוי?‬
‫נחזור אחורה )‪ (backtracking‬ונחפש עבורה מיקום חדש‪.‬‬
‫לפניכם הפעולה ‪ PlaceQueens‬השלימו את הוראות ה ‪ return‬בהתאם‪:‬‬
‫)‪static bool PlaceQueens(bool[,] board, int row‬‬
‫{‬
‫) ‪if ( . . .‬‬
‫; ‪return . . .‬‬
‫)‪for (int col = 0; col < N; col++‬‬
‫{‬
‫) האם המיקום בעמודה בטוח ? ( ‪if‬‬
‫{‬
‫;‪board[row, col] = true‬‬
‫))‪if (PlaceQueens(board, row + 1‬‬
‫; ‪return . . .‬‬
‫;‪board[row, col] = false‬‬
‫}‬
‫}‬
‫; ‪return . . .‬‬
‫}‬
‫שימו ♥ ‪ -‬לא לשכוח את תנאי העצירה!‬
‫דף מספר ‪6‬‬
‫כיצד מוודאים שאף מלכה לא מאוימת ע"י האחרות?‬
‫כתבו פעולה המקבלת את לוח המשחק ומיקום של מלכה ובודקת שהיא אינה מאוימת ע"י המלכות שכבר מוצבות‬
‫על הלוח‪.‬‬
‫‪- 158 -‬‬
7 ‫דף מספר‬
:‫לפניכם מימוש חלקי של הפעולה הבודקת שהמלכה אינה מאוימת ע"י המלכות הקודמות‬
static bool Safe(bool[,] board, int row, int col)
{
for (int i = 0; i <= row; i++)
{
if (board[i, col])
return false;
if (. . . )
return false;
if (. . .)
return false;
}
return true;
}
.)‫השלימו את הפעולה (זכרו לבדוק גם את האלכסונים‬
8 ‫דף מספר‬
:‫לפניכם הפעולה המלאה שבודקת שמיקום המלכה אינו מאוים ע"י המלכות הקיימות‬
static bool Safe(bool[,] board, int row, int col)
{
for (int i = 0; i <= row; i++)
{
if (board[i, col]) // ‫אותה עמודה‬
return false;
if (i <= col && board[row - i, col - i]) // ‫אלכסון ראשי‬
return false;
if (col + i < N && board[row - i, col + i]) // ‫אלכסון משני‬
return false;
}
return true;
}
.PlaceQueens ‫שבצו אותה במקום המתאים בפעולה‬
- 159 -
9 ‫דף מספר‬
:‫לפניכם הפתרון המלא לבעיה‬
static bool PlaceQueens(bool[,] board, int row)
{
if (row == N)
return true;
for (int col = 0; col < N; col++)
{
if (Safe(board, row, col))
{
board[row, col] = true;
if (PlaceQueens(board, row + 1))
return true;
board[row, col] = false;
}
}
return false;
}
:‫משימות נוספות‬
.‫ הריצו את התכנית עבור גדלים שונים של לוחות‬.1
.‫ הוסיפו הדפסה של הלוח עם הפתרון‬.2
- 160 -
‫התאמת שאלות לתכנית הלימודים החדשה‬
‫מבני נתונים‬
‫בגרות תשנ"ז שאלה ‪( 1‬ברכה דאום‪-‬רייטר) ‪162 .........................................................................‬‬
‫בגרות תשנ"ח שאלה ‪( 13‬דפנה מינסטר‪ ,‬ולרי פקר‪ ,‬מושית ורחל) ‪163 ..........................‬‬
‫בגרות תשס"א שאלה ‪( 1‬שרה פונק) ‪168 ......................................................................................‬‬
‫בגרות תשס"ג שאלה ‪( 1‬חיה עידן) ‪173 .........................................................................................‬‬
‫בגרות תשס"ה שאלה ‪( 2‬יבגני קנל ודורית ליקרמן) ‪174 ........................................................‬‬
‫בגרות תשס"ו שאלה ‪( 4‬ענת שלוס סגל‪ ,‬אוי‪ ,‬מושית ורחל) ‪176 .......................................‬‬
‫בגרות תשס"ז שאלה ‪( 4‬רוני אלנקרי‪ ,‬יוסי זהבי) ‪183 ..............................................................‬‬
‫בגרות תשס"ח שאלה ‪( 2‬רחל לודמר‪ ,‬גיא אורן) ‪186 ................................................................‬‬
‫בגרות תשס"ט שאלה ‪( 1‬ולרי פקר‪ ,‬דפנה לוי רשתי) ‪190 .......................................................‬‬
‫בגרות תש"ע שאלה ‪( 2‬גלית שריקי‪ ,‬חני טוראל‪ ,‬ישראל אברמוביץ) ‪192 ....................‬‬
‫בגרות תשע"ג שאלה ‪( 1‬ולרי פקר‪ ,‬רחלי צרניחוב‪ ,‬משה ניסים) ‪196 ..............................‬‬
‫בגרות תשע"ג שאלה ‪( 3‬ולרי פקר) ‪201 ............................................................................................‬‬
‫‪- 161 -‬‬
‫ניסוח מחודש של שאלות בגרות והתאמתן לתכנית הלימודים החדשה‬
‫פיתוח‪ :‬משתתפי קורס מורים מובילים תשע"ה‬
‫שאלה ‪ ,1‬בגרות תשנ"ז ‪1997‬‬
‫ברכה דאום‪-‬רייטר‬
‫הניסוח המקורי‪:‬‬
‫נתונות שתי רשימות מקושרות ‪ L1‬ו‪ ,L2 -‬של מספרים שלמים גדולים מאפס שהאורכים שלהם לא ידועים‪.‬‬
‫כתוב תכנית‪ ,‬בשפת פסקל או בשפת בייסיק מובנה‪ ,‬שתיצור משתי הרשימות ‪ L1‬ו‪ L2-‬רשימה מקושרת חדשה ‪L3‬‬
‫באופן הזה‪ :‬התכנית תאתר עבור כל איבר ב‪ L1 -‬את האיברים ב‪ L2 -‬שהם כפולות שלו‪ ,‬ותעביר את האיברים האלו ל‪-‬‬
‫‪ .L3‬כלומר‪ ,‬בסוף התהליך תכיל הרשימה ‪ L2‬אך ורק איברים שלא נמצאו להם מחלקים ב‪.L1-‬‬
‫הצעה לניסוח חדש שיתאים לתכנית "מבני נתונים"‪:‬‬
‫נתונות הפניות לשתי שרשרות חוליות ‪ chain1‬ו‪ ,chain2 -‬שבהן מספרים שלמים גדולים מאפס שהאורכים שלהן לא‬
‫ידועים‪.‬‬
‫כתוב פעולה חיצונית שתקבל את שתי ההפניות לשרשרות ‪ chain1‬ו‪ chain2-‬ותחזיר הפניה לשרשרת חוליות חדשה‬
‫‪ chain3‬שתיבנה באופן הזה‪:‬‬
‫הפעולה תאתר עבור כל איבר ב‪ chain1-‬את האיברים ב‪ chain2-‬שהם כפולות שלו‪ ,‬ותעביר את האיברים הללו ל‪-‬‬
‫‪ .chain3‬כלומר בסוף התהליך תכיל השרשרת ‪ chain2‬אך ורק איברים שלא נמצאו להם מחלקים ב‪.chain1-‬‬
‫הצעה נוספת‪:‬‬
‫‪.1‬נתונה כותרת הפעולה‪:‬‬
‫)‪)public static Boolean IsDivider(Node<int> N1, Node<int> N2‬‬
‫המקבלת הפניות לשתי חוליות ומחזירה אמת אם החוליה ‪ N1‬מחלקת את החוליה ‪.N2‬‬
‫ממש את הפעולה בשפת ‪.java‬‬
‫‪ .2‬נתונות הפניות לשתי שרשרות חוליות ‪ chain1‬ו‪ ,chain2 -‬של מספרים שלמים גדולים מאפס שהאורכים‬
‫שלהם לא ידועים‪.‬‬
‫כתוב פעולה חיצונית שתקבל את שתי ההפניות לשרשרות ‪ chain1‬ו‪ chain2-‬ותחזיר הפניה לשרשרת חוליות חדשה‬
‫‪ chain3‬שתיבנה באופן הזה‪:‬‬
‫הפעולה תאתר עבור כל איבר ב‪ chain1-‬את האיברים ב‪ chain2-‬שהם כפולות שלו‪ ,‬ותעביר את האיברים הללו ל‪-‬‬
‫‪ .chain3‬כלומר בסוף התהליך תכיל השרשרת ‪ chain2‬אך ורק איברים שלא נמצאו להם מחלקים ב‪.chain1-‬‬
‫השתמש בפעולת העזר שכתבת בסעיף ‪.1‬‬
‫‪- 162 -‬‬
‫שאלה ‪ ,13‬בגרות קיץ תשנ"ח ‪1998‬‬
‫הניסוח המקורי‪:‬‬
‫מקטע‪-‬משותף‪-‬מקסימלי לשתי רשימות נתונות הוא תת‪-‬הרשימה הרצופה המקסימלית המשותפת לשתיהן‪.‬‬
‫לדוגמה‪ :‬עבור הרשימות ‪ L1‬ו‪: L2 -‬‬
‫‪L1 = 1, 5, 6, 3, 4, 8, 9, 5, 4, 3, 6, 7‬‬
‫‪L2 = 5, 4, 4, 8, 9, 5, 6, 3, 6‬‬
‫המקטע‪-‬המשותף‪-‬המקסימלי הוא הרשימה ‪:L3‬‬
‫‪L3 = 4, 8, 9, 5‬‬
‫נתונה הפונקציה‪:‬‬
‫;‪function list_compare (L1, L2 : list_type; pos1, pos2 : pos_type; n : integer) : boolean‬‬
‫הפונקציה מקבלת שתי רשימות ‪ L1‬ו‪ L2 -‬ושני מצביעים ‪ pos1‬ו‪ pos2 -‬המצביעים על מקומות ב‪ L1 -‬ו‪L2 -‬‬
‫בהתאמה‪ .‬הפונקציה מחזירה ‪ TRUE‬אם ‪ n‬האיברים החל מ‪ pos1 -‬ברשימה ‪ L1‬זהים ל‪ n -‬האיברים החל מ‪-‬‬
‫‪pos2‬ברשימה ‪ ,L2‬ו‪ FALSE -‬אחרת‪.‬‬
‫אם מספר האיברים אחרי ‪ pos1‬או ‪ pos2‬קטן מ‪ ,n -‬תחזיר הפונקציה ‪.FALSE‬‬
‫א‪.‬‬
‫כתוב פרוצדורה בסביבת העבודה‪ ,‬שתקבל שתי רשימות ‪ L1‬ו‪L2 -‬‬
‫ותחזיר את המקטע‪-‬המשותף‪-‬המקסימלי לשתיהן‪.‬‬
‫ב‪.‬‬
‫מהי סיבוכיות זמן הריצה של הפעולה שמימשת בסעיף הקודם? נמק‪.‬‬
‫אם נעזרת בפונקציה ‪ ,list_compare‬הנח כי סיבוכיות זמן הריצה שלה‪,‬‬
‫כפונקציה של ‪ n‬המועבר כפרמטר‪ ,‬היא‪.O(n) :‬‬
‫הצעה ‪ 1‬של רחל בן‪-‬עמי ומושית ולץ‬
‫הצעה לניסוח חדש שיתאים לתכנית "מבני נתונים"‪:‬‬
‫מקטע _משותף_ מקסימלי לשתי רשימות נתונות הוא תת הרשימה הרצופה המקסימלית‪ ,‬המשותפת לשתיהן‪.‬‬
‫לדוגמה‪ ,‬עבור הרשימות ‪ L1‬ו‪ , L2 -‬כאשר ‪ L2 ,L1‬מטיפוס >‪.Node<int‬‬
‫‪L1 1 ,5, 6, 3, 4, 8, 9, 5, 4, 3, 6, 7‬‬
‫‪L2 5, 4, 4, 8, 9, 5, 6, 3, 6‬‬
‫המקטע _המשותף_ המקסימלי הוא הרשימה ‪:‬‬
‫‪L3 4, 8, 9, 5‬‬
‫נתונה הפעולה‪:‬‬
‫‪public static bool ListCompare(Node<int> L1, Node<int> L2, Node<int> pos1,‬‬
‫)‪Node<int> pos2, int n‬‬
‫הפעולה מקבלת שתי רשימות ‪ L2 ,L1‬ושתי הפניות ‪ pos1, pos2‬למקומות ב‪ L2 ,L1 -‬בהתאמה‪.‬‬
‫הפעולה מחזירה ‪ TRUE‬אם ‪ n‬האברים החל מ‪ pos1 -‬ברשימה ‪ L1‬זהים ל‪ n -‬האיברים החל מ‪pos2 -‬‬
‫ברשימה ‪ ,L2‬ו‪ FALSE -‬אחרת‪.‬‬
‫‪- 163 -‬‬
‫אם מספר האיברים אחרי ‪ pos1‬או ‪ pos2‬קטן מ‪ , n -‬תחזיר הפעולה ‪.FALSE‬‬
‫א‪ .‬כתוב פעולה שתקבל שתי רשימות ‪ L1‬ו‪ L2-‬מטיפוס >‪Node<int‬‬
‫ותחזיר את המקטע _המשותף_ המקסימלי לשתיהן‪.‬‬
‫ב‪ .‬מהי סיבוכיות זמן הריצה של הפעולה שמימשת בסעיף הקודם? נמק‪.‬‬
‫אם נעזרת בפעולה ‪ ,ListCompare‬הנח כי סיבוכיות זמן הריצה שלה‪ ,‬כפונקציה של ‪ n‬המועבר‬
‫כפרמטר‪ ,‬היא )‪. O(n‬‬
‫הצעה ‪ 2‬של דפנה מינסטר‬
‫הצעה לניסוח חדש שיתאים לתכנית "מבני נתונים"‪:‬‬
‫מקטע‪-‬משותף‪-‬מקסימלי לשני אוספים נתונים הוא תת‪-‬אוסף הרצוף המקסימלי המשותף לשניהם‪.‬‬
‫לדוגמה‪ :‬עבור האוספים ‪ collect1‬ו– ‪collect2‬‬
‫|| ‪collect1  1  5  6  3  4  8  9  5  4  3  6  7 ‬‬
‫|| ‪collect2  5  4  4  8  9  5  6  3  6 ‬‬
‫המקטע‪-‬המשותף‪-‬המקסימלי הוא האוסף ‪:collect3‬‬
‫|| ‪collect3  4  8  9  5 ‬‬
‫נתונה השיטה‪:‬‬
‫‪public static boolean collectCompare ( Node < Integer > collect1 ,‬‬
‫‪Node < Integer > collect2 ,‬‬
‫‪Node < Integer > p1 ,‬‬
‫) ‪Node < Integer > p2 , int N‬‬
‫השיטה מקבלת שני אוספים מאותחלים ‪ collect1‬ו‪ collect2 -‬ושני מצביעים (מיקומים) ‪ p1‬ו‪ p2 -‬המצביעים על‬
‫מקומות ב‪ collect1 -‬ו‪ collect2 -‬בהתאמה‪ .‬השיטה מחזירה 'אמת' (‪ )true‬אם ‪N‬האיברים החל מ‪ p1 -‬באוסף‬
‫‪ collect1‬זהים ל‪ N -‬האיברים החל מ‪ p2 -‬באוסף ‪ , collect2‬אחרת מחזירה 'שקר' (‪.)false‬‬
‫אם מספר האיברים אחרי ‪ p1‬או אחרי ‪ p2‬קטן מ‪ N -‬תחזיר השיטה 'שקר' (‪.)false‬‬
‫א‪.‬‬
‫כתב‪/‬י שיטה בשפת ‪ Java‬שתקבל שני אוספים ‪ collect1‬ו‪ collect2 -‬ותחזיר את המקטע‪-‬המשותף‪-‬‬
‫המקסימלי לשניהם‪ .‬השתמש‪/‬י בשיטה ‪( collectCompare‬הערה‪ :‬אין צורך לממש את השיטה)‪.‬‬
‫ב‪.‬‬
‫מהו סדר הגודל של השיטה שכתבת הסעיף א' ? נמק‪/‬י !‬
‫אם נעזרת בשיטה ‪ collectCompare‬הנח‪/‬י כי סדר הגודל שלה‪ ,‬כפונקציה של ‪ n‬המועבר כפרמטר‪,‬‬
‫הוא‪.O(n) :‬‬
‫‪- 164 -‬‬
‫הצעה ‪ 3‬של ולרי פקר (כולל התייחסות להצעה של דפנה מינסטר)‬
‫לדעתי‪ ,‬הניסוח מחדש לשאלה (שהציעה דפנה מינסטר) לא מתאים לתכנית הלימודים החדשה‪.‬‬
‫‪ .1‬החוליה היא אבן יסוד למבנה נתונים דינמי ולא אוסף‪ .‬אוסף הוא מחלקה סגורה התומכת בפעולות הכנסה‪ ,‬הוצאה‪,‬‬
‫סריקה‪ ,‬חיפוש וכדומה‪.‬‬
‫‪ .2‬בתכנית הישנה המבוססת על שפת ‪ Pascal‬היו שני מימושים של טיפוס הנתונים רשימה‪ :‬באמצעות מערך ובעזרת‬
‫שרשרת חוליות‪ .‬בשני ייצוגים של הרשימה בממשק של יחידות הספרייה לא היו הבדלים בהגדרת הפעולות‪ ,‬והן היו‬
‫זהות לחלוטין‪ .‬משתמש חיצוני‪ ,‬שכתב קוד הנעזר ביחידת הספרייה אחת‪ ,‬היה יכול להחליף את יחידת הספרייה מבלי‬
‫לשנות דבר בקוד‪.‬‬
‫הפעולות כמו סוף‪-‬רשימה(‪ ,)L‬עוקב‪-‬ברשימה(‪ ,)L, p‬עוגן‪-‬רשימה(‪ )L‬היו צריכים רשימה כפרמטר‪ .‬לכן‬
‫בניסוח השאלה בשנת ‪ 1998‬השתמשו בשני הפרמטרים ‪ L1‬ו‪.L2-‬‬
‫בתוכנית החדשה הייצוג של שרשרת חוליות "פתוח" וידוע מראש ואין צורך בפרמטרים כאלו‪.‬‬
‫‪ .1‬החוליה היא אבן יסוד למבנה נתונים דינמי ולא אוסף‪.‬‬
‫אוסף הוא מחלקה סגורה התומכת בפעולות הכנסה‪ ,‬הוצאה‪ ,‬סריקה‪ ,‬חיפוש וכדומה‪.‬‬
‫‪ .2‬בתכנית הישנה המבוססת על שפת ‪ Pascal‬היו שני מימושים של טיפוס הנתונים רשימה‪:‬‬
‫באמצעות מערך ובעזרת שרשרת חוליות‪.‬‬
‫בשני ייצוגים של הרשימה בממשק של יחידות הספרייה לא היו הבדלים בהגדרת הפעולות‪ ,‬והן היו זהות‬
‫לחלוטין‪ .‬משתמש חיצוני‪ ,‬שכתב קוד הנעזר ביחידת הספרייה אחת‪ ,‬היה יכול להחליף את יחידת הספרייה‬
‫מבלי לשנות דבר בקוד‪.‬‬
‫הפעולות כמו סוף‪-‬רשימה(‪ ,)L‬עוקב‪-‬ברשימה(‪ ,)L, p‬עוגן‪-‬רשימה(‪ )L‬היו צריכים רשימה כפרמטר‪.‬‬
‫לכן בניסוח השאלה בשנת ‪ 1998‬השתמשו בשני הפרמטרים ‪ L1‬ו‪.L2-‬‬
‫בתוכנית החדשה הייצוג של שרשרת חוליות "פתוח" וידוע מראש ואין צורך בפרמטרים כאלו‪.‬‬
‫לכן ניסוח השאלה לדעתי צריך להיות‪:‬‬
‫מקטע‪-‬משותף‪-‬מקסימלי לשני שרשרות חוליות נתונות הוא תת‪-‬שרשרת החוליות הרצופה המקסימלית‪ ,‬המשותפת‬
‫לשתיהן‪ .‬לדוגמה‪ :‬עבור שרשרות החוליות ‪ chain1‬ו– ‪chain2‬‬
‫|| ‪chain1  1  5  6  3  4  8  9  5  4  3  6  7 ‬‬
‫|| ‪chain1  5  5  5  8  9  5  6  3  6 ‬‬
‫המקטע‪-‬המשותף‪-‬המקסימלי הוא שרשרת החוליות ‪:chain3‬‬
‫|| ‪chain3  4  8  9  5 ‬‬
‫‪- 165 -‬‬
‫מציאת מקטע‪-‬משותף‪-‬מקסימלי ‪ ,‬המשותפת לשתי שרשרות החוליות‪.‬‬
‫כדי לאתר את תת‪-‬שרשרת החוליות הרצופה המקסימלית החֵל מחוליות מסוימות בשתי שרשרת החוליות‪ ,‬לא נצטרך‬
‫להעביר את השרשרות "המלאות" כפרמטרים לפעולה‪ ,‬כיוון שממילא אין צורך לחפש בשרשרות "המלאות"‪ .‬די יהיה‬
‫בהעברת הפניות לחוליות שמהן אנו רוצים להתחיל את החיפוש‪.‬‬
‫לכן ניסוח השאלה לדעתי צריך להיות‪:‬‬
‫לפניכם חתימת הפעולה החיצונית‪:‬‬
‫‪public static boolean collectCompare (Node < Integer > chain1 ,‬‬
‫)‪Node < Integer > chain2 , int n‬‬
‫הפעולה מקבלת שתי הפניות על שרשרות החוליות ‪ chain1‬ו–‪ chain2‬ומספר ‪ .n‬הפעולה מחזירה 'אמת' אם ‪n‬‬
‫האיברים החל מהחוליה ‪ chain1‬זהים ל‪ n-‬האיברים החל מהחוליה ‪ , chain2‬אחרת מחזירה 'שקר'‪ .‬אם מספר‬
‫האיברים החל מהחוליה ‪ chain1‬או החל מהחוליה ‪ chain2‬קטן מ‪ n-‬תחזיר הפעולה 'שקר'‪.‬‬
‫א‪.‬‬
‫ב‪.‬‬
‫על‬
‫שרשרות‬
‫החוליות‬
‫כתבו פעולה בשפת ‪ Java‬שתקבל שתי הפניות‬
‫ו–‪ chain2‬ותחזיר את המקטע‪-‬המשותף‪-‬המקסימלי לשניהם‪.‬‬
‫השתמשו בפעולה ‪ collectCompare‬בלי לממש אותה‬
‫מהו סדר הגודל של הפעולה שכתבת הסעיף א' ? נמק!‬
‫אם נעזרת בפעולה ‪ collectCompare‬הנחו כי סדר הגודל שלה‪ ,‬כפונקציה של ‪ n‬המועבר כפרמטר‪ ,‬הוא‬
‫)‪.O(n‬‬
‫‪chain1‬‬
‫פתרון אפשרי בשפת ‪:C#‬‬
‫)‪public static bool Compare2Nodes(Node<int> chain1, Node<int> chain2, int n‬‬
‫{‬
‫)‪while (chain1 != null && chain2 != null & n > 0‬‬
‫{‬
‫))(‪if (chain1.GetValue() != chain2.GetValue‬‬
‫;‪return false‬‬
‫;)(‪chain1 = chain1.GetNext‬‬
‫;)(‪chain2 = chain2.GetNext‬‬
‫;‪n--‬‬
‫}‬
‫;‪return n == 0‬‬
‫}‬
‫‪- 166 -‬‬
public static Node<int> MaximumSharedSegment(Node<int> chain1, Node<int> chain2)
{
Node<int> p1 = chain1;
Node<int> p2, pMax = null;
int maxSement = 0, n;
while (p1 != null)
{
p2 = chain2;
while (p2 != null)
{
n = maxSement;
while (Compare2Nodes(p1, p2, n + 1))
n++;
if (n > maxSement)
{
maxSement = n;
pMax = p1;
}
p2 = p2.GetNext();
}
p1 = p1.GetNext();
}
if (pMax != null)
{
p2 = new Node<int>(pMax.GetValue());
pMax = pMax.GetNext();
p1 = p2;
for (int i = 2; i <= maxSement; i++)
{
p1.SetNext(new Node<int>(pMax.GetValue()));
p1 = p1.GetNext();
- 167 -
‫;)(‪pMax = pMax.GetNext‬‬
‫}‬
‫}‬
‫‪else‬‬
‫;‪p2 = null‬‬
‫;‪return p2‬‬
‫}‬
‫שאלה ‪ ,1‬בגרות תשס"א ‪2001‬‬
‫שרה פונק‬
‫הניסוח המקורי‬
‫לפניך האלגוריתם סוד (הנעזר באלגוריתמים תעלומה והחלף)‬
‫‪- 168 -‬‬
?‫ שלפניך‬i – ii ‫ אם יקבל את הרשימות‬,)L, 9( ‫ מה יחזיר האלגוריתם סוד‬.‫א‬
.‫פרט את המעקב אחר ביצוע האלגוריתם עבור כל אחת מהרשימות‬
8 ,25 ,9 ,3 ,41 ,10
.i
7 ,2 ,9 ,5 ,24 ,7 ,18 ,3 ,14 ,4
.ii
)L, x( ‫ הסבר באופן כללי מה מבצע האלגוריתם סוד‬.‫ב‬
.‫) ? נמק‬L, x( ‫ מהי סיבוכיות זמן הריצה של האלגוריתם סוד‬.‫ג‬
:"‫הצעה לניסוח חדש שיתאים לתכנית "מבני נתונים‬
java -‫המרת שאלה אלגוריתמית לשאלת מעקב הכתובה ב‬
import java.util.Scanner;
public class TestBagrut2001_q1
{
/**
* @param args
*/
public static Node<Integer> inputInt(int num)
{
Scanner sc = new Scanner (System.in);
System.out.println("Enter "+num+" integers");
Node<Integer> chain = new Node<Integer>(sc.nextInt());
Node<Integer>pos = chain ;
for(num-- ; num>0 ;num--, pos = pos.getNext())
pos.setNext(new Node<Integer>(sc.nextInt()));
return chain ;
}
- 169 -
public static <T> void printList(Node<T> head)
{
while (head!=null)
{
System.out.print(head.getValue()+" --> ");
head = head.getNext();
}
System.out.println("null");
}
public static void main(String[] args)
{
Node<Integer> list1 = inputInt(6);
printList(list1);
System.out.println(Bagrut2001_q1.mys1(list1, 0));
}
}
public class Bagrut2001_q1
{
public static int mys1(Node<Integer> head , int x )
{
Node<Integer> p1 = head ;
Node<Integer> p2 = head ;
while (p2.getNext()!=null)
p2 = p2.getNext();
return mys2(head , p1,p2, x);
}
public static int mys2(Node <Integer> head , Node<Integer> p1,
Node<Integer> p2, int x)
- 170 -
{
if(p1 == p2)
if(p1.getValue()> x)
return 1 ;
else
return 0 ;
else
if(p1.getValue()>x)
return mys2(head, p1.getNext(),p2 , x)+1 ;
else
if(p2.getValue()<=x)
{
Node<Integer> prev = p1 ;
while(prev.getNext()!=p2)
prev = prev.getNext();
return mys2(head , p1 ,prev , x);
}
else
{
int temp = p1.getValue();
p1.setValue(p2.getValue());
p2.setValue(temp);
TestBagrut2001_q1.printList(head);
return mys2(head , p1,p2,x);
}
}
}
public class Node <T>
{
private T value ;
private Node<T> next ;
public Node (T x )
- 171 -
{
this.value = x ;
this.next = null;
}
public Node (T x , Node<T> next )
{
this.value = x ;
this.next = next;
}
public T getValue(){return this.value ;}
public Node<T> getNext () {return this.next ;}
public void setValue(T x){ this.value = x ;}
public void setNext (Node<T> next){ this.next = next ;}
public boolean hasNext(){return this.next == null;}
public String toString(){return this.value.toString();}
}
- 172 -
‫שאלה ‪ ,1‬בגרות קיץ תשס"ג ‪2003‬‬
‫חיה עידן‬
‫הניסוח המקורי‬
‫כתוב תת‪-‬תכנית (פרוצדורה או פונקציה) בסביבת העבודה‪ ,‬שתקבל רשימה ‪ L‬לא ריקה של מספרים שלמים ותחזיר רשימה חדשה‬
‫באופן הזה‪:‬‬
‫עבור כל תת‪-‬רשימה של מספרים עולים ב‪ ,L -‬שבה כל מספר גדול מקודמו‪ ,‬יופיע ברשימה החדשה מספר אחד שהוא סכום כל‬
‫המספרים העולים‪ .‬כל תת‪-‬רשימה של מספרים עולים מסתיימת כאשר אחריה יש מספר שהוא קטן מן המספר האחרון שבה‪ ,‬או‬
‫שווה לו‪.‬‬
‫תת‪-‬רשימה יכולה לכלול גם מספר אחד בלבד‪ .‬סדר האיברים ברשימה החדשה יהיה על פי סדר התת‪-‬רשימות ברשימה ‪.L‬‬
‫לדוגמה‪:‬‬
‫עבור הרשימה ‪( L‬משמאל לימין)‪7 , 2 , 4 , 8 , 20 , 18 , 19 , 20 , 20 , 5 , -3 , 0 , 9 :‬‬
‫הרשימה החדשה שתוחזר‪7 , 34 , 57 , 20 , 5 , 6 :‬‬
‫הערה‪ :‬אין צורך לממש בסביבת העבודה את הפעולות של ממשק רשימה‪.‬‬
‫הצעה לניסוח חדש שיתאים לתכנית "מבני נתונים"‪:‬‬
‫כתוב תת‪-‬תכנית בסביבת העבודה‪ ,‬שתקבל שרשרת חוליות לא ריקה ‪ L‬של מספרים שלמים‪,‬‬
‫הפעולה תחזיר שרשרת חוליות חדשה באופן הבא‪:‬‬
‫עבור כל סדרה של חוליות של מספרים עולים ב‪ ,L -‬תופיע חוליה אחת המכילה את סכום כל המספרים העולים‪.‬‬
‫כל סדרת חוליות של מספרים עולים מסתיימת כאשר אחריה יש מספר שהוא קטן או שווה למספר האחרון שבה‪.‬‬
‫סדר החוליות בשרשרת החוליות החדשה יהיה על פי סדר תת הסדרות עולות בשרשרת החוליות המקורית‪.‬‬
‫פתרון‬
‫)‪public static Node<int> MakeSumList(Node<int> lst‬‬
‫{‬
‫;‪Node<int> sumLst, p, ps‬‬
‫;‪p = lst‬‬
‫;‪ps = sumLst= null‬‬
‫;‪int sum = 0‬‬
‫)‪while (p != null‬‬
‫{‬
‫;)(‪sum += p.GetInfo‬‬
‫))(‪if (p.GetNext()== null || p.GetInfo()>= p.GetNext().GetInfo‬‬
‫{‬
‫)‪if (ps==null‬‬
‫;)‪sumLst=ps=new Node<int>(sum‬‬
‫‪else‬‬
‫{‬
‫;))‪ps.SetNext(new Node<int>(sum‬‬
‫;)(‪ps=ps.GetNext‬‬
‫}‬
‫;‪sum = 0‬‬
‫}‬
‫‪- 173 -‬‬
‫;)(‪p=p.GetNext‬‬
‫}‬
‫;‪return sumLst‬‬
‫}‬
‫שאלה ‪ ,2‬בגרות קיץ תשס"ה ‪2005‬‬
‫הניסוח המקורי‬
‫רשימה "חשבונית" ‪ L‬היא רשימה ששדה התוכן שלה מייצג ביטוי חשבוני‪.‬‬
‫הביטוי החשבוני מורכב משלושה חלקים‪:‬‬
‫‪ ‬מספר שלם גדול מאפס‬
‫‪ ‬תו אחד מבין ארבעת התווים‪:‬‬
‫‪ +‬המייצג חיבור‬
‫ המייצג חיסור‬‫* המייצג כפל‬
‫‪ /‬המייצג חילוק‬
‫‪ ‬מספר שלם גדול מאפס‬
‫דוגמה לרשימה "חשבונית" ‪: L‬‬
‫א‪ .‬הגדר בסביבת העבודה את טיפוס שדה התוכן של איבר ברשימה "חשבונית" ‪.L‬‬
‫ב‪ .‬ממש בסביבת העבודה תת‪-‬תכנית ‪ ,calculate‬שתקבל רשימה "חשבונית" ‪ L‬ומקום ‪ p‬ברשימה‪ p .‬הוא מקום ב‪L -‬‬
‫שאינו סוף‪-‬רשימה ואינו עוגן‪-‬רשימה‪ .‬התת‪-‬תכנית תחזיר את התוצאה המתקבלת מהביטוי החשבוני הנמצא באיבר‬
‫שבמקום ‪.p‬‬
‫ג‪ .‬ממש בסביבת העבודה תת‪-‬תכנית ‪ ,sumExpressions‬שתקבל רשימה "חשבונית" ‪ ,L‬ותחזיר את הסכום הכולל של‬
‫תוצאות הביטויים החשבוניים הנמצאים ברשימה‪ .‬בעבור רשימה ריקה יוחזר ‪.0‬‬
‫עליך להשתמש בתת‪-‬תכנית ‪.calculate‬‬
‫בעבור הרשימה "החשבונית" ‪ L‬בדוגמה הנתונה‪ ,‬התת‪-‬תכנית ‪ sumExpressions‬תחזיר ‪.14‬‬
‫הצעה ‪ 1‬של יבגני קנל‬
‫הצעה לניסוח חדש שיתאים לתכנית "מבני נתונים"‪:‬‬
‫שרשרת "חשבונית" היא שרשרת המורכבת מ"ביטוים חשבוניים"‪.‬‬
‫הביטוי החשבוני כולל שני מספרים שלמים ותו המציין אחת מ‪ 5-‬פעולות חשבון‪.%,/,*,-,+ :‬‬
‫לפני תיאור חלקי של המחלקה ‪ ,MExp‬המייצגת ביטוי החשבוני‪:‬‬
‫‪MExp‬‬
‫המספר הראשון בביטוי‬
‫הסימן המגדיר פעולה חשבונית‪.‬‬
‫;‪private int num1‬‬
‫;‪private char sign‬‬
‫‪- 174 -‬‬
‫הנחה‪ :‬הסימן הוא אחד מ‪ 5-‬סימנים ‪.%,/,*,-,+ :‬‬
‫המספר השני בביטוי‬
‫הפעולה הבונה‬
‫הפעולה בודקת האם ניתן לבצע חישוב של ביטוי חשבוני‬
‫הפעולה מחזירה את התוצאה המתקבלת מהביטוי החשבוני‪.‬‬
‫אם לא ניתן לבצע חישוב‪ ,‬הפעולה תחזיר ‪.0‬‬
‫;‪private int num2‬‬
‫)‪public MExp(int num1,char sign, int num2‬‬
‫)(‪public boolean isValid‬‬
‫)(‪public int calculate‬‬
‫א‪ .‬ממש את פעולה )(‪isValid‬‬
‫ב‪ .‬ממש את פעולה )(‪calculate‬‬
‫ג‪ .‬ממש את פעולה החיצונית )‪ sumExpessions(Node<MExp> ch‬המקבלת שרשרת "חשבונית" ‪ .‬הפעולה‬
‫תחזיר את הסכום הכולל של תוצאות הביטויים החשבוניים הנמצאים בשרשרת‪ .‬בעבור השרשת הבאה הפעולה‬
‫תחזיר ‪14‬‬
‫‪ch‬‬
‫הצעה ‪ 2‬של דורית ליקרמן‬
‫"רשימה חשבונית" היא רשימה של ‪( Expressions‬ביטוי חשבוניים)‪.‬‬
‫‪( Expression‬ביטוי חשבוני) מיוצג על ידי ‪:‬‬
‫מספר שלם גדול מאפס‬
‫תו מבין ארבעת התווים‪:‬‬
‫‪ +‬מייצג חיבור‬
‫ מייצג חיסור‬‫* מייצג כפל‬
‫‪ /‬מייצג חילוק‪.‬‬
‫מספר שלם גדול מאפס‬
‫דוגמא ל"רשימה חשבונית"‪:‬‬
‫‪10‬‬
‫‪8‬‬
‫‪3‬‬
‫‪-‬‬
‫‪/‬‬
‫‪+‬‬
‫‪7‬‬
‫‪2‬‬
‫‪4‬‬
‫‪- 175 -‬‬
‫א‪.‬‬
‫כתוב ב‪ c# -‬או ב‪ Java -‬את כותרת המחלקה ‪ Expression‬ואת תכונותיה‪.‬‬
‫ב‪.‬‬
‫נתונה כותרת הפעולה ‪calculate:‬‬
‫)‪public static int calculate (Node<Expression> p‬‬
‫הפעולה מחזירה את ערך הביטוי החשבוני הנמצא ב‪.p -‬‬
‫ממש את הפעולה ‪ c# -‬או ב‪.Java -‬‬
‫ג‪.‬‬
‫ממש ב‪ c# -‬או ב‪ Java -‬פעולה ‪ ,sumExpressions‬המקבלת "רשימה חשבונית" ומחזירה את הסכום הכולל‬
‫של תוצאות הביטויים החשבוניים הנמצאים ברשימה‬
‫עליך להשתמש בפעולה ‪calculate‬‬
‫לדוגמא‪ ,‬בעבוד הרשימה למעלה‪ sumExpressions ,‬תחזיר ‪.14‬‬
‫עבור סעיפים ב' ו‪ -‬ג' הנח שכל פעולות ה‪ get/set -‬במחלקה ‪ Expression‬קיימות‪.‬‬
‫שאלה ‪ ,4‬בגרות קיץ תשס"ו ‪2006‬‬
‫הניסוח המקורי‪:‬‬
‫כתוב תת‪-‬תכנית בפסקל או ב‪ ,C -‬שתקבל שתי רשימות ‪ L2 , L1‬של מספרים שלמים וגדולים מ‪ 0 -‬ותחזיר רשימה‬
‫חדשה ‪.L3‬‬
‫התת‪-‬תכנית תסרוק את הרשימה ‪ L1‬פעם אחת‪ ,‬מתחילתה עד סופה‪.‬‬
‫בכל שלב התת‪-‬תכנית תבדוק איבר אחד מהרשימה ‪ .L1‬נסמן את ערך האיבר ב‪.k -‬‬
‫התת‪-‬תכנית תבצע את אחת הפעולות שלהלן‪ ,‬בהתאם ל‪ k -‬ולרשימה ‪ L2‬כפי שהיא בשלב זה‪:‬‬
‫‪ ‬אם ‪ k‬הוא מספר זוגי‪ ,‬התת‪-‬תכנית תמחק את האיבר שמיקומו ‪ k‬מתחילת הרשימה ‪.L2‬‬
‫‪ ‬אם ‪ k‬הוא מספר אי‪-‬זוגי‪ ,‬התת‪-‬תכנית תוסיף לרשימה ‪ L3‬איבר שהערך שלו הוא הערך של האיבר שמיקומו ‪k‬‬
‫מתחילת הרשימה ‪.L2‬‬
‫‪ ‬אם ברשימה ‪ L2‬אין איבר שמיקומו ‪ ,k‬התת‪-‬תכנית לא תבצע דבר‪.‬‬
‫הערות‪:‬‬
‫אין חשיבות לסדר הכנסת האיברים לרשימה ‪.L3‬‬
‫התת‪-‬תכנית לא תחזיר את הרשימה ‪.L2‬‬
‫לדוגמה‪:‬‬
‫בעבור הרשימות ‪( L2 , L1‬משמאל לימין)‪:‬‬
‫‪4, 3, 2,6‬‬
‫‪10 , 11 , 19 , 1 , 7 , 100‬‬
‫‪L1 :‬‬
‫‪L2 :‬‬
‫מצב הרשימות ‪ L3 , L2‬בתום כל שלב של ביצוע התת‪-‬תכנית יהיה כזה‪:‬‬
‫אחרי שלב ‪I‬‬
‫‪10 , 11 , 19 , 7 , 100‬‬
‫‪L2 :‬‬
‫‪L3 :‬‬
‫אחרי שלב ‪II‬‬
‫‪10 , 11 , 19 , 7 , 100‬‬
‫‪19‬‬
‫‪- 176 -‬‬
‫‪L2 :‬‬
‫‪L3 :‬‬
‫אחרי שלב ‪III‬‬
‫‪10 , 19 , 7 , 100‬‬
‫‪19‬‬
‫‪L2 :‬‬
‫‪L3 :‬‬
‫‪10 , 19 , 7 , 100‬‬
‫‪19‬‬
‫‪L2 :‬‬
‫‪L3 :‬‬
‫אחרי שלב ‪IV‬‬
‫הצעה ‪ 1‬ענת שלוס סגל‬
‫הצעה לניסוח חדש שיתאים לתכנית "מבני נתונים"‪:‬‬
‫מצורפות בהמשך שתי הצעות פתרון‪ :‬בתכנית הנוכחית ובתכנית החדשה‪.‬‬
‫ניתן לראות כי פתרון השאלה כפי שהיא בתכנית החדשה מעלה הופך להיות יותר מורכב‪.‬‬
‫מכיוון שיש צורך למצוא את האיבר ה‪ k-‬ברשימה ‪ L2‬ובהתאם לערכו אולי גם למחוק אותו‬
‫יש לבצע סריקה שעוצרת באיבר ה ‪.k-1‬‬
‫בעיה נוספת שהייתה יכולה להיווצר היא מחיקת האיבר הראשון בשרשרת חוליות שהועברה כפרמטר לפעולה‪ .‬אך‬
‫בעיה זו לא קיימת מכיוון שמחיקה מתבצעת רק עבור איברים שמקומם ברשימה זוגי‪.‬‬
‫שתי הצעות ל"שיפוץ השאלה"‬
‫‪ )1‬עבור ‪ k‬זוגי הכנס ל ‪ L3‬איבר שהערך שלו הוא ריבוע הערך של האיבר שמיקומו ‪ k‬מתחילת הרשימה ‪.L2‬‬
‫(עבור ‪ k‬אי‪-‬זוגי אין שינוי)‬
‫‪ )2‬רק לבצע מחיקה מרשימה ‪ L2‬עבור ‪ k‬זוגי‪ ,‬ולא לבצע דבר עבור ‪ k‬אי‪-‬זוגי‪.‬‬
‫כלומר אין בנייה והחזרה של רשימה שלישית‪.‬‬
‫הצעת פתרון לפי תכנית ישנה‪/‬נוכחית‬
‫)‪public static List<Integer> getList ( List<Integer> lst1 , List<Integer> lst2‬‬
‫{‬
‫;)(>‪List<Integer> lst3 = new List<Integer‬‬
‫;)(‪Node<Integer> pos1= lst1.getFirst‬‬
‫)‪while (pos1 != null‬‬
‫{‬
‫;)(‪int k = pos1.getInfo‬‬
‫;‪int i = 1‬‬
‫;)(‪Node<Integer> pos2 = lst2.getFirst‬‬
‫)‪while (pos2 != null && i < k‬‬
‫{‬
‫;)(‪pos2 = pos2.getNext‬‬
‫;‪i++‬‬
‫}‬
‫)‪if (i == k && pos2 != null‬‬
‫{‬
‫)‪if (k%2 == 0‬‬
‫;)‪lst2.remove(pos2‬‬
‫‪- 177 -‬‬
else
lst3.insert (null, pos2.getInfo());
}
pos1 = pos1.getNext();
}
return lst3;
}
‫הצעת פתרון לפי התכנית החדשה‬
public static Node<Integer> getList ( Node<Integer> lst1 , Node<Integer> lst2)
{
Node<Integer> lst3 = null;
Node<Integer> pos1= lst1;
while (pos1 != null)
{
int k = pos1. getValue ();
int i = 1;
Node<Integer> pos2 = lst2;
while (pos2.getNext() != null && i < k-1)
{
pos2 = pos2.getNext();
i++;
}
if (i == k-1 && pos2.getNext() != null)
{
if (k%2 == 0)
{
Node<Integer> temp = pos2.getNext();
pos2.setNext(temp.getNext());
temp.setNext(null);
}
else
lst3=new Node<Integer> (pos2.getNext().getValue (), lst3);
}
pos1 = pos1.getNext();
}
return lst3;
}
- 178 -
‫הצעה ‪ 2‬אוי גרינולד‬
‫הצעה לניסוח חדש שיתאים לתכנית "מבני נתונים"‪:‬‬
‫כתוב פעולה אשר מקבלת ‪ 2‬רשימות של מספרים שלמים וחיוביים‪. list1, list2 ,‬‬
‫הפעולה עוברת על כל איברי רשימה ‪ list1‬פעם אחת מתחילתה ועד סופה‪.‬‬
‫עבור כל איבר מרשימה ‪ list1‬אשר ערכו ‪ , k‬הפעולה תבצע את הצעד הבא‪:‬‬
‫‪-‬‬
‫אם ‪ k‬זוגי‪ ,‬הפעולה תמחק את האיבר שמיקומו ‪ k‬צעדים מתחילת רשימה ‪List2‬‬
‫‪-‬‬
‫אם ‪ k‬אי‪-‬זוגי‪ ,‬הפעולה תוסיף לרשימה ‪ list3‬את האיבר שנמצא במיקום ‪ k‬צעדים מתחילת רשימה ‪list2‬‬
‫‪-‬‬
‫אם אין מיקום ‪ k‬ברשימה ‪ , list2‬הפעולה לא תבצע כלום על איבר זה‪.‬‬
‫‪-‬‬
‫אין חשיבות לסדר הערכים ברשימה ‪. list3‬‬
‫הפעולה תחזיר את רשימה ‪. list3‬‬
‫במידה אף איבר לא התווסף לרשימה תוחזר רשימה‬
‫מצב התחלתי‬
‫אחרי שלב ‪1‬‬
‫עם חוליה אחת בלבד שערכה ‪.0‬‬
‫לדוגמה עבור הרשימות‪:‬‬
‫אחרי שלב ‪2‬‬
‫אחרי שלב ‪3‬‬
‫אחרי שלב ‪4‬‬
‫]‪list1: [ 2,4,1,5‬‬
‫] ‪list2: [ 10,20,30,40,50,60‬‬
‫‪k=2‬‬
‫] ‪list2: [ 10,30,40,50,60‬‬
‫] ‪list3: [ 0‬‬
‫‪k=4‬‬
‫] ‪list2: [ 10,30,40,60‬‬
‫] ‪list3: [ 0‬‬
‫‪k=1‬‬
‫] ‪list2: [ 10,30,40,60‬‬
‫] ‪list3: [ 10‬‬
‫‪k=5‬‬
‫] ‪list2: [ 10,30,40,60‬‬
‫] ‪list3: [ 10‬‬
‫פתרון‪:‬‬
‫;‪import unit4.collectionsLib.Node‬‬
‫;‪import java.util.Scanner‬‬
‫**‪/‬‬
‫‪* @version 14/1/15‬‬
‫‪* @author evi‬‬
‫‪*/‬‬
‫‪public class Bg4_06‬‬
‫{‬
‫)(‪public static Node<Integer> create‬‬
‫פעולת ליצירת רשימה של שלמים ‪{//‬‬
‫;)‪Scanner in = new Scanner(System.in‬‬
‫;‪int x‬‬
‫;‪Node<Integer> first, node, pos‬‬
‫;)"‪System.out.println("Enter integer value != 99‬‬
‫;)(‪x = in.nextInt‬‬
‫‪- 179 -‬‬
first = new Node<Integer>(x);
pos = first;
System.out.println("Enter integer value, 99 to stop");
x = in.nextInt();
while (x!=99)
{
node = new Node<Integer>(x);
pos.setNext(node);
pos = node;
System.out.println("Enter integer value, 99 to stop");
x = in.nextInt();
}
return first;
}
public static void print(Node<Integer> list)
{//‫פעולה להדפסת רשימה של שלמים‬
while (list!=null)
{
System.out.print(list.getValue()+" --> ");
list = list.getNext();
}
System.out.println("null");
}
/**
* @param list: Node<Integer>
* @param k: int
* @return reference to Node<Integer> position k in list
* if k>number of nodes in list, return null
*/
public static Node<Integer> goTo(Node<Integer> list, int k)
{
while (list!=null && k>1)
{
list = list.getNext();
k--;
}
return list;
}
/**
* deletes node in k steps from beginning of list,
* in conditions than there is k nodes
* @param list: Node<Integer>
* @param k ; int
*/
public static void deleteK(Node<Integer> list, int k)
- 180 -
{//k ‫מחיקת איבר במקום‬
Node<Integer> prev = goTo(list, k-1);
Node<Integer> pos;
if (prev!=null && prev.hasNext())
{
pos = prev.getNext();
prev.setNext(pos.getNext());
pos.setNext(null);
}
}
/**
*
* @param list2: Node<Integer>
* @param list3: Node<Integer> refer to Node<Integer>(0)
* @param k ; int
* inserts values in k position of list2 to list3,
* first value to insert change first value from 0 to the value from list2
*/
public static void insertK(Node<Integer> list2, Node<Integer> list3, int k)
{//list3 ‫ לרשימה‬k ‫הוספת אחבר במקום‬
Node<Integer> pos2 = goTo(list2, k);
Node<Integer> pos3 = list3;
Node<Integer> node;
int value;
if (pos2!=null)
{
value = pos2.getValue();
if (pos3.getInfo()==0)
{// insert the first value
pos3.setValue(value);
}
else
{
node = new Node<Integer>(value,pos3.getNext());
pos3.setNext(node);
}
}
}
public static Node<Integer> doIt(Node<Integer> list1, Node<Integer> list2)
{// ‫הפעולה על פי הניסוח‬
int k;
int value;
Node<Integer> pos;
Node<Integer> list3 = new Node<Integer>(0);
while (list1!=null)
{
- 181 -
k = list1.getValue();
if (k%2==0)
{// removes value after (k-1) steps in list2
deleteK(list2, k);
}
else
{// k%2!=0
insertK(list2, list3, k);
}
list1=list1.getNext();
}
return list3;
}
public static void main(String[] args)
{
System.out.println("create list1:");
Node<Integer> list1 = UtilNodeInt.create();
UtilNodeInt.print(list1);
System.out.println("create list2:");
Node<Integer> list2 = UtilNodeInt.create();
UtilNodeInt.print(list2);
Node<Integer> list3 = doIt(list1, list2);
System.out.println("after doIt");
System.out.println("list2");
UtilNodeInt.print(list2);
System.out.println("list3");
UtilNodeInt.print(list3);
}
}
‫עמי ומושית ולץ‬-‫ רחל בן‬3 ‫הצעה‬
:"‫הצעה לניסוח חדש שיתאים לתכנית "מבני נתונים‬
. L3 ‫ ותחזיר רשימה חדשה‬0-‫ של מספרים שלמים וגדולים מ‬L1,L2 ‫כתוב פעולה שתקבל שתי רשימות‬
.Node<int> ‫ מטיפוס‬L1, L2, L3
.‫ פעם אחת מתחילתה ועד סופה‬L1 ‫הפעולה תסרוק את הרשימה‬
.k-‫ נסמן את ערך האיבר ב‬. L1 ‫בכל שלב הפעולה תבדוק אבר אחד מהרשימה‬
:‫ כפי שהיא בשלב זה‬L2 ‫ ולרשימה‬k ‫ בהתאם ל‬,‫הפעולה תבצע את אחת הפעולות שלהלן‬
.L2 ‫ מתחילת הרשימה‬k ‫ הפעולה תמחק את האיבר שמיקומו‬,‫ הוא מספר זוגי‬K ‫ אם‬‫ איבר שהערך שלו הוא הערך של האיבר‬L3 ‫ הפעולה תוסיף לרשימה‬,‫ הוא מספר אי זוגי‬k ‫ אם‬.L2 ‫ מתחילת הרשימה‬k ‫שמיקומו‬
.‫ הפעולה לא תבצע דבר‬k ‫ אין איבר שמיקומו‬L2 ‫ אם ברשימה‬-
- 182 -
‫הערות‪:‬‬
‫אין חשיבות לסדר הכנסת האיברים לרשימה ‪. L3‬‬
‫הפעולה לא תחזיר את הרשימה ‪.L2‬‬
‫לדוגמה‪:‬‬
‫עבור הרשימות ‪( L1 , L2‬משמאל לימין)‪:‬‬
‫‪L1 4 , 3 ,2 ,6‬‬
‫‪L2 10 , 11 , 19 , 1 , 7 , 100‬‬
‫מצב הרשימות ‪ L2 ,L3‬בתום כל שלב ‪:‬‬
‫שלב ‪:1‬‬
‫‪L210 , 11 , 19 , 7 , 100‬‬
‫‪L3‬‬
‫שלב ‪:2‬‬
‫‪L210 , 11 , 19 , 7 , 100‬‬
‫‪L3 19‬‬
‫שלב ‪:3‬‬
‫‪L210 , 19, 7 , 100‬‬
‫‪L3 19‬‬
‫שלב ‪:4‬‬
‫‪L210 , 19 , 7 , 100‬‬
‫‪L3 19‬‬
‫שאלה ‪ ,4‬בגרות קיץ תשס"ז ‪2007‬‬
‫הניסוח המקורי‬
‫בטלפון הנייד של חברת "נייד‪-‬פון" ניהול השיחות הנכנסות מתבצע באופן הזה‪:‬‬
‫‪ ‬מספר טלפון שממנו התקבלה שיחה נשמר ברשימת שיחות נכנסות‪.‬‬
‫‪ ‬מספרי הטלפון של השיחות הנכנסות שהתקבלו במכשיר נשמרים לפי סדר הפוך מסדר קבלתן‪ ,‬כך שמספר‬
‫הטלפון של השיחה האחרונה שהתקבלה יהיה ראשון ברשימת השיחות הנכנסות‪.‬‬
‫‪ ‬כל מספרי הטלפון השמורים שונים זה מזה‪ .‬כאשר מתקבלת שיחה נוספת ממספר טלפון הנמצא כבר בין‬
‫מספרי השיחות הנכנסות‪ ,‬מספר זה נרשם ראשון והוא נמחק מקומו הקודם‪.‬‬
‫‪ ‬מספר השיחות הנכנסות שאפשר לשמור במכשיר מוגבל‪.‬‬
‫‪ ‬כאשר רשימת השיחות הנכנסות מלאה ומתקבלת שיחה ממספר טלפון שאינו נמצא ברשימה‪ ,‬מספר זה נרשם‬
‫ראשון והמספר האחרון נמחק‪.‬‬
‫יומן שיחות נכנסות מיוצג על ידי‪:‬‬
‫‪ .1‬רשימה מקושרת שכל איבר בה הוא מספר טלפון המיוצג ע"י מחרוזת‪.‬‬
‫‪ .2‬מספר שלם ‪ maxCalls‬המייצג את המספר המקסימלי של מספרי טלפון שאפשר לשמור ביומן השיחות‬
‫הנכנסות‪.‬‬
‫‪ .3‬מספר שלם ‪ currentCalls‬המייצג את המספר של מספרי הטלפון הנמצאים בזמן מסוים ביומן השיחות‬
‫הנכנסות‪.‬‬
‫‪- 183 -‬‬
‫לפותרים ב– ‪ C#‬או ב–‪Java‬‬
‫א‪ .‬כתוב ב–‪ C#‬או ב–‪ Java‬את כותרת המחלקה יומן שיחות נכנסות‪ ,‬ואת התכונות שלה על פי הייצוג המתואר ב– ‪1‬‬
‫עד ‪3‬‬
‫ב‪ .‬ממֵש ב–‪ C#‬או ב–‪ Java‬פעולה במחלקה יומן שיחות נכנסות‪ ,‬המקבלת מספר טלפון של שיחה נכנסת ‪ tel‬ומעדכנת‬
‫את יומן השיחות הנכנסות‪.‬‬
‫הערה‪:‬אפשר להשתמש בפעולות הממשק < ‪ List < T‬בלי לממש אותן‪ .‬אם אתה משתמש בפעולות נוספות‪ ,‬עליך‬
‫לממש אותן‪.‬‬
‫הצעה ‪ 1‬רוני אלנקרי‬
‫הקושי אליו אני מתייחסת הוא למחיקה מרשימה שהופכת מורכבת יותר בשרשרת חוליות שכן יש לשמור את המקום‬
‫הקודם לחוליה שיש למחוק‪ .‬בנוסף קיים הקושי שיש להתייחס ל‪ 2-‬מקרים שונים‪ ,‬מחיקה של החוליה הראשונה ומחיקה‬
‫של חוליה שאינה הראשונה‪.‬‬
‫במטרה להוריד את רמת הקושי ניתן לנסח את השאלה של בגרות ‪ 2007‬שאלה ‪ 4‬כך שלא תתקיים מחיקה מהמקום‬
‫הראשון‪ ,‬זאת מבלי לשנות את הנדרש בתיאור‪.‬‬
‫הצעה לניסוח חדש שיתאים לתכנית "מבני נתונים"‪:‬‬
‫בטלפון הנייד של חברת "נייד‪-‬פון" ניהול השיחות הנכנסות מתבצע באופן הזה‪:‬‬
‫‪-‬‬
‫מספר טלפון שממנו התקבלה שיחה נשמר ברשימת שיחות נכנסות‪.‬‬
‫‪-‬‬
‫מספרי הטלפון של השיחות הנכנסות שהתקבלו במכשיר נשמרים לפי סדר הפוך‬
‫מסדר קבלתן‪ ,‬כך שמספר הטלפון של השיחה האחרונה שהתקבלה יהיה ראשון‬
‫ברשימת השיחות הנכנסות‪.‬‬
‫‪-‬‬
‫כל מספרי הטלפון השמורים שונים זה מזה‪ .‬כאשר מתקבלת שיחה נוספת ממספר טלפון הנמצא כבר בין‬
‫מספרי השיחות הנכנסות‪ ,‬מספר זה נרשם ראשון והוא נמחק מקומו הקודם‪ .‬אם המספר נמצא כבר בין מספרי‬
‫הטלפון והוא ראשון אין לעשות דבר‪.‬‬
‫‪-‬‬
‫מספר השיחות הנכנסות שאפשר לשמור במכשיר מוגבל‪.‬‬
‫‪-‬‬
‫כאשר רשימת השיחות הנכנסות מלאה ומתקבלת שיחה ממספר טלפון שאינו נמצא ברשימה‪ ,‬מספר זה נרשם‬
‫ראשון והמספר האחרון נמחק‪.‬‬
‫הצעה ‪ 2‬יוסי זהבי‬
‫הצעה לניסוח חדש שיתאים לתכנית "מבני נתונים"‪:‬‬
‫בטלפון הנייד של חברת "נייד‪-‬פון" ניהול השיחות הנכנסות מתבצע באופן הזה‪:‬‬
‫‪‬‬
‫מספר טלפון שממנו התקבלה שיחה נשמר ברשימת שיחות נכנסות‪.‬‬
‫‪- 184 -‬‬
‫‪‬‬
‫מספרי הטלפון של השיחות הנכנסות שהתקבלו במכשיר נשמרים לפי סדר הפוך‬
‫מסדר קבלתן‪ ,‬כך שמספר הטלפון של השיחה האחרונה שהתקבלה יהיה ראשון‬
‫ברשימת השיחות הנכנסות‪.‬‬
‫‪‬‬
‫כל מספרי הטלפון השמורים שונים זה מזה‪ .‬כאשר מתקבלת שיחה נוספת ממספר טלפון הנמצא כבר בין‬
‫מספרי השיחות הנכנסות‪ ,‬מספר זה נרשם ראשון והוא נמחק מקומו הקודם‪.‬‬
‫‪‬‬
‫מספר השיחות הנכנסות שאפשר לשמור במכשיר מוגבל‪.‬‬
‫‪‬‬
‫כאשר רשימת השיחות הנכנסות מלאה ומתקבלת שיחה ממספר טלפון שאינו נמצא ברשימה‪ ,‬מספר זה נרשם‬
‫ראשון והמספר האחרון נמחק‪.‬‬
‫יומן שיחות נכנסות מיוצג על ידי‪:‬‬
‫‪ .1‬שרשרת חוליות שכל חוליה בה הוא מספר טלפון המיוצג ע"י מחרוזת‪.‬‬
‫‪ .2‬מספר שלם ‪ maxCalls‬המייצג את המספר המקסימלי של מספרי טלפון שאפשר‬
‫לשמור ביומן השיחות הנכנסות‪.‬‬
‫‪ .3‬מספר שלם ‪ currentCalls‬המייצג את המספר של מספרי הטלפון הנמצאים בזמן‬
‫מסוים ביומן השיחות הנכנסות‪.‬‬
‫לפותרים ב– ‪ C#‬או ב–‪Java‬‬
‫א‪ .‬כתוב ב–‪ C#‬או ב–‪ Java‬את כותרת המחלקה יומן שיחות נכנסות‪ ,‬ואת התכונות‬
‫שלה על פי הייצוג המתואר ב– ‪ 1‬עד ‪3‬‬
‫ב‪ .‬ממֵש ב–‪ C#‬או ב–‪ Java‬פעולה במחלקה יומן שיחות נכנסות‪ ,‬המקבלת מספר טלפון של שיחה נכנסת ‪ tel‬ומעדכנת‬
‫את יומן השיחות הנכנסות‪.‬‬
‫הערה‪ :‬אפשר להשתמש בפעולות של המחלקה >‪ , Node<T‬בלי לממש אותן‪.‬‬
‫אם אתה משתמש בפעולות נוספות‪ ,‬עליך לממש אותן‪.‬‬
‫‪- 185 -‬‬
‫שאלה ‪ ,2‬בגרות קיץ תשס"ח ‪2008‬‬
‫הניסוח המקורי‬
‫טיפוס הנתונים מיון ‪ -‬בתחומים מאפשר לשמור כמות גדולה של מספרים שלמים‪ ,‬שונים זה מזה‪,‬‬
‫הממוינים לפי תחומים‪ .‬לכל תחום מוגדר ערך מינימלי וערך מקסימלי‪ .‬כל תחום כולל מספרים הגדולים מהערך‬
‫המינימלי או שווים לו‪ ,‬וקטנים מהערך המקסימלי‪.‬‬
‫לתחום האחרון מוגדר רק ערך מינימלי‪ ,‬והוא כולל מספרים הגדולים מערך או שווים לו‪.‬‬
‫טיפוס הנתונים מיון ‪ -‬בתחומים מורכב מ‪:‬‬
‫מערך חד מימדי בגודל ‪ 100‬המכיל מספרים שלמים שונים זה מזה‪ ,‬הממוינים בסדר עולה‪ .‬כל מספר מייצג‬
‫‪mins‬‬
‫ערך מינימלי של תחום‪.‬‬
‫‪ values‬מערך חד מימדי בגודל ‪ 100‬המכיל רשימות כל רשימה מכילה מספרים שלמים שונים זה מזה‪ ,‬הממוינים‬
‫בסדר עולה‪ .‬ברשימה שנמצאת במקום ‪ k‬במערך ‪ values‬נמצאים מספרים הגדולים מן הערך שנמצא במקום‬
‫ה ‪ k‬במערך ‪ mins‬או שווים לו‪ .‬וקטנים מן הערך שנמצא במקום ה ‪ k+1‬במערך ‪ .mins‬ברשימה האחרונה‬
‫נמצאים מספרים הגדולים מן הערך המינימלי של התחום האחרון או שווים לו‪.‬‬
‫‪ current‬מספר שלם המייצג את מספר התחומים הנוכחי במערך ‪mins‬‬
‫לדוגמא‪ :‬בעבור המספרים האלה‪ 1, 700, 556, 120, 220, 9, 6, 99, 555 :‬ושלושת התחומים האלה‪:‬‬
‫מספרים הגדולים מ ‪ 0‬או שווים לו וקטנים מ ‪101‬‬
‫‪.i‬‬
‫מספרים הגדולים מ ‪ 101‬או שווים לו וקטנים מ ‪556‬‬
‫‪.ii‬‬
‫מספרים השווים ל ‪ 556‬או גדולים ממנו‪.‬‬
‫‪.iii‬‬
‫‪ sort1‬מטיפוס מיון – בתחומים יהיה‪:‬‬
‫א‪ .‬רשום ב ‪ Java‬או ב ‪ C#‬את כותרת המחלקה מיון – בתחומים ‪ SortByRange‬ואת התכונות שלה‪.‬‬
‫ב‪ .‬ממש ב ‪ Java‬או ב ‪ C#‬פעולה פנימית בשם ‪ insert‬במחלקה ‪ ,SortByRange‬שתקבל מספר שלם ‪.num‬‬
‫הפעולה תכניס את ‪ num‬לרשימה המתאימה במערך ‪ ,values‬על פי סדר המיון של המספרים ברשימה‪.‬‬
‫הנח כי ‪ num‬אינו נמצא ב‪ values -‬ו‪ num -‬גדול מהערך הקטן ביותר שנמצא במערך ‪.mins‬‬
‫ג‪ .‬ממש ב ‪ Java‬או ב ‪ C#‬פעולה פנימית בשם ‪ addRange‬במחלקה ‪ , SortByRange‬שתקבל מספר שלם ‪r‬‬
‫הגדול מכל המספרים ב – ‪ .values‬הפעולה תוסיף תחום חדש ש‪ r -‬הוא הערך המינימלי שלו‪.‬‬
‫הנח כי יש מקום לתחום נוסף‪.‬‬
‫ד‪ .1.‬מהי סיבוכיות זמן ריצה של הפעולה שמימשת בסעיף ב'‪ .‬הסבר‪.‬‬
‫ד‪ .2.‬מהי סיבוכיות זמן ריצה של הפעולה שמימשת בסעיף ג'‪ .‬הסבר‪.‬‬
‫הערה‪ :‬אפשר להשתמש בפעולות של המחלקה >‪ ,List<T> Node<T‬בלי לממש אותן‪.‬‬
‫אם אתה משתמש בפעולות נוספות‪ ,‬עליך לממש אותן‪.‬‬
‫‪- 186 -‬‬
‫הצעה ‪ 1‬רחל לודמר‬
‫הצעה לניסוח חדש שיתאים לתכנית "מבני נתונים"‪:‬‬
‫טיפוס הנתונים מיון ‪ -‬בתחומים מאפשר לשמור כמות גדולה של מספרים שלמים‪ ,‬שונים זה מזה‪,‬‬
‫הממוינים לפי תחומים‪ .‬לכל תחום מוגדר ערך מינימלי וערך מקסימלי‪ .‬כל תחום כולל מספרים הגדולים מהערך‬
‫המינימלי או שווים לו‪ ,‬וקטנים מהערך המקסימלי‪.‬‬
‫לתחום האחרון מוגדר רק ערך מינימלי‪ ,‬והוא כולל מספרים הגדולים מערך או שווים לו‪.‬‬
‫טיפוס הנתונים מיון ‪ -‬בתחומים מורכב מ‪:‬‬
‫‪ – mins‬מערך חד מימדי בגודל ‪ 100‬המכיל מספרים שלמים שונים זה מזה‪ ,‬הממוינים בסדר עולה‪.‬‬
‫כל מספר מייצג ערך מינימלי של תחום‪.‬‬
‫‪ - values‬מערך חד מימדי בגודל ‪ 100‬המכיל רשימות כל רשימה מכילה מספרים שלמים שונים זה‬
‫מזה‪ ,‬הממוינים בסדר עולה‪.‬‬
‫הרשימות הן מטיפוס >‪ Node<Integet‬ב ‪ ,java‬וב ‪ C#‬מטיפוס >‪.Node<int‬‬
‫ברשימה שנמצאת במקום ‪ k‬במערך ‪ values‬נמצאים מספרים הגדולים מן הערך שנמצא‬
‫במקום ה ‪ k‬במערך ‪ mins‬או שווים לו‪ .‬וקטנים מן הערך שנמצא במקום ה ‪ k+1‬במערך‬
‫‪ .mins‬ברשימה האחרונה נמצאים מספרים הגדולים מן הערך המינימלי של התחום‬
‫האחרון או שווים לו‪.‬‬
‫‪ – current‬מספר שלם המייצג את מספר התחומים הנוכחי במערך ‪.mins‬‬
‫לדוגמא‪ :‬בעבור המספרים האלה‪1, 700, 556, 120, 220, 9, 6, 99, 555 :‬‬
‫ושלושת התחומים האלה‪:‬‬
‫מספרים הגדולים מ ‪ 0‬או שווים לו וקטנים מ ‪101‬‬
‫‪.iv‬‬
‫מספרים הגדולים מ ‪ 101‬או שווים לו וקטנים מ ‪556‬‬
‫‪.v‬‬
‫מספרים השווים ל ‪ 556‬או גדולים ממנו‪.‬‬
‫‪.vi‬‬
‫‪ sort1‬מטיפוס מיון – בתחומים יהיה‪:‬‬
‫‪current‬‬
‫‪3‬‬
‫‪values‬‬
‫‪mins‬‬
‫‪0‬‬
‫‪1, 6 , 9, 99‬‬
‫‪101‬‬
‫‪120, 220, 555‬‬
‫‪556, 700‬‬
‫‪556‬‬
‫‪.‬‬
‫‪.‬‬
‫‪.‬‬
‫‪ SortByRange‬ואת התכונות שלה‪.‬‬
‫א‪ .‬רשום ב ‪ Java‬או ב ‪ C#‬את כותרת המחלקה מיון – בתחומים‬
‫‪.‬‬
‫הנח שבמחלקה פעולה בונה ברירת מחדל ופעולה שמקבלת פרמטר לכל תכונה‪.‬‬
‫ב‪ .‬ממש ב ‪ Java‬או ב ‪ C#‬פעולה פנימית בשם ‪ insert‬במחלקה ‪ ,SortByRange‬שתקבל מספר שלם ‪.num‬‬
‫הפעולה תכניס את ‪ num‬לרשימה המתאימה במערך ‪ ,values‬על פי סדר המיון של המספרים ברשימה‪.‬‬
‫הנח כי ‪ num‬אינו נמצא ב‪ values -‬ו‪ num -‬גדול מהערך הקטן ביותר שנמצא במערך ‪.mins‬‬
‫‪- 187 -‬‬
‫ג‪ .‬ממש ב ‪ Java‬או ב ‪ C#‬פעולה פנימית בשם ‪ addRange‬במחלקה ‪ , SortByRange‬שתקבל מספר שלם ‪r‬‬
‫הגדול מכל המספרים ב – ‪ .values‬הפעולה תוסיף תחום חדש ש‪ r -‬הוא הערך המינימלי שלו‪.‬‬
‫הנח כי יש מקום לתחום נוסף‪.‬‬
‫ד‪ .1.‬מהי סיבוכיות זמן ריצה של הפעולה שמימשת בסעיף ב'‪ .‬הסבר‪.‬‬
‫ד‪ .2.‬מהי סיבוכיות זמן ריצה של הפעולה שמימשת בסעיף ג'‪ .‬הסבר‪.‬‬
‫הערה‪ :‬אפשר להשתמש בפעולות של המחלקה >‪ , Node<T‬בלי לממש אותן‪.‬‬
‫אם אתה משתמש בפעולות נוספות‪ ,‬עליך לממש אותן‪.‬‬
‫הצעה ‪ 2‬גיא אורן‬
‫למה בחרתי בשאלה הזו‪.‬‬
‫לדעתי השאלה הזו מייצגת את רמת השאלות שהייתי רוצה לראות בבגרות‪.‬‬
‫הצעה לניסוח חדש שיתאים לתכנית "מבני נתונים"‪:‬‬
‫מבנה הנתונים מיון בתחומים (‪ )SortByRange‬מאפשר לשמור כמות גדולה של מספרים שלמים‪ ,‬שונים זה מזה‪,‬‬
‫הממוינים לפי תחומים‪ .‬כל המספרים בתחום נעים בין ערך מינימלי למקסימלי המגדירים את התחום‪ .‬לתחום האחרון‬
‫יוגדר ערך מינימלי בלבד‪.‬‬
‫כדי לממש את מבנה הנתונים נגדיר‪:‬‬
‫‪ mins‬מערך חד ממדי בגודל ‪ 100‬המכיל מספרים בסדר עולה ממש‪.‬‬
‫‪ values‬מערך חד ממדי בגודל ‪ 100‬המכיל הפנייה לשרשרת חוליות ממויינת‪ .‬שרשרת חוליות ‪ k‬מכילה מספרים‬
‫המתאימה לתחום המוגדר ע"י )]‪.(mins[k],mins[k+1‬‬
‫‪ – current‬מספר המייצג את מספר התחומים הנוכחי‪.‬‬
‫‪ sort1‬הוא אובייקט‪/‬הפנייה מסוג ‪SortByRanger‬‬
‫א‪ .‬רשום ב ‪ JAVA‬את כותרת המחלקה ‪ SortByRange‬ואת התכונות שלה‪.‬‬
‫ב‪ .‬ממש את הפעולה ‪ 2insert‬כך שתקבל מספר ‪ . num‬הפעולה תכניס את המספר לשרשרת החוליות המתאימה‪ .‬ניתן‬
‫להניח כי ‪ num‬גדול מהערך המינימלי במערך התחומים‪ .3‬ניתן להניח שהמספר ‪ num‬אינו קיים במבנה‪.‬‬
‫ג‪ .‬ממש ב ‪ JAVA‬פעולה בשם ‪ addRange‬שתקבל מספר ‪ r‬הגדול ממש מהמספר המקסימלי ב‪ . values‬הפעולה‬
‫תוסיף תחום חדש ש‪ r-‬הוא ערכו המינימלי‪ .‬הנח כי יש מקום לתחום הנוסף‪.4‬‬
‫‪ 2‬אני לא חושב שצריך לציין פנימית‪ ,‬זו צריכה להיות ברירת המחדל‪.‬‬
‫‪ 3‬עדיף היה לו ההנחה הזו הייתה יורדת‪ ,‬ובמקומה הצעה מה לעשות במקרה הנ"ל‪.‬‬
‫‪ 4‬שוב מיותר‪ .‬במקום יש להגדיר לתלמידים מה לעשות במידה ואין אפשרות להוסיף תחום נוסף‪.‬‬
‫‪- 188 -‬‬
.'‫ ב וג‬.‫אני חושב שהיה עדיף להפוך את סדר הסעיפים‬
‫פתרון‬
.‫ החלטתי בסוף ללכת על פתרון פשוט יותר‬.‫ משלי‬sortedList ‫התלבטתי אם להוסיף‬
package bagrut2008;
import unit4.collectionsLib.*;
public class SortByRange {
final static int MAX_NUM_OF_RANGES = 100;
private Node<Integer>[] values = new Node[MAX_NUM_OF_RANGES];
private int[] mins = new int[MAX_NUM_OF_RANGES];
private int current;
private int search(int num)
{
for(int idx = 0;idx <= current;idx++)
{
if(mins[idx] < num)
return idx;
}
return -1;
}
public void addRange(int r)
{
mins[current++] = r;
}
public void insert(int num)
{
Node<Integer> cur = values[search(num)],
prev = cur;
Node<Integer> newLink = new Node<Integer>(num);
if(cur == null)
{
cur = newLink;
}
else
{
for(;cur.getInfo() < num;prev = cur,cur = cur.getNext());
prev.setNext(newLink);
newLink.setNext(cur);
}
}
}
- 189 -
‫שאלה ‪ ,1‬בגרות קיץ תשס"ט ‪2009‬‬
‫הניסוח המקורי‪:‬‬
‫רשימה תיקרא משולשת אם היא מקיימת את התנאים האלה‪:‬‬
‫* הרשימה אינה ריקה‪.‬‬
‫* מספר האיברים בה מתחלק ב‪ 3-‬בלי שארית‪.‬‬
‫* האיברים בשליש הראשון של הרשימה מכילים את אותם ערכים שמכילים האיברים בשליש השני של‬
‫הרשימה ואותם ערכים שמכילים האיברים בשליש השלישי של הרשימה‪ .‬הערכים מסודרים באותו סדר בכל‬
‫אחד מהשלישים‪.‬‬
‫לדוגמה‪ :‬הרשימה ‪ L1‬שלפניך היא רשימה משולשת באורך ‪.12‬‬
‫כתוב ב‪ C# -‬או ב‪ Java -‬פעולה חיצונית שתקבל רשימה ‪ L‬שהאיברים שלה הם מטיפוס שלם‪.‬‬
‫אם ‪ L‬היא רשימה משולשת‪ ,‬הפעולה תחזיר ‪ .true‬אחרת ‪ -‬הפעולה תחזיר ‪.false‬‬
‫אתה יכול להשתמש בפעולות של המחלקות >‪ List <T> ,Node <T‬בלי לממש אותן‪.‬‬
‫אם אתה משתמש בפעולות נוספות‪ ,‬עליך לממש אותן‪.‬‬
‫הצעה ‪ 1‬ולרי פקר‬
‫ולרי מציע לתאר את הרשימה המשולשת כך‪:‬‬
‫הצעה לניסוח חדש שיתאים לתכנית "מבני נתונים"‪:‬‬
‫שרשרות חוליות תיקרא משולשת אם היא מקיימת את התנאים האלה‪:‬‬
‫* מספר האיברים בה מתחלק ב‪ 3-‬בלי שארית‪.‬‬
‫*‬
‫האיברים בשליש הראשון של שרשרות החוליות מכילים את אותם ערכים שמכילים האיברים בשליש השני‬
‫של שרשרות החוליות ואותם ערכים שמכילים האיברים בשליש השלישי של שרשרות החוליות‪ .‬הערכים‬
‫מסודרים באותו סדר בכל אחד מהשלישים‪.‬‬
‫לדוגמה‪ :‬שרשרות החוליות ‪ chain‬שלפניך היא רשימה של מספרים שלמים משולשת באורך ‪.12‬‬
‫כתוב פעולה חיצונית שתקבל שרשרות חוליות ‪ chain‬שהאיברים שלה הם מטיפוס שלם‪.‬‬
‫אם ‪ chain‬היא שרשרות חוליות משולשת‪ ,‬הפעולה תחזיר ‪ .true‬אחרת ‪ -‬הפעולה תחזיר ‪.false‬‬
‫‪- 190 -‬‬
‫ דפנה לוי רשתי‬2 ‫הצעה‬
:"‫הצעה לניסוח חדש שיתאים לתכנית "מבני נתונים‬
:‫ תקרא משולשת אם היא מקיימת את התנאים הבאים‬L ‫שרשרת חוליות‬
.‫ בלי שארית‬3-‫מספר החוליות בה מתחלק ב‬
‫החוליות בשליש הראשון של השרשרת מכילים את אותם ערכים שמכילות החוליות בשליש השני של השרשרת ואותם‬
.‫ הערכים מסודרים באותו סדר בכל אחד מהשלישים‬.‫ערכים שמכילות החוליות בשליש השלישי של השרשרת‬
‫ היא שרשרת חוליות משולשת‬L ‫ אם‬.‫ שהאיברים שלה הם מטיפוס שלם‬L ‫כתוב פעולה שתקבל שרשרת חוליות‬
.‫ הפעולה תחזיר שקר‬,‫ אחרת‬,‫הפעולה תחזיר אמת‬
public static bool TripleList(Node<int> pos1)
{
int length = Length(pos1);
if (length == 0 || length % 3 != 0)
return false;
Node<int> pos2 = NodeAfterXNodes(pos1, length / 3);
Node<int> pos3 = NodeAfterXNodes(pos2, length / 3);
while (pos3 != null &&
pos1.GetInfo() == pos2.GetInfo() &&
pos1.GetInfo() == pos3.GetInfo())
{
pos1 = pos1.GetNext();
pos2 = pos2.GetNext();
pos3 = pos3.GetNext();
}
return (pos3 == null);
}
public static int Length(Node<int> pos)
{
int length = 0;
while (pos != null)
{
pos = pos.GetNext();
length++;
}
return length;
}
private static Node<int> NodeAfterXNodes(Node<int> pos,
int length)
{
- 191 -
‫)‪while (length > 0 && pos != null‬‬
‫{‬
‫;)(‪pos = pos.GetNext‬‬
‫;‪length--‬‬
‫}‬
‫;‪if (length == 0) return pos‬‬
‫;‪return null‬‬
‫}‬
‫שאלה ‪ ,2‬בגרות קיץ תש"ע ‪2010‬‬
‫הניסוח המקורי‪:‬‬
‫‪ L‬היא רשימה המכילה מספרים שלמים שונים זה מזה וממוינים בסדר עולה‪.‬‬
‫רשימת הטווחים של ‪ L‬היא רשימה חדשה שנבנית באופן הזה‪:‬‬
‫בעבור כל רצף של מספרים עוקבים ב‪ L -‬יהיה ברשימת הטווחים איבר אחד שמכיל שני מספרים‪ .‬מספר אחד הוא המספר הקטן‬
‫ביותר ברצף‪ ,‬והמספר השני הוא הגדול ביותר ברצף‪.‬‬
‫רצף יכול להיות באורך ‪ 1‬או יותר‪ .‬אם הרצף באורך ‪ ,1‬הוא מיוצג ברשימת הטווחים על ידי איבר ששני המספרים בו שווים‪.‬‬
‫לפנייך תיאור חלקי של המחלקה ‪ , RangeNode‬המייצגת איבר ברשימת הטווחים‪.‬‬
‫‪RangeNode‬‬
‫;‪private int from‬‬
‫המספר הקטן ביותר ברצף ‪//‬‬
‫‪Private int to‬‬
‫המספר הגדול ביותר ברצף ‪//‬‬
‫)‪public RangeNode(int from, int to‬‬
‫ממש ב‪ java -‬או ב‪ c# -‬פעולה חיצונית שתקבל רשימה לא ריקה‪ ,‬המכילה מספרים שלמים השונים זה מזה וממוינים‬
‫בסדר עולה‪ ,‬ותחזיר את רשימת הטווחים שלה‪.‬‬
‫כותרת הפעולה ב‪ java -‬היא‪:‬‬
‫)‪public static List<RangeNode> createRangList(List<Integer> sourceList‬‬
‫‪- 192 -‬‬
‫כותרת הפעולה ב‪ c# -‬היא‪:‬‬
‫)‪public static List<RangeNode> CreateRangList(List<int> sourceList‬‬
‫הנח שלכל אחת מהתכונות במחלקה ‪ RangeNode‬יש פעולות ‪ get‬ו‪.set -‬‬
‫אתה יכול להשתמש הפעולות אלה ובפעולה הבונה של המחלקה ‪ RangeNode‬בלי לממש אותן‪.‬‬
‫אם אתה משתמש בפעולות נוספות‪ ,‬עליך לממש אותן‪.‬‬
‫הצעה ‪ 1‬גלית שריקי‬
‫הצעה לניסוח חדש שיתאים לתכנית "מבני נתונים"‪:‬‬
‫‪ L‬היא שרשרת חוליות המכילה מספרים שלמים שונים זה מזה וממוינים בסדר עולה‪.‬‬
‫רשימת הטווחים של ‪ L‬היא שרשרת חוליות חדשה שנבנית באופן הזה‪:‬‬
‫בעבור כל רצף של מספרים עוקבים ב‪ L -‬יהיה ברשימת הטווחים איבר אחד שמכיל שני מספרים‪ .‬מספר אחד הוא המספר הקטן‬
‫ביותר ברצף‪ ,‬והמספר השני הוא הגדול ביותר ברצף‪.‬‬
‫רצף יכול להיות באורך ‪ 1‬או יותר‪ .‬אם הרצף באורך ‪ ,1‬הוא מיוצג ברשימת הטווחים על ידי איבר ששני המספרים בו שווים‪.‬‬
‫לפנייך תיאור חלקי של המחלקה ‪ , RangeNode‬המייצגת איבר ברשימת הטווחים‪.‬‬
‫‪RangeNode‬‬
‫;‪private int from‬‬
‫המספר הקטן ביותר ברצף ‪//‬‬
‫‪Private int to‬‬
‫המספר הגדול ביותר ברצף ‪//‬‬
‫)‪public RangeNode(int from, int to‬‬
‫ממש ב‪ java -‬או ב‪ c# -‬פעולה חיצונית שתקבל שרשרת חוליות‪ ,‬המכילה מספרים שלמים השונים זה מזה וממוינים‬
‫בסדר עולה‪ ,‬ותחזיר את רשימת הטווחים שלה‪.‬‬
‫כותרת הפעולה ב‪ java -‬היא‪:‬‬
‫)‪public static Node<RangeNode> createRangList(Node<Integer> sourceList‬‬
‫כותרת הפעולה ב‪ c# -‬היא‪:‬‬
‫)‪public static Node<RangeNode> CreateRangList(Node<int> sourceList‬‬
‫הנח שלכל אחת מהתכונות במחלקה ‪ RangeNode‬יש פעולות ‪ get‬ו‪.set -‬‬
‫אתה יכול להשתמש הפעולות אלה ובפעולה הבונה של המחלקה ‪ RangeNode‬בלי לממש אותן‪.‬‬
‫אם אתה משתמש בפעולות נוספות‪ ,‬עליך לממש אותן‪.‬‬
‫‪- 193 -‬‬
‫הערה של דפנה מינסטר‪:‬‬
‫בתרגיל שהמרת קיים המושג שרשרת חוליות‪ L( ,‬היא שרשרת חוליות המכילה)‪,‬‬
‫אך בהמשך השאלה יש את המונח איבר‪ .‬אני חושבת שמונח זה קשור יותר לרשימה ולא לשרשרת חוליות‪.‬‬
‫אולי גם כדאי לשנות את רשימת הטווחים לשרשרת הטווחים ?‬
‫הייתי מחליפה את המילה איבר במילה חוליה‪.‬‬
‫מה דעתך? מה דעתכם‪ ,‬חברי המורים ?‬
‫הצעה ‪ 2‬חני טוראל‬
‫הצעה לניסוח חדש שיתאים לתכנית "מבני נתונים"‪:‬‬
‫‪ intNode‬הוא הפנייה לחוליה הראשונה בשרשרת חוליות המכילה מספרים שלמים השונים זה מזה וממויינים בסדר‬
‫עולה – לשרשרת זו נקרא רשימה ‪.L‬‬
‫רשימת הטווחים של הרשימה ‪ L‬היא שרשרת חוליות חדשה שנבנית באופן הזה‪ :‬בעבור כל רצף של מספרים עוקבים‬
‫ברשימה ‪ L‬יהיה ברשימת הטווחים חוליה אחת שמכילה שני מספרים‪ .‬מספר אחד הוא המספר הקטן ביותר ברצף‪,‬‬
‫והמספר השני הוא המספר הגדול ביותר ברצף‪.‬‬
‫רצף יכול להיות באורך ‪ 1‬או יותר‪ .‬אם הרצף הוא באורך ‪ ,1‬הוא מיוצג ברשימת הטווחים על ידי חוליה ששני‬
‫המספרים בה שווים‪.‬‬
‫לדוגמא ‪ ,‬בעבור הרשימה ‪ L‬שלפניך‪:‬‬
‫רשימת הטווחים של ‪ L‬תהיה‪:‬‬
‫לפניך תיאור חלקי של המחלקה ‪ ,RangeNode‬המייצגת חוליה ברשימת הטווחים‪.‬‬
‫ממש ב ‪ Java‬או ב ‪ C#‬פעולה חיצונית שתקבל הפנייה לשרשרת חוליות‪ ,‬המכילה מספרים שלמים שונים זה מזה‬
‫וממויינים בסדר עולה‪ ,‬ותחזיר את רשימת הטווחים שלה (את הפניה לחוליה הראשונה בשרשרת החוליות )‪.‬‬
‫כותרת הפעולה ב‪ Java -‬היא‪:‬‬
‫)‪public static Node<RangeNode> createRangeList(Node<int> source‬‬
‫כותרת הפעולה ב‪ C# -‬היא‪:‬‬
‫)‪public static Node<RangeNode> CreateRangeList(Node<int> source‬‬
‫הנח שלכל אחת מהתכונות במחלקה ‪ RangeNode‬יש פעולות ‪ get‬ו‪. set -‬‬
‫אתה יכול להשתמש בפעולות אלה ובפעולה הבונה של המחלקה ‪ RangeNode‬בלי לממש אותן‪.‬‬
‫אם אתה משתמש בפעולות נוספות‪ ,‬עליך לממש אותן‪.‬‬
‫‪- 194 -‬‬
‫הצעה ‪ 3‬ישראל אברמוביץ‬
‫הצעה לניסוח חדש שיתאים לתכנית "מבני נתונים"‪:‬‬
‫‪ L‬היא רשימה אשר ממומשת כשרשרת חוליות המכילה מספרים שלמים שונים זה מזה וממוינים בסדר עולה‪.‬‬
‫רשימת הטווחים של ‪ L‬היא רשימה חדשה שנבנית באופן הזה‪ :‬בעבור כל רצף של מספרים עוקבים ב‪ L -‬יהיה ברשימת‬
‫הטווחים איבר אחד שמכיל שני מספרים‪ .‬מספר אחד הוא המספר הקטן ביותר ברצף‪ ,‬והמספר השני הוא המספר הגדול ביותר‬
‫ברצף‪.‬‬
‫רצף יכול להיות באורך ‪ 1‬או יותר‪ .‬אם הרצף הוא באורך ‪ ,1‬הוא מיוצג ברשימת הטווחים על ידי חוליה ששני המספרים בה‬
‫שווים‪.‬‬
‫לדוגמא ‪ ,‬בעבור הרשימה ‪ L‬שלפניך‪:‬‬
‫רשימת הטווחים של ‪ L‬תהיה‪:‬‬
‫לפניך תיאור חלקי של המחלקה ‪ ,RangeNode‬המייצגת חוליה ברשימת הטווחים‪.‬‬
‫ממש ב ‪ Java‬או ב ‪ C#‬פעולה חיצונית שתקבל הפניה אל החוליה הראשונה ברשימה‪ ,‬הרשימה המכילה לפחות חוליה אחת‪.‬‬
‫שרשרת החוליות שמרכיבה את הרשימה‪ ,‬מכילה מספרים שלמים שונים זה מזה וממוינים בסדר עולה‪.‬‬
‫הפעולה תחזיר הפניה לרשימה שבנויה משרשרת החוליות ‪. RangeNode‬‬
‫כותרת הפעולה ב ‪Java‬‬
‫)‪public static Node<RangeNode> CreateRangeListWithNodes(Node<integer> sourceList‬‬
‫כותרת הפעולה ב ‪C#‬‬
‫)‪public static Node<RangeNode> CreateRangeListWithNodes(Node<int> sourceList‬‬
‫הנח שלכל אחת מהתכונות במחלקה ‪ RangeNode‬יש פעולות ‪ get‬ו‪. set -‬‬
‫אתה יכול להשתמש בפעולות אלה ובפעולה הבונה של המחלקה ‪ RangeNode‬בלי לממש אותן‪.‬‬
‫אם אתה משתמש בפעולות נוספות‪ ,‬עליך לממש אותן‪.‬‬
‫פיתרון (שינוי מהפתרון באתר של הילה קדמן)‬
‫)‪public static Node<RangeNode> CreateRangeListWithNodes(Node<int> sourceList‬‬
‫{‬
‫;‪Node<int> p = sourceList‬‬
‫;)‪Node<RangeNode> qFirst = new Node<RangeNode>(null, null‬‬
‫‪- 195 -‬‬
Node<RangeNode> q = qFirst;
Node<RangeNode> qTemp;
RangeNode r = new RangeNode(2,3);
Node<RangeNode> qFirst2 = new Node<RangeNode>(r, null);
int x, y = 0, z;
z = p.GetInfo();
if (p.GetNext() == null) // ‫אחד מאיבר מורכבת הרשימה אם‬
qFirst.SetInfo(new RangeNode(z, z));
else
{
while (p.GetNext() != null)
{
x = p.GetInfo();
y = p.GetNext().GetInfo();
if (y - x == 1)
{
p = p.GetNext();
}
else
{
qTemp = new Node<RangeNode>(new RangeNode(z, x), null);
q.SetNext(qTemp);
q = q.GetNext();
z = y;
p = p.GetNext();
}
}
qTemp = new Node<RangeNode>(new RangeNode(z, y), null);
q.SetNext(qTemp);
}
return qFirst;
}
2013 ‫ בגרות קיץ תשע"ג‬,1 ‫שאלה‬
:‫הניסוח המקורי‬
.Sod3 ,Sod2 ,Sod1 ‫לפניך שלוש פעולות‬
public static bool Sod1(List<int> list1, List<int> list2)
{
Node<int> node1 = list1.GetFirst();
Node<int> node2 = list2.GetFirst();
for (int i = 1; i <= 4; i++)
{
if (node1 == null || node2 == null)
- 196 -
return false;
if (i == 1 || i == 4)
if (node1.GetInfo() != node2.GetInfo())
return false;
node1 = node1.GetNext();
}
return true;
}
public static bool Sod2(List<int> list1, List<int> list2)
{
Node<int> node1 = list1.GetFirst();
Node<int> node2 = list2.GetFirst();
while (node1 != null && node2 != null)
{
if (node1.GetInfo() != node2.GetInfo())
return false;
node1 = node1.GetNext();
node2 = node2.GetNext();
}
return true;
}
public static bool Sod3(List<int> list1, List<int> list2)
{
Node<int> node1 = list1.GetFirst();
while (node1 != null)
{
bool found = false;
Node<int> node2 = list2.GetFirst();
while (node2 != null && !found)
{
if (node1.GetInfo() == node2.GetInfo())
found = true;
node2 = node2.GetNext();
}
if (!found)
return false;
node1 = node1.GetNext();
}
return true;
}
:‫ שלפניך‬list2-‫ ו‬list1 ‫ עם הרשימות‬,Sod3 ,Sod2 ,Sod1 ‫עקוב אחר כל אחת מהפעולות‬
- 197 -
.‫א‬
list1: [2, 4, 5, 1, 1, 9]
list2: [2, 4, 5, 1, 4]
.‫ במעקב הראה את המעבר על הרשימות‬.‫רשום מה יוחזר בעבור כל אחת מהפעולות‬
.‫? נמק את תשובתך‬Sod3 ,Sod2 ,Sod1 ‫מה סיבוכיות זמן הריצה של כל אחת מהפעולות‬
.‫ב‬
‫ ולרי פקר‬1 ‫הצעה‬
:"‫הצעה לניסוח חדש שיתאים לתכנית "מבני נתונים‬
.Sod3 ,Sod2 ,Sod1 ‫לפניך שלוש פעולות‬
public static bool Sod1(Node<int> chain1, Node<int> chain2)
{
for (int i = 1; i <= 4; i++)
{
if (chain1 == null || chain2 == null)
return false;
if (i == 1 || i == 4)
if (chain1.GetInfo() != chain2.GetInfo())
return false;
chain1 = chain1.GetNext();
}
return true;
}
public static bool Sod2(Node<int> chain1, Node<int> chain2)
{
while (chain1 != null && chain2 != null)
{
if (chain1.GetInfo() != chain2.GetInfo())
return false;
chain1 = chain1.GetNext();
chain2 = chain2.GetNext();
}
return true;
}
public static bool Sod3(Node<int> chain1, Node<int> chain2)
{
Node<int> pos1 = chain1;
while (pos1 != null)
- 198 -
{
bool found = false;
Node<int> pos2 = chain2;
while (pose2 != null && !found)
{
if (pos1.GetInfo() == pos2.GetInfo())
found = true;
pos2 = pos2.GetNext();
}
if (!found)
return false;
pos1 = pos1.GetNext();
}
return true;
}
chain1 ‫ עם שתי שרשרות החוליות של מספרים שלמים‬,Sod3 ,Sod2 ,Sod1 ‫עקוב אחר כל אחת מהפעולות‬
:‫ שלפניך‬chain2-‫ו‬
.‫א‬
.‫ במעקב הראה את המעבר על שרשרות החוליות‬.‫רשום מה יוחזר בעבור כל אחת מהפעולות‬
.‫? נמק את תשובתך‬Sod3 ,Sod2 ,Sod1 ‫מה סיבוכיות זמן הריצה של כל אחת מהפעולות‬
.‫ב‬
‫ רחלי צרניחוב‬2 ‫הצעה‬
:"‫הצעה לניסוח חדש שיתאים לתכנית "מבני נתונים‬
(List<int> list1, List<int> list2)
‫במקום‬
(Node<int> list1, Node<int> list2) ‫יהיה כתוב‬
Node<int> node1 = list1.GetFirst();
‫במקום‬
Node<int> node1 = list1.GetFirst(); ‫יהיה כתוב‬
public static bool Sod1(Node<int> list1, Node<int> list2)
{
Node<int> node1 = list1;
Node<int> node2 = list2;
- 199 -
for (int i = 1; i <= 4; i++)
{
if ((node1 == null) || (node2 == null))
return
false;
if ((i == 1) || (i == 4))
if (node1.GetInfo() != node2.GetInfo())
return
false;
node1 = node1.GetNext();
}
return true;
}
public static bool Sod2(Node<int> list1, Node<int> list2)
{
Node<int> node1 = list1;
Node<int> node2 = list2;
while ((node1 != null) && (node2 != null))
{
if (node1.GetInfo() != node2.GetInfo())
return
false;
node1 = node1.GetNext();
node2 = node2.GetNext();
}
return true;
}
public static bool Sod3(Node<int> list1, Node<int> list2)
{
Node<int> node1 = list1;
while (node1 != null)
{
bool found = false;
Node<int> node2 = list2;
while ((node2 != null) && (!found))
{
if (node1.GetInfo() == node2.GetInfo())
found = true;
node2 = node2.GetNext();
}
if (!found)
return false;
node1 = node1.GetNext();
}
return true;
}
- 200 -
‫ משה ניסים‬3 ‫הצעה‬
Sod1 ‫ פונקציית‬C# ‫ גרסת‬1 ‫ שאלה‬2013 ‫מבחן‬
public static bool Sod1(List<int> list1, List<int> list2)
{
Node<int> node1 = list1.GetFirst();
Node<int> node2 = list2.GetFirst();
for (int i = 1; i <= 4; i++)
{
if ((node1 == null) || (node2 == null))
return false;
if ((i == 1) || (i == 4))
if (node1.GetInfo() != node2.GetInfo())
return false;
node1 = node1.GetNext();
}
return true;
}
: ‫ בתוכנית הלימודים החדשה‬6 ‫השינוי עפ"י סעיף‬
".‫ ותו לא‬Node ‫ מבנה הנתונים "רשימה" ייוצג וימומש בתוכנית הלימודים ע"י מחלקת‬,‫ ככלל‬-‫"רשימה‬
‫ משום שאוטומטית ניגש‬GetFirst() -‫ אין לנו צורך יותר ב‬list1,list2 ‫ כאשר נפנה למשתנים‬,List -‫ומאחר שהורדנו את ה‬
.‫לראשון‬
public static bool Sod1(Node<int> list1, Node<int> list2)
{
Node<int> node1 = list1;
Node<int> node2 = list2;
for (int i = 1; i <= 4; i++)
{
if ((node1 == null) || (node2 == null))
return false;
if ((i == 1) || (i == 4))
if (node1.GetInfo() != node2.GetInfo())
return false;
node1 = node1.GetNext();
}
return true;
}
2013 ‫ בגרות קיץ תשע"ג‬,‫ סעיף ב‬3 ‫שאלה‬
‫ולרי פקר‬
:‫הניסוח המקורי‬
‫ המכילה מספרים שלמים‬lst ‫ ורשימה‬,1-‫ גדול מ‬,num ‫ פעולה שתקבל מספר שלם‬C#-‫ או ב‬Java-‫) כתוב ב‬1(
.num-‫ שכולם קטנים מ‬,0-‫גדולים מ‬
‫ שאינם מופיעים‬,num-‫ וקטנים מ‬0-‫הפעולה תחזיר רשימה חדשה שאיבריה הם כל המספרים השלמים הגדולים מ‬
.lst ‫ברשימה‬
- 201 -
‫(‪ )2‬מהי סיבוכיות זמן הריצה של הפעולה שכתבת? נמק את תשובתך‪.‬‬
‫הצעה לניסוח חדש שיתאים לתכנית "מבני נתונים"‪:‬‬
‫(‪ )1‬כתוב ב‪ Java-‬או ב‪ C#-‬פעולה שתקבל מספר שלם ‪ ,num‬גדול מ‪ ,1-‬ושרשרת של חוליות ‪ chain‬המכילה‬
‫מספרים שלמים גדולים מ‪ ,0-‬שכולם קטנים מ‪.num-‬‬
‫הפעולה תחזיר הפניה לשרשרת חוליות חדשה שאיבריה הם כל המספרים השלמים הגדולים מ‪ 0-‬וקטנים מ‪,num-‬‬
‫שאינם מופיעים בשרשרת החוליות ‪.chain‬‬
‫(‪ )2‬מהי סיבוכיות זמן הריצה של הפעולה שכתבת? נמק את תשובתך‪.‬‬
‫‪- 202 -‬‬