משרד החינוך המזכירות הפדגוגית – אגף מדעים הטכניון – מכון טכנולוגי לישראל מרכז המורים הארצי למדעי המחשב מינהלת מל"מ ,המרכז הישראלי לחינוך מדעי טכנולוגי ע"ש עמוס דה שליט פיתוח: משתתפי קורס מורים מובילים תשע"ה פרויקט 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 L210 , 11 , 19 , 7 , 100 L3 שלב :2 L210 , 11 , 19 , 7 , 100 L3 19 שלב :3 L210 , 19, 7 , 100 L3 19 שלב :4 L210 , 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 -
© Copyright 2024