מבוא למדעי המחשב 2018 תרגול 7 רשימות משורשרות, רקורסיית זנב 1
ראינו בהרצאה רשימות משורשרות רקורסיית זנב 2
בתרגול היום רשימות משורשרות עוד שיטות מחלקה רקורסיית זנב היפוך מחרוזות, חיפוש בינארי 3
רשימות משורשרות 4
תזכורת המחלקות LinkedList, Link public class LinkedList { private static class Link { private Link first; public LinkedList () { first = null; public boolean isempty(){ return first == null; public void addfirst(object element) { if (isempty()) first = new Link(element) else first = new Link(element, first); public void remove(object toremove){ public String tostring(){ public Object get(int index){ public boolean contains(object element){ public Object remove(object element){ 5 private Object data; private Link next; public Link (Object data) { this(data, null); public Link (Object data, Link next) { this.data = data; this.next = next; public object getdata() { return data; public Link getnext() { return next; public Link setnext(link next) { this.next = next; public String tostring(){ return data.tostring; // end of Link class // end of LinkedList class
שיטות נוספות נוסיף את השיטות הבאות במחלקה :LinkedList element) indexof(object החזרת האינדקס בו נמצא המופע הראשון של element או 1- אם הוא לא נמצא ברשימה. index החלפת האיבר במקום ה- set(int index, Object element) עם.element element) add(int index, Object הכנסת איבר למקום ה- index תוך הזזה ימינה של כל אברי הרשימה החל מ- index. element) add(object הוספת איבר לסוף הרשימה. 6
שיטות נוספות indexof public class LinkedList { // returns the index of the first occurrence of the specified element in this list, or -1 if // this list does not contain the element. public int indexof(object element){ if(element == null) throw new NullPointerException(); int index = 0; for(link curr = first; curr!= null ; curr = curr.getnext()){ if( curr.getdata().equals(element) ) return index; else return -1; index = index + 1; 4 5 6 5 7 2 null indexof(5) is 1 7
שיטות נוספות set public class LinkedList { // replaces the element at the specified position in this list with the specified element // throws NullPointerException - if the specified element is null // throws IndexOutOfBoundsException if the index is out of range (index < 0 index >= size()) public Object set(int index, Object element){ if(index < 0 index >= size()) throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size()); if(element == null) throw new NullPointerException(); Link current = first; while (index > 0) { index = index - 1; current = current.getnext(); Object prev = current.getdata(); current.setdata(element); return prev; 4 8 6 5 7 2 null After set(3, 1) 4 8 6 1 7 2 null Returns 5 8
שיטות נוספות add public class LinkedList { // inserts the specified element at the specified position in this list // throws NullPointerException - if the specified element is null // throws IndexOutOfBoundsException if the index is out of range (index < 0 index >= size()) public void add(int index, Object element) { if(index < 0 index > size()) throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size()); if(element == null) throw new NullPointerException(); if(index == 0) addfirst(element); else { Link prev = null ; Link curr = first ; for(int i = 0; i < index; i = i + 1) { prev = curr; curr = curr.getnext(); Link toadd = new Link(element, curr); prev.setnext(toadd); 4 8 6 5 7 2 null After add(3, 1) 4 8 6 1 5 7 2 null 9
שיטות נוספות add public class LinkedList { // appends the specified element to the end of this list // throws NullPointerException - if the specified element is null public boolean add(object element) { if(element == null) throw new NullPointerException(); if(isempty()) addfirst(element); else { Link current = first; while(current.getnext()!= null){ current = current.getnext(); { current.setnext(new Link(element)); return true; 4 8 6 5 7 2 null After add(2) 4 8 6 5 7 2 2 null 10
רשימה כמבנה רקורסיבי כאמור, מעצם הגדרתה של רשימה, ניתן לראות את טבעה הרקורסיבי. הגדרת חוליה ברשימה מכילה מצביע מאותו טיפוס. נראה כיצד ניתן לנצל תכונה זאת. 11
השיטה add במחלקות LinkedList, Link public class LinkedList { private Link first; public LinkedList () { private static class Link { private Object data; private Link next; public Link (Object data) { public Link (Object data, Link next) { public void add(object e) { if (isempty()) addfirst(e); else first.add(e); public void add(object e) { If (next == null) next = new Link(e); else next.add(e); // end of Link class // end of LinkedList class 12
השיטה print במחלקות LinkedList, Link public class LinkedList { private Link first; public LinkedList () { private static class Link { private Object data; private Link next; public Link (Object data) { public Link (Object data, Link next) { public void print() { if (first!= null) first.print(); public void print() { System.out.println(data.toString()); if (next!= null) next.print(); // end of Link class // end of LinkedList class 13
השיטה printbackwards במחלקות LinkedList, Link public class LinkedList { private Link first; public LinkedList () { private static class Link { private Object data; private Link next; public Link (Object data) { public Link (Object data, Link next) { public void printbackwards() { if (first!= null) first.printbackwards(); public void printbackwards() { if (next!= null) next.printbackwards(); System.out.println(data.toString()); // end of Link class // end of LinkedList class 14
אתגר הוסיפו את השיטות הבאות באופן רקורסיבי: element) indexof(object החזרת האינדקס בו נמצא המופע הראשון של element או 1- אם הוא לא נמצא ברשימה. index החלפת האיבר במקום ה- set(int index, Object element) עם.element element) add(int index, Object הכנסת איבר למקום ה- index תוך הזזה ימינה של כל אברי הרשימה החל מ- index. 15
הפסקה 16
רקורסיית זנב 17
רקורסיית זנב רקורסיית זנב היא מקרה מיוחד של רקורסיה, בו הקריאה הרקורסיבית הינה הפעולה האחרונה שהפונקציה הרקורסיבית מבצעת )פרט להשמה ואז.)return 18
היפוך מחרוזות נרצה לכתוב פונקציה המקבלת מחרוזת str ומחזירה מחרוזת הפוכה. ראינו בהרצאה פונקציה הפותרת את הבעיה בלי רקורסיית זנב. 19
reverse from class // gets a string and reverses it public static String reverse(string str){ if(str == null) { throw new NullPointerException(); { String output; if(str.length() == 0) return str; else return reverse(str.substring(1)) + str.charat(0); { מדוע הפונקציה איננה רקורסיית זנב? מה עלינו לעשות בשביל להפוך את הפונקציה לרקורסיית זנב? 20
Reverse - tail recursion // gets a string and flips it public static String reversetail(string str) { if (str == null){ throw new NullPointerException(); return reversetail(str, ""); { // flips str and and concatenate acc from the right public static String reversetail(string str, String acc) { if (str.length() == 0) { return acc; else { return reversetail(str.substring(1), str.charat(0) + acc); { { 21
חיפוש בינארי רקורסיבי בהינתן מערך ממוין של מספרים שלמים ומפתח,key במערך. כיצד נעשה זאת באופן רקורסיבי? נרצה לדעת היכן מיקומו ראשית ניגש לאמצע המערך ונבדוק האם key מצוי שם. אם כן, נחזיר את מיקומו. אחרת, אם ערכו של המיקום האמצעי גדול מ-,key נחפש בחציו הימני של המערך באופן רקורסיבי. אחרת, נחפש בחציו השמאלי של המערך באופן רקורסיבי. מתי נעצור? 22
חיפוש בינארי רקורסיבי key = 13 0 1 2 3 4 5 6 7 8 9 1 2 4 7 9 13 18 23 34 45 output = 5 mid = 4 mid = 5 mid = 7 // returns the index of element key within a sorted array or -1 if key // doesn t appears in arr. public static int recsearch(int key, int[] arr) { if (arr==null arr.length==0 (key<arr[0] key>arr[arr.length])) return -1; return recsearch(key, arr, 0, arr.length-1); 24
חיפוש בינארי רקורסיבי // returns the index of element key within a sorted array in the // index interval [from, till], or -1 if key doesn t appears in arr. public static int recsearch(int key, int[] arr, int from, int till) { if(from <= till) { int mid = (from + till)/2; if(key < arr[mid]) return recsearch(key, arr, from, mid-1); else if(key > arr[mid]) return recsearch(key, arr, mid+1, till); else return mid; return -1; 25
מיון הכנסה רקורסיבי למדנו בכתה איך לבצע מיון הכנסה. ראינו כי המיון מסתמך על הטענה כי כל אברי המערך עד למקום מסוים ממוינים, נסמן מקום זה ב- i. אלגוריתם המיון משמר טענה זו לאורך ריצתו ומנסה להכניס לחלק הממוין של המערך את האיבר המופיע מיקום אחד אחרי המיקום המסוים i, וכאשר מגיע לסוף המערך, מובטח כי המערך ממוין. 26
מיון הכנסה רקורסיבי רעיון האלגוריתם: בהינתן מערך ואינדקס )שעד אליו המערך ממוין(, אם האינדקס הוא סוף המערך, חזור. אחרת: הכנס למערך את הערך הנמצא באינדקס כך שישמר ממוין. מיין את שאר אברי המערך באופן רקורסיבי. 27
// sorts the given array public static void insertionsort(int[] arr) { insertionsort(arr, 0); // begins from index zero מיון הכנסה רקורסיבי // invariant: arr is sorted till indextoinsert. // inserts arr[indextoinsert] into its right position within the // sorted part of arr, and sorts the rest of the array. public static void insertionsort(int[] arr, int indextoinsert) { if(indextoinsert >= arr.length) return; insert(arr, indextoinsert); // insert function we ve seen in ps 3 insertionsort(arr, indextoinsert + 1); 28
סיכום ומשימות תרגלנו רשימות משורשרות רקורסיית זנב משימות עבודת בית 3 הגישו בסיום כל משימה! Quiz 6 29