תרגול 12: Iterator מחסנית תור 1. מחסנית (stack) מחסנית (stack) היא...

Preview:

Citation preview

12תרגול :

Iterator מחסנית תור

1

( stack )מחסנית

( היא מבנה נתונים שמזכיר stack )מחסנית•מחסנית של רובה: האיבר שנכנס ראשון למחסנית

(.LIFO - Last In First Outיוצא ממנה אחרון )ניתן לראות במחסנית קופסה סגורה בעלת פתח •

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

. LIFOאחרון יוצא ראשון- מחסנית היא שימושית כאשר יש צורך•

לשמור נתונים בסדר מסוים ולשלוף אותם בסדר הפוך.

2

public interface Stack {/** * push - adds an element to the stack. * @param o the elemented to be inserted to the stack. */

public void push (Object o); /** * pop - removes an element form the stack (LIFO order). * @return the element from the top of the stack. */ public Object pop (); /** * isEmpty - checks if the stack is empty or not. * @return true if there is no more elements in the stack. */ public boolean isEmpty();}

ממשק

3

מימוש מחסנית בעלת ע"י מערך

import java.util.EmptyStackException;

public class StackAsArray implements Stack {/* Defines the initial capacity of a stack */

private static final int INITIAL_CAPACITY = 5;/* Defines the capacity extension of a stack when it is full */

private static final int CAPACITY_EXTENSION = 5;

protected Object[] elements;

protected int size;/* Creates a new stack.*/

public StackAsArray)( {

elements = new Object[INITIAL_CAPACITY];

size = 0;

}

4

מימוש מחסנית ע"י מערךpublic void push)Object o( {

if )size >= elements.length(

extend)(;

elements[size] = o;

size = size + 1;

}

public Object pop)( {

if )size == 0(

throw new EmptyStackException)(;

size = size - 1;

return elements[size];

}

public boolean isEmpty)( {

return size == 0;

}

מימוש מחסנית ע"י מערךprivate void extend)( {

/* Create a new array with the new size */

Object[] tmpArray = new Object[elements.length + CAPACITY_EXTENSION]; /* Copy the old elements to the new array */

for )int i = 0; i < elements.length; i=i+1(

tmpArray[i] = elements[i]; /* Replace the elements array with the new one */

elements = tmpArray;

}

}

Iterator

7

Iterator

( הדרושים לתכנית מחשב dataמידע ונתונים )•(. data structure )מבנה נתוניםנשמרים בתוך

על מבנה נתונים יש צורך לבצע מספר פעולות, •.כמו הכנסת נתונים והוצאת נתונים

אחת הדרכים להוציא נתונים היא לעבור על •.אוסף הנתונים פריט-מידע אחר פריט-מידע

האחריות על מבנה הנתונים היא של המתכנת •שלו, ברצוננו להקל על המשתמש במבנה

הנתונים ככל הניתן.8

Iteratorנרצה שתכונה זו תהיה משותפת למבני נתונים רבים, •

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

JAVA. ב-Iterable, ובאנגלית: פריט-אחר-פריט

קיים הממשק:

9

public interface Iterable { /** * Returns an iterator over a set of elements. * * @return an Iterator. */ Iterator iterator();}

Iterator

יהיה לנו אובייקט שיעזור בתהליך. אובייקט זה •יעבור על אוסף הנתונים פריט אחר פריט, לפי

. Iteratorסדר מסוים, ובאנגלית:

מוגדר ממשק לעבודה עם אובייקט כזה:JAVAב-

10

public interface Iterator {boolean hasNext();

Object next();

void remove();}

public interface Iterator {/** * Returns true if the iteration has more elements. * @return true if the iterator has more elements. */boolean hasNext();

/** * Returns the next element in the iteration. * @return the next element in the iteration. * @exception NoSuchElementException iteration has no more elements. */Object next();

/** * Removes from the underlying collection the last element returned by the * iterator (optional operation) * @exception UnsupportedOperationException if the "remove" * operation is not supported by this Iterator. * * @exception IllegalStateException if the "next" method has not * yet been called, or the "remove" method has already * been called after the last call to the "next" * method. */void remove();

}

11

Iteratorשימוש ב-, Iteratorכך שתתמוך ב-StackAsArrayבהמשך נראה כיצד להפוך את המחלקה

Iteratorכרגע נניח שהמחלקה כבר תומכת בו, ועל סמך זאת נעשה שימוש ב-מממשת את StackAsArray , שמובטחת לנו מכיוון ש-)(iteratorשמתקבל מהשיטה

Iterable.

12

public static void main(String[] args) {StackAsArray stack= new StackAsArray();

stack.push("Tasty"); stack.push(“Are");

stack.push("Shnitsels");

Iterator it = stack.iterator();while (it.hasNext()) {

Object currentData = it.next();System.out.print(currentData);if (it.hasNext())

System.out.print(", ");}System.out.println();

}

StackAsArray עבור Iteratorמימוש ה-public class StackAsArrayIterator implements Iterator {

private int currentIndex;private Object[] Array;

public ArrayIterator(int size, Object[] Array) { currentIndex = size;this.Array = Array;

}public boolean hasNext() {

return (currentIndex != 0);}

public Object next() {if (!hasNext()) {

throw new NoSuchElementException();}currentIndex = currentIndex -1;Object data = arry[currentIndex];return data;

}public void remove() {

throw new UnsupportedOperationException();}

} 13

במחלקה Iteratorעתה נראה כיצד נתמוך ב LinkedList:

14

public interface Iterable { /** * Returns an iterator over a set of elements. * * @return an Iterator. */ Iterator iterator();}

LinkedList במחלקה Iterableמימוש ה-

במחלקה Iterableמימוש ה-StackAsArray

עכשיו כל מה שנותר לעשות הוא לממש את השיטה •iterator)( של הממשק Iterable ב StackAsArray:

public class StackAsArray implements Iterable{

protected Object[] elements;protected int size;

/* Creates a new stack.*/

public StackAsArray() {elements = new Object[INITIAL_CAPACITY];size = 0;

}…

public Iterator iterator(){return new StackAsArrayIterator(elements,size);

}}

הערות• Iterator מניח שלא נעשה שינוי באוסף עליו הוא עובר

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

מחוייבת לזרוק את החריגה next השיטה )(•NoSuchElementException במידה ואין יותר אלמנטים

נוודא ש )(nextבאוסף. ) אם לפני כל קריאה ל-hasNext)( החזיר true.)אז לא נתקל בחריגה זו

נזרקת UnsupportedOperationExceptionהחריגה: •כאשר אנו מחוייבים להכריז שיטה מסויימת )למשל כי

היא חלק מממשק( במחלקה שלנו, אך אנו לא תומכים בשיטה זו. לכן בגוף השיטה נזרוק את החריגה.

16

דוגמה

נרצה לקלוט מהמשתמש מספר מחרוזות ורק

כאשר הוא יסיים להקליד )למשל ע"י זיהוי שורה

ריקה( נדפיס בחזרה את כל המחרוזות ההפך

מסדר ההכנסה.

17

המשךimport java.util.Scanner;…public static void main(String args[]) {

Scanner sc = new Scanner(System.in);Queue s = new stackAsArray();

System.out.println("Insert few lines … ");

while (sc.hasNextLine()) {String line = sc.nextLine();s.push( line );

}

System.out.println("Printing all the lines back! ");

while (!s.isEmpty()) {System.out.println(s.pop());

}}

18

s ומחזירה העתק של המחסנית s מקבלת כארגומנט מחסנית copyהשיטה זהה.sכאשר יש לשמור על סדר האיברים במחסנית המועתקת וב-

לא תמיד נצטרך לדעת כיצד מימשו את הממשק– העתק

מחסניתpublic static Stack copy(Stack s){

}

19

s ומחזירה העתק של המחסנית s מקבלת כארגומנט מחסנית copyהשיטה זהה.sכאשר יש לשמור על סדר האיברים במחסנית המועתקת וב-

לא תמיד נצטרך לדעת כיצד מימשו את הממשק– העתק

מחסניתpublic static Stack copy(Stack s){

Stack temp = new StackImpl();Stack ans = new StackImpl();while (!s.isEmpty()) {

temp.push(s.pop());}while (!temp.isEmpty()) {

Object o = temp.pop();ans.push(o);s.push(o);

}return ans;

}

20

Queueתור -

הוא מבנה נתונים (Queue) תור •המזכיר תור של בני אדם: האיבר

שנכנס ראשון לתור- יוצא ממנו ראשון. 2ניתן לראות כקופסה סגורה בעלת •

פתחים: פתח הכנסה ופתח יציאה. FIFOאיבר שנכנס ראשון יוצא ראשון •

(FIFO - First In First Out) .שימושים: ניהל תהליכים ע"י מערכת •

ההפעלה, ניהול תור בבית מרקחת, ...

21

public interface Queue{ /** * isEmpty - checks if the queue is empty or not. * @return true if the queue is empty */ public boolean isEmpty(); /** * dequeue - removes an object from the head of the queue. * (FIFO order) * @return the next object in the queue. */ public Object dequeue(); /** * enqueue - inserts an object into the queue. * @param o the object to be enqueued. */ public void enqueue(Object o);}

22

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

בשיטה זו.

דוגמה

public static void reverse(Queue q){ Object o;

}

23

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

בשיטה זו.

דוגמה

public static void reverse(Queue q){ Object o;if(!q.isEmpty()){

o=q.deueue();reverse(q);q.enqueue(o);

}}

24

תרגיל

המממשת את StackAsArrayהוסיפו למחלקה לסינון איברים filter את השיטה Iterableהממשק

העונים על תנאי מתוך כלל איברי במחסנית.

Stack filter(Filter f)

.Filter fהתנאי ע"פ מסננים האיברים הוא

, accept המכיל שיטה אחת והיא Filterנגדיר ממשק המקבלת אובייקט ומחליטה האם הוא עובר את

הסינון או לא.

25

public interface Filter {/** * accept – defines the filtration criterion. * @param o the object to be examined. * @return true if the object should not be * filtered out. */public boolean accept(Object o);

}

, המשאיר רק את המחרוזות הלא String פשוט עבור המחלקה Filterאנו נממש ריקות:

public class EmptyStringFilter implements Filter {public boolean accept(Object o) {

boolean ans = false;if (o instanceof String) {

String s = (String) o;ans = s.length() > 0;

}return ans;

} }

 26

public stackAsArray filter(Filter filter) {stackAsArray filteredStack = new stackAsArray() ;Iterator it = this.iterator(); while (it.hasNext()) {

Object data = it.next();if(filter.accept(data)) {

filteredStack.push(data) ;}

}return filteredStack;

}

: StackAsArray כל שנותר הוא לממש את השיטת הסינון ב-השיטה מקבלת כקלט מסנן, ומחזיר מחסנית חדשה שתכיל את כל

.אברי המחסנית הנוכחית שעברו את המסנן

27

Recommended