Transcript 006.class8
מבני נתונים
שיעור – 8חזרה ותרגול.
מערך ,תור ,מחסנית ,רשימה מקושרת,
עצים בינאריים.
Arrays
מערכים
הצהרה על מערך
int[] anArray; // declares an array of integers
byte[] anArrayOfBytes;
short[] anArrayOfShorts;
long[] anArrayOfLongs;
float[] anArrayOfFloats;
double[] anArrayOfDoubles;
boolean[] anArrayOfBooleans;
char[] anArrayOfChars;
String[] anArrayOfStrings;
לשם כך יש לאתחל את,ההצהרה על מערך אינה יצירה של אובייקט מערך
:המערך
anArray = new int[10]; // create an array of integers using “new”
integer מספרים מסוג10 בשלב זה נוצר אובייקט מערך ומוקצה מקום ל
•
•
•
Arrays
מערכים
אתחול ערכי האלמנטים במערך
anArray[0] = 100; // initialize first element
anArray[1] = 200; // initialize second element
anArray[2] = 300; // etc.
•
:גישה אל האלמנטים של המערך ע"י האינדקס
System.out.println("Element 1 at index 0: " + anArray[0]);
System.out.println("Element 2 at index 1: " + anArray[1]);
System.out.println("Element 3 at index 2: " + anAray[2]);
:דרך נוספת ליצירה ואתחול מערך
int[] anArray = {100, 200, 300, 400, 500, 600, 700, 800, 900, 1000};
.בדרך זו אורך המערך נקבע באופן אוטומטי ע"פ מספר האלמנטים בסוגריים
: למשל מערך דו מימדי יוגדר כך,ניתן להגדיר מערכים מרובי מימדים
int [][] 2dArray=new int[5][10];
... דוגמא...למעשה נוצר מערך של מערכים
•
•
•
•
•
מערכים
Arrays
מערך עצמים
•
כאשר אברי המערך הינם עצמים ולא טיפוסים פרימיטיביים יש צורך להקצות כל
! איבר במערך במפורש
•
Line line_arr[];
line_arr = new Line[3];
line_arr[0].draw(); // BUG!
line_arr[0] = new Line();
line_arr
line_arr
line_arr
Array Object
Line Object
Array Object
Line Object
Line Object
תרגיל 3
• יש ליצור מחלקה SortedArrayאשר מחזיקה
מערך של מספרים שלמים intממויין.
• המחלקה תכיל מערך ,שיטת הכנסת איברים
תוך שמירה על סדר המערך ושיטה המחזירה
איבר עם אינדקס מסוים .i
• צור מחלקה Class7עם שיטת mainוהכנס 10
ערכים מהמשתמש ,ולאחר מכן הכנס עוד 5
ערכים אקראיים בתחום בין הערך הקטן ביותר
והגדול ביותר שבמערך.
5
תזכורת- מספר אקראי
Random rnd = new Random();
int from= 10;
int to = 100;
int num= from+rnd.nextInt(to-from+1);
6
מימוש מחסנית ע"י מערך
:) (נניח שמחזיקה ערכים שלמיםStack נגדיר את המחלקה
class public Stack{
private int S[]; //משתנה מחלקה מערך של שלמים
private int num, t;
public Stack(int n){S=new int[n]; num=n; t=-1}// בנאי מאתחל את המערך
public int size(){return t+1;}
public boolean isEmpty(){return t==-1;}
public int top(){
if isEmpty() then throw emptyStackException;//שגיאת מחסנית ריקה
else return S[t];}
public int pop(){
if isEmpty() then throw emptyStackException;//שגיאת מחסנית ריקה
else {int e = S[t]; t = t – 1; return e;}}
public void push(int new){
if size()==num then throw fullStackException;//שגיאת מחסנית מלאה
else {t = t + 1; S[t]=new;}}
•
java - מימוש תור ע"י מערך
:) (נניח שמחזיקה ערכים שלמיםQueue נגדיר את המחלקה
class public Queue{
private int Q[]; //משתנה מחלקה מערך של שלמים
private int N, f, r; //משתנים המצביעים על תחילת וסוף התור
public Stack(int n){Q=new int[n];N=n; f=0; r=0}// בנאי מאתחל את המערך
public int size(){return (N-f+r) mod N;}
public boolean isEmpty(){return f==r;}
public int front(){
if isEmpty() then throw emptyQueueException;//שגיאת תור ריק
else return Q[f];}
public int dequeue(){
if isEmpty() then throw emptyQueueException;//שגיאת תור ריק
else {int e = Q[f]; f = (f+1) mod N; return e;}}
public void enqueue(int new){
if size()==N-1 then throw fullQueueException;//שגיאת תור מלא
else {Q[r]=new; r = (r+1) mod N}}
•
מימוש רשימה מקושרת חד כיוונית
class Node{
public Node next;
public int data;//)ניתן להגדיר כל סוג של נתונים (אובייקט
public Node (int d){
data = d;
next = null;
}
public void displayNode(){
System.out.println(“the data is:” + d);
}
}//end of class Node
class LinkedList
class LinkedList{
private Node first;//מצביע לאיבר הראשון
public LinkedList(){first = null;}
public boolean isEmpty(){return (first==null);}
public void insertFirst(int new){
Node newNode = new Node(new);//יצירת אוביקט
newNode.next = first;//עדכון האיבר הבא
first = newNode;//} עדכון ראש הרשימה
public Node deleteFirst(){
Node temp = first;//שמירת מצביע על האיבר הנמחק
first = first.next;//)עדכון ראש הרשימה (מחיקת הקודם
return temp;//} החזרת האיבר המחוק
public void displayList(){
System.out.println(“The List is: “);
Node current = first;
//מתחיל מהראשון
while(current != null){
//עד סוף הרשימה
current.displayNode();
//מדפיס את הנתון
current = current.next;}} //איבר הבא
}
מימוש עץ בינארי בג'אווה
Node מחלקה
public class Node
{
public int data;
private Node leftChild;
private Node rightChild;
}
מימוש עץ בינארי בג'אווה
Tree מחלקת
public class Tree
{
private Node root;
//Methods
public Node find(int key)
public void insert(int key)
public void delete(int key)
//and more methods…
}
find מימוש רקורסיבי שיטת
public Node findR (int key, Node current){
if(current == null);
return null //לא נמצא
if(key < current.data)
return findR(key, current.leftChild); //בן שמאלי
if(key == current.data)
return current;//איבר מוחזר
if(key > current.data)
return findR(key, current.rightChild); //בן ימני
}
שיטת insert
• פעולת הכנסת איבר היא למעשה זהה לפעולת
חיפוש איבר שאינו קיים.
• בדומה לחיפוש איבר ,בהכנסת איבר חדש
"מטיילים" על העץ עד שמגיעים לעלה ,אשר
הופך להורה של האיבר החדש המוכנס.
• האיבר החדש יהיה בן שמאלי של העלה אם
הוא קטן ממנו ,או בן ימני אם הוא גדול ממנו
(בהתאם לחוקיות הסדר)
סריקת איברי העץ Traversing -
• פעולה זו עוברת על כל איברי העץ ע"פ סדר
מסוים
• פעולת הסריקה פחות שימושית מחיפוש איבר
מסוים
• קיימות 3דרכים פשוטות לסריקת עץ בינרי
– :Inorderסריקה על כל איברי העץ בסדר עולה
– :Preorderכל איבר נסרק לפני הילדים שלו
– :Postorderכל איבר נסרק אחרי הילדים שלו
סריקת Inorder
•
•
•
•
צורת הסריקה השכיחה והשימושית ביותר.
מאפשר ליצור רשימה ממוינת של איברי העץ
מימוש רקורסיבי יעיל לסריקת Inorder
השיטה נקראת עם איבר נוכחי ,כאשר מתחילים
מהשורש ,ומבצעת שלושה פעולות:
.1השיטה קוראת לעצמה (רקורסיה) עם הבן השמאלי
.2מבצעת פעולה על האיבר הנוכחי (פעולת הביקור)
.3השיטה קוראת לעצמה (רקורסיה) עם הבן הימני
סריקת Preorder
• שיטה רקורסיבית לסריקת Preorderנקראת עם
איבר נוכחי החל מהשורש:
.1מבצעת פעולה על האיבר הנוכחי (פעולת הביקור)
.2השיטה קוראת לעצמה (רקורסיה) עם הבן השמאלי
.3השיטה קוראת לעצמה (רקורסיה) עם הבן הימני
• שיטת סריקה זו שימושית כאשר יש להדפיס
מסמך עם פרקים ותתי פרקים ע"פ הסדר
סריקת Postorder
• שיטה רקורסיבית לסריקת Postorderנקראת עם
איבר נוכחי החל מהשורש:
.1השיטה קוראת לעצמה (רקורסיה) עם הבן השמאלי
.2השיטה קוראת לעצמה (רקורסיה) עם הבן הימני
.3מבצעת פעולה על האיבר הנוכחי (פעולת הביקור)
• שיטת סריקה זו שימושית כאשר יש לחשב נפח
קבצים של תיקיות ותתי תיקיות.
תרגיל 2
•
•
•
•
•
•
יש לבנות את מחלקות תור ,מחסנית ,רשימה מקושרת חד
כיוונית ועץ בינארי.
בהמשך לשיטת mainבמחלקה Class7צור מחסנית ,תור,
רשימה מקושרת ועץ בינארי והכנס לתוכם את האיברים של
המערך הממויין ע"פ הסדר.
הדפס את איברי הרשימה המקושרת.
העבר 5איברים מהמחסנית לתור ,ואח"כ 6איברים מהתור
למחסנית.
מחק את כל איברי המבנה המכיל מספר רב יותר של איברים
(התור או המחסנית) תוך הדפסתם.
הצג את איברי העץ ע"פ שלושת דרכי הסריקה (יש לממש
סריקה עם הדפסת האיברים)
19
תרגיל 3
נתון עץ בינארי כלשהו בעל nצמתים .בכל צומת יש:
•
•
•
.1
.2
.3
מפתח – מספר טבעי כלשהו
שני מצביעים לבנים
שדה נוסף המכיל מספר טבעי (מותר להשתמש בו לביצוע המשימה
הנדרשת)
הצע אלג' לחישוב ערכו של המסלול הכבד ביותר בעץ מהשורש
לעלה .המסלול הכבד הינו המסלול שסכום המפתחות בצמתים שלו
הוא מקסימלי.
יש להדפיס את הערכים לאורך מסלול זה.
סיבוכיות זמן נדרשת – )O(n
דוגמא:
100+20
20
50
0
100
פתרון
חישוב הערך:
•
•
מחשבים באופן רקורסיבי עבור שני תת-העצים ומוסיפים את ערך השורש
למקסימום מבינהם.
הדפסת המסלול:
•
•
•
בשדה הנוסף בכל צומת נרשום 0אם המקסימום התקבל מתת-העץ
השמאלי ,ו 1 -אם מהימני.
לאחר חישוב הערך נדפיס לאורך המסלול המסומן את ערכיו.