Download as pdf or txt
Download as pdf or txt
You are on page 1of 17

‫סיכום מבני נתונים ‪C#‬‬

‫רשימה – שרשרת חוליות‬

‫ממשק המחלקה ‪Node‬‬


‫סיבוכיות‬ ‫חתימת הפעולה‬ ‫תיעוד הפעולה‬
‫)‪o(1‬‬ ‫)‪Node(T value‬‬ ‫הפעולה בונה ומחזירה חוליה שהערך שלה הוא ‪ value‬ואין‬
‫לה חוליה עוקבת‬
‫)‪o(1‬‬ ‫)‪Node(T value, Node<T> next‬‬ ‫הפעולה בונה ומחזירה חוליה שהערך שלה הוא ‪value‬‬
‫והחוליה העוקבת לה היא החוליה ‪next‬‬
‫)‪o(1‬‬ ‫)(‪T GetValue‬‬ ‫הפעולה מחזירה את הערך של החוליה הנוכחית‬
‫)‪o(1‬‬ ‫)(‪Node<T> GetNext‬‬ ‫הפעולה מחזירה את החוליה העוקבת לחוליה הנוכחית‬
‫)‪o(1‬‬ ‫)‪void SetValue(T value‬‬ ‫הפעולה קובעת את ערך החוליה הנוכחית להיות ‪value‬‬
‫)‪o(1‬‬ ‫)‪void SetNext(Node<T> next‬‬ ‫הפעולה קובעת את החוליה העוקבת לחוליה הנוכחית להיות‬
‫החוליה ‪next‬‬
‫)‪o(1‬‬ ‫)(‪bool HasNext‬‬ ‫הפעולה מחזירה ‪ true‬אם לחוליה הנוכחית יש חוליה עוקבת‪,‬‬
‫או ‪ false‬אם זו החוליה האחרונה בשרשרת‪.‬‬
‫)‪o(1‬‬ ‫)(‪string ToString‬‬ ‫הפעולה מחזירה מחרוזת המתארת את החוליה‬

‫בניית רשימה‬

‫;)‪Node<int> first = new Node>int>(value‬‬ ‫מצביע לחוליה הראשונה‪ ,‬יש לתת לה ערך בבנייה‪//‬‬

‫;‪Node<int> last = first‬‬ ‫מצביע לחוליה האחרונה ברשימה– מיועד להוספת חוליות לסוף הרשימה‪//‬‬

‫)‪for (int i = 0; i < numElements - 1; i++‬‬

‫{‬

‫הוספת חוליות לסוף הרשימה ‪last.SetNext(new Node<int> (value)); //‬‬

‫;)(‪last = last.GetNext‬‬ ‫קידום המצביע לחוליה שנבנתה‪ -‬החוליה האחרונה‪//‬‬

‫}‬

‫בניית רשימה בסדר הפוך‬

‫‪Node<int> first = null‬‬ ‫מצביע לחוליה הראשונה‪//‬‬

‫)‪for (int i = 0; i < numElements ; i++‬‬

‫{‬

‫הוספת חוליות לתחילת הרשימה‪first= new Node<int> (value, first); //‬‬

‫}‬

‫‪1‬‬
‫סריקת רשימה‬
‫סכימת אברי רשימה‬

int sum=0;

Node<int> p=first;

while(p!=null)

sum+=p.GetValue();

p=p.GetNext();

‫הוספת חוליה לרשימה‬


)first ‫הוספת חוליה לראש הרשימה (ראש הרשימה‬

Node<int> q = new Node<int> (value); //‫בניית החוליה החדשה‬

q.SetNext(first);

first = q;

p ‫הוספת חוליה אחרי חוליה‬

Node<int> q = new Node<int> (value); //‫בניית החוליה החדשה‬

q.SetNext(p.GetNext());

p.SetNext(q);

‫הוצאת חוליה מרשימה‬


)first ‫הוצאת חוליה מראש הרשימה (ראש הרשימה‬

Node<int> del = first;

first = first.GetNext();

del.SetNext(null);

p ‫הוצאת חוליה אחרי החוליה‬

Node<int> del =p.GetNext();

p.SetNext(del.GetNext());

del.SetNext(null);

2
‫דגשים‪:‬‬

‫אין לאבד את המצביע לראש‪ .‬ע"מ לסרוק רשימה יש להעמיד מצביע נוסף ואיתו לסרוק את הרשימה‪.‬‬ ‫‪‬‬
‫(אם סורקים רשימה בפעולה לא חובה לשמור את המצביע לראש משום שהוא שמור ב‪)Main‬‬
‫אם משנים את ראש הרשימה בפעולה (הוספה‪/‬הוצאת חוליה מהראש)‪ -‬הפעולה חייבת להחזיר את ראש‬ ‫‪‬‬
‫הרשימה החדש‪.‬‬
‫אם סורקים רשימה עד הסוף (כולל האיבר האחרון) הלולאה תהיה ‪while(p!=null) :‬‬ ‫‪‬‬
‫ואם סורקים רשימה לא כולל האיבר האחרון הלולאה תהיה‪while(p.HasNext()) :‬‬

‫דוגמאות‪:‬‬

‫‪ .1‬פעולה המקבלת רשימה ‪ list‬שאינה ריקה ומספר שלם ‪ .num‬הפעולה מעדכנת את הרשימה כך שאחרי כל איבר‬
‫ברשימה יתווסף איבר חדש כך שסכום כל זוג איברים עוקבים יהיה שווה ל‪.num-‬‬

‫)‪public static void CouplesList(Node<int> list, int num‬‬


‫{‬ ‫הפעולה יכולה להיות ‪ void‬כיון שראש‬
‫;‪Node<int> p‬‬ ‫הרשימה לא משתנה‬
‫)‪while(list!=null‬‬
‫{‬
‫;))(‪p = new Node<int>(num - list.GetValue‬‬
‫;))(‪p.SetNext(list.GetNext‬‬
‫;)‪list.SetNext(p‬‬
‫;)(‪list = p.GetNext‬‬ ‫לולאה שעוברת על כל הרשימה ואחרי כל‬
‫חוליה מוסיפה עוד חוליה כך שסכומן יהיה‬
‫}‬
‫שווה ל‪.num-‬‬
‫}‬

‫‪3‬‬
.num ‫ הפעולה מוציאה מהרשימה את כל החוליות שערכן‬,num ‫ פעולה המקבלת רשימה של מספרים שלמים ומספר‬.2

‫דרך א‬
public static Node<int> RemoveNum(Node<int> list, int num)
{ ‫הפעולה חייבת להחזיר את החוליה‬
Node<int> p,head; ‫ כיון‬,‫שבראש הרשימה לאחר ההוצאה‬
while (list!=null && list.GetValue()==num) .‫שיכול להיות שראש הרשימה משתנה‬
{
p = list;
list = list.GetNext();
p.SetNext(null); ‫לולאה להוצאת כל האיברים מראש‬
} num-‫הרשימה ששווים ל‬
head = list;
while(list.HasNext())
{
if(list.GetNext().GetValue()==num)
{
p = list.GetNext(); ‫לולאה להוצאת כל האיברים משאר‬
list.SetNext(p.GetNext()); num-‫הרשימה ששווים ל‬
p.SetNext(null);
}
else
list = list.GetNext();
}
return head;
}

‫דרך ב‬

public static Node<int> RemoveNum2(Node<int> list, int num)


{
Node<int> p, del;
while (list.HasNext())
{
if (list.GetNext().GetValue() == num)
{ ‫לולאה להוצאת כל האיברים מהרשימה מלבד‬
p = list.GetNext(); num-‫האיבר שבראש הרשימה ששווים ל‬
list.SetNext(p.GetNext());
p.SetNext(null);
}
else
list = list.GetNext();
}
if (list.GetValue() == num)
{ num-‫הוצאת האיבר מראש הרשימה במידה ושווה ל‬
del = list;
list = list.GetNext();
del.SetNext(null);
}
return list;
}

4
‫רשימה של עצמים‬
:‫דוגמה‬
NumTav .char ‫ בונה ומחזירה רשימה של‬,NumTav ‫פעולה המקבלת רשימה מטיפוס‬
char Tav ‫ תווים של‬num ‫ יוכנסו לרשימה החדשה ברצף‬,‫עבור כל איבר מהרשימה המקורית‬
int num .tav

.‫ בתנאי נפרד‬-‫ בניית החוליה הראשונה ברשימה בתוך הלולאה‬-‫דרך א‬

public static Node<char> BuildCharList1(Node<NumTav> numTavList)


{
Node<char> charList = null,last=null;

while (numTavList != null)


{
for (int i = 0; i < numTavList.GetValue().GetNum(); i++)
{
char value = numTavList.GetValue().GetTav();
if (charList == null)
‫בניית החוליה הראשונה ברשימה‬
{
charList = new Node<char>(value);
last = charList;
}
else
{
last.SetNext(new Node<char>(value));
last = last.GetNext();
}
}
numTavList = numTavList.GetNext();
}
return charList;
}

)‫ בניית החוליה הראשונה ברשימה מחוץ ללולאה (איבר סתמי שבסוף הפעולה מוציאים מהרשימה‬-'‫דרך ב‬

public static Node<char> BuildCharList2(Node<NumTav> numTavList)


{
Node<char> charList = new Node<char>(' '); ‫בניית החוליה הראשונה ברשימה עם ערך סתמי‬
Node<char> last = charList;
while(numTavList!=null)
{
for(int i=0; i<numTavList.GetValue().GetNum();i++)
{
last.SetNext(new Node<char>(numTavList.GetValue().GetTav()));
last = last.GetNext();
}
numTavList = numTavList.GetNext();
}
return charList.GetNext();
}

5
‫מחסנית‬

‫מחסנית היא מבנה נתונים מופשט המתנהל בצורה של ‪.LIFO- Last In First Out‬‬
‫ממשק המחלקה ‪Stack‬‬
‫סיבוכיות‬ ‫חתימת הפעולה‬ ‫תיעוד הפעולה‬
‫)‪o(1‬‬ ‫)(‪Stack‬‬ ‫פעולה בונה המחזירה מחסנית ריקה‬
‫)‪o(1‬‬ ‫)‪void Push(T x‬‬ ‫הפעולה מקבלת ערך ‪ x‬ומכניסה אותו לראש המחסנית‬
‫)‪o(1‬‬ ‫)(‪T Pop‬‬ ‫הפעולה מוציאה ומחזירה את הערך הנמצא בראש המחסנית‬
‫)‪o(1‬‬ ‫)(‪T Top‬‬ ‫הפעולה מחזירה את הערך הנמצא בראש מחסנית‬
‫)‪o(1‬‬ ‫)(‪bool IsEmpty‬‬ ‫הפעולה מחזירה ‪ true‬אם המחסנית ריקה ו‪ false‬אחרת‬
‫)‪o(n‬‬ ‫)(‪string ToString‬‬ ‫הפעולה מחזירה מחרוזת המתארת את המחסנית‬

‫כללים חשובים‪:‬‬

‫סריקת מחסנית נעשית ע"י מחסנית נוספת (או באמצעות רקורסיה)‪.‬‬ ‫‪‬‬
‫יש לשים לב שבסוף הפעולה המחסנית חוזרת לקדמותה (כל האיברים חוזרים חזרה למחסנית) לפני ה‪. return‬‬ ‫‪‬‬

‫דוגמאות‪:‬‬
‫‪ .1‬פעולה המונה את מספר האיברים במחסנית‪.‬‬
‫)‪public static int NumElements(Stack<int> s‬‬
‫{‬
‫;‪int count = 0‬‬
‫;)(>‪Stack<int> temp = new Stack<int‬‬
‫))(‪while (!s.IsEmpty‬‬
‫{‬ ‫העברת האיברים מהמחסנית למחסנית‬
‫;‪count++‬‬ ‫‪ temp‬תוך ספירתם‬
‫;))(‪temp.Push(s.Pop‬‬
‫}‬
‫))(‪while (!temp.IsEmpty‬‬
‫;))(‪s.Push(temp.Pop‬‬
‫;‪return count‬‬
‫}‬

‫‪ .2‬פעולה המקבלת מחסנית של מספרים שלמים ומספר ובודקת האם המספר נמצא במחסנית‪.‬‬

‫)‪public static bool IsExist(Stack<int> s,int num‬‬


‫{‬
‫;‪bool found = false‬‬
‫;)(>‪Stack<int> temp = new Stack<int‬‬
‫)‪while (!s.IsEmpty() && !found‬‬
‫{‬
‫)‪if (s.Top() == num‬‬ ‫אם צריך לשמור על איברי המחסנית‪ ,‬לא‬
‫ניתן לכתוב ;‪ return true‬במידה ומצאנו‬
‫;‪found = true‬‬
‫משום שיש להחזיר קודם ה ‪ return‬את‬
‫;))(‪temp.Push(s.Pop‬‬
‫האיברים לתוך המחסנית‪.‬‬
‫}‬
‫))(‪while (!temp.IsEmpty‬‬
‫;))(‪s.Push(temp.Pop‬‬
‫;‪return found‬‬
‫}‬ ‫‪6‬‬
‫‪ .3‬פעלה המקבלת מחסנית ובודקת האם המחסנית ממוינת‬

‫)‪public static bool IsSort(Stack<int> s‬‬


‫{‬
‫;‪bool flag = true‬‬
‫;‪int first‬‬
‫;)(>‪Stack<int> temp = new Stack<int‬‬
‫אם כבר הוצא איבר מהמחסנית‪ ,‬יש‬
‫)‪while(!s.IsEmpty() && flag‬‬ ‫לבדוק שוב שהמחסנית לא ריקה לפני‬
‫שבודקים את הבא (אחרת יגרור שגיאת‬
‫{‬
‫ריצה על האיבר האחרון)‪.‬‬
‫;)(‪first=s.Pop‬‬
‫))(‪if (!s.IsEmpty() && first > s.Top‬‬
‫;‪flag=false‬‬
‫;)‪temp.Push(first‬‬
‫}‬
‫))(‪while (!temp.IsEmpty‬‬
‫;))(‪s.Push(temp.Pop‬‬
‫;‪return flag‬‬
‫}‬

‫רקורסיה על מחסנית‬
‫דגשים‪:‬‬

‫לפני הקריאה הרקורסיבית יש לשים לב שהוצא איבר מהמחסנית‪.‬‬ ‫‪‬‬


‫אם לא הוצא איבר מהמחסנית‪ ,‬המחסנית תישלח שוב באותה צורה לפעולה ללא שום שינוי מה שיביא לשגיאת‬
‫ריצה‪.‬‬
‫המנגנון הרקורסיבי מאפשר להחזיר חזרה את איברי המחסנית ובכך חוסך את השימוש במחסנית עזר‪.‬‬ ‫‪‬‬
‫דוגמאות‬
‫‪ .4‬פעולה רקורסיבית המקבלת מחסנית של מספרים שלמים ומחזירה את סכום אברי המחסנית‬
‫דרך א‪ -‬ללא שמירת אברי המחסנית‬
‫)‪public static int SumStack(Stack<int> s‬‬
‫{‬ ‫הזימון הרקורסיבי‬
‫מתבצע לאחר הוצאת‬
‫))(‪if (s.IsEmpty‬‬
‫האיבר מהמחסנית‪.‬‬
‫;‪return 0‬‬ ‫אם זה היה הפוך‪-‬‬
‫;)‪return s.Pop() + SumStack(s‬‬ ‫היה גורר שגיאת‬
‫}‬ ‫ריצה‬

‫דרך ב‪ -‬עם שמירה על אברי המחסנית‬

‫)‪public static int SumStack2(Stack<int> s‬‬


‫{‬ ‫אם רוצים לשמור על אברי המחסנית‪ ,‬יש‬
‫))(‪if (s.IsEmpty‬‬ ‫לשמור את האיבר שהוצא מהמחסנית‬
‫;‪return 0‬‬ ‫בתוך משתנה ולאחר החזרה‬
‫;)(‪int x = s.Pop‬‬ ‫מהרקורסיה להחזיר אותו‬
‫;)‪int result=x + SumStack2(s‬‬
‫;)‪s.Push(x‬‬
‫;‪return result‬‬
‫}‬
‫‪7‬‬
‫ פעולה רקורסיבית גנרית המקבלת מחסנית של מספרים שלמים ומספר ובודקת האם המספר נמצא המחסנית‬.5
‫ ללא שמירת אברי המחסנית‬-‫דרך א‬

public static bool IsExist<T>(Stack<T> s, T value)


{
if (s.IsEmpty())
return false;
return s.Pop().Equals(value)|| IsExist(s, value);
} ‫ לא ניתן‬,‫מכיון שהערך גנרי‬
== ‫לבצע השוואה באמצעות‬

‫ עם שמירה על אברי המחסנית‬-‫דרך ב‬

public static bool IsExist2<T>(Stack<T> s, T value)


{
if (s.IsEmpty())
return false;
if (s.Top().Equals(value))
return true;
T num = s.Pop();
bool found= IsExist2(s, value);
s.Push(num);
return found;
}

8
‫תור‬

‫תור הוא מבנה נתונים מופשט המתנהל בצורה של ‪.FIFO- First In First Out‬‬
‫ממשק המחלקה ‪Queue‬‬
‫סיבוכיות‬ ‫חתימת הפעולה‬ ‫תיעוד הפעולה‬
‫)‪o(1‬‬ ‫)(‪Queue‬‬ ‫פעולה בונה המחזירה תור ריק‬
‫)‪o(1‬‬ ‫)‪void Insert(T x‬‬ ‫הפעולה מקבלת ערך ‪ x‬ומכניסה אותו לסוף התור‬
‫)‪o(1‬‬ ‫)(‪T Remove‬‬ ‫הפעולה מוציאה ומחזירה את הערך הנמצא בראש התור‬
‫)‪o(1‬‬ ‫)(‪T Head‬‬ ‫הפעולה מחזירה את הערך הנמצא בראש התר‬
‫)‪o(1‬‬ ‫)(‪bool IsEmpty‬‬ ‫הפעולה מחזירה ‪ true‬אם התור ריק ו‪ false‬אחרת‬
‫)‪o(n‬‬ ‫)(‪string ToString‬‬ ‫הפעולה מחזירה מחרוזת המתארת את התור‬

‫כללים חשובים‪:‬‬

‫סריקת תור נעשית ע"י תור נוסף או באמצעות העברת האיברים לסוף התור או באמצעות רקורסיה‪.‬‬ ‫‪‬‬
‫בסריקת תור ע"י העברת האיברים לסוף התור‪ ,‬יש צורך להכניס לתור ערך דמה (דגל) –ערך שידוע שלא נמצא‬ ‫‪‬‬
‫בתור ע"מ שיאפשר לזהות כי סרקנו את כל אברי התור‪ .‬משום כך דרך זו לא תמיד אפשרית (תמיד ניתן לסרוק‬
‫תור ע"י תור עזר)‪.‬‬
‫סריקת תור ברקורסיה תהפוך את סדר האיברים בתור‪.‬‬ ‫‪‬‬
‫יש לשים לב שבסוף הפעולה התור חוזר לקדמותו (כל האיברים חוזרים חזרה לתור) לפני ה‪. return‬‬ ‫‪‬‬

‫‪9‬‬
‫דוגמאות‬
:‫ פעולה המקבלת תור של מספרים שלמים ומונה את מספר האיברים בתור באמצעות שלוש השיטות‬.1
‫ מניית מספר האיברים בתור באמצעות תור עזר‬

public static int NumElements1(Queue<int> q)


{
int count = 0;
Queue<int> temp = new Queue<int>();
while(!q.IsEmpty())
{
count++;
temp.Insert(q.Remove());
}
while (!temp.IsEmpty())
q.Insert(temp.Remove());
return count;
}

‫מניית מספר האיברים בתור באמצעות העברה לסוף התור‬ 

public static int NumElements2(Queue<int> q,int dummy)


{
int count = 0;
q.Insert(dummy);
‫ערך שידוע שלא נמצא בתור‬
while (q.Head()!=dummy)
{
count++;
q.Insert(q.Remove());
}
q.Remove();
return count; ‫בסוף יש להוציא את האיבר שהוכנס‬
}

‫מניית מספר האיברים בתור באמצעות רקורסיה‬ 

public static int NumElements3(Queue<int> q)


{
if (q.IsEmpty())
return 0; ‫ לאחר הזימון‬.‫הוצאת האיבר מראש התור‬
int x = q.Remove(); .‫ הוא מוחזר לראש התור‬,‫הרקורסיבי‬
int count = 1 + NumElements3(q);
q.Insert(x); – ‫יוצא שהראשון להיכנס לתור הוא האחרון שהוצא‬
return count; ‫גורם להיפוך התור‬
}

10
.‫ פעולה המקבלת תור של מספרים שלמים ומספר ובודקת האם המספר נמצא בתור‬.2

public static bool IsExist1(Queue<int> q, int num)


{
bool found = false;
‫ לא ניתן‬,‫אם צריך לשמור על איברי התור‬
Queue<int> temp = new Queue<int>();
‫ במידה ומצאנו‬return true; ‫לכתוב‬
while(!q.IsEmpty())
‫ את‬return ‫משום שיש להחזיר קודם ה‬
{
.‫האיברים לתוך התור‬
if (q.Head() == num)
found = true;
temp.Insert(q.Remove());
}
while (!temp.IsEmpty())
q.Insert(temp.Remove());
return found;
}

‫ עוצרים את לולאת החיפוש ובלולאה נוספת מעבירים את שאר‬,‫ לאחר שנמצא האיבר שאותו מחפשים‬:‫דרך נוספת‬
)‫האיברים הנמצאים בתור (ע"מ שסדר האיברים בתור לא ישתנה‬

public static bool IsExist2(Queue<int> q, int num)


{
bool found = false;
Queue<int> temp = new Queue<int>();
while (!q.IsEmpty() && !found)
{ ‫עצירת לולאת החיפוש באמצעות‬
if (q.Head() == num) .found ‫המשתנה הבוליאני‬
found = true;
temp.Insert(q.Remove());
}
while (!q.IsEmpty())
temp.Insert(q.Remove());
‫לולאה להעברת האיברים בתור שנמצאים‬
while (!temp.IsEmpty()) .‫אחרי האיבר שאותו מחפשים‬
q.Insert(temp.Remove()); )‫(ע"מ לשמור על סדר האיברים המקורי‬
return found;
}

11
‫עץ בינארי‬
‫ממשק המחלקה ‪BinNode‬‬
‫סיבוכיות‬ ‫חתימת הפעולה‬ ‫תיעוד הפעולה‬
‫)‪o(1‬‬ ‫)‪BinNode (T value‬‬ ‫הפעולה בונה ומחזירה עץ שהוא רק שורש שהערך שלו הוא‬
‫‪ value‬שאין לו תת עץ שמאל ואין לו תת עץ ימין‪ .‬ההפניות‬
‫אליהם הן ‪null‬‬
‫)‪o(1‬‬ ‫‪BinNode (BinNode<T> left ,‬‬ ‫הפעולה בונה ומחזירה עץ שהשורש שלו הוא ‪ ,value‬תת העץ‬
‫)‪T value, BinNode<T> right‬‬ ‫השמאלי הוא ‪ left‬ותת העץ הימני הוא ‪right‬‬
‫)‪o(1‬‬ ‫)(‪T GetValue‬‬ ‫הפעולה מחזירה את הערך של שורש העץ‬
‫)‪o(1‬‬ ‫)(‪BinNode<T> GetLeft‬‬ ‫הפעולה מחזירה את תת העץ השמאלי של העץ הנוכחי‬
‫)‪o(1‬‬ ‫)(‪BinNode<T> GetRight‬‬ ‫הפעולה מחזירה את תת העץ הימני של העץ הנוכחי‬
‫)‪o(1‬‬ ‫)‪void SetValue(T value‬‬ ‫הפעולה קובעת את ערך החוליה הנוכחית להיות ‪value‬‬
‫)‪o(1‬‬ ‫)‪void SetLeft(BinNode<T> left‬‬ ‫הפעולה קובעת את תת העץ השמאלי של העץ הנוכחי להיות‬
‫העץ ‪left‬‬
‫)‪o(1‬‬ ‫)‪void SetRight(BinNode<T> right‬‬ ‫הפעולה קובעת את תת העץ הימני של העץ הנוכחי להיות‬
‫העץ ‪left‬‬
‫)‪o(1‬‬ ‫)(‪bool HasLeft‬‬ ‫הפעולה מחזירה ערך בוליאני האם יש תת עץ שמאלי לשורש‬
‫הנוכחי‬
‫)‪o(1‬‬ ‫)(‪bool HasRight‬‬ ‫הפעולה מחזירה ערך בוליאני האם יש תת עץ ימני לשורש‬
‫הנוכחי‬
‫)‪o(1‬‬ ‫)(‪string ToString‬‬ ‫הפעולה מחזירה מחרוזת המתארת את הצומת‬

‫מושגים‪:‬‬
‫צומת – כל איבר בעץ‪.‬‬
‫‪10‬‬
‫שורש‪ -‬הצומת הראשון של העץ‪.‬‬
‫בן‪ -‬צומת עוקב בעץ (הבן השמאלי של הצומת שערכו ‪ 5‬הוא הצומת שערכו ‪.)40‬‬
‫‪11‬‬ ‫‪22‬‬
‫אב‪-‬צומת קודם בעץ (האב של הצומת שערכו ‪ 15‬הוא הצומת שערכו ‪.)22‬‬
‫עלה‪-‬צומת ללא בנים (הצמתים שערכם ‪.)40, 3, -9, 0‬‬
‫‪5‬‬
‫‪15‬‬
‫‪0‬‬ ‫תת עץ ימני‪ -‬תת העץ הימני של הצומת ‪ 22‬הוא העץ‬
‫תת עץ שמאלי‪ -‬תת העץ השמאלי של הצומת ‪ 22‬הוא העץ‬
‫עץ ריק‪ -‬עץ ללא צמתים (מצביע ל‪.)null-‬‬
‫‪40‬‬ ‫‪7‬‬
‫אחים‪ -‬בנים לאותו אב (הצומת שערכו ‪ 11‬אח של הצומת שערכו ‪.)22‬‬
‫אב קדמון‪ -‬צומת שנמצא מעל הצומת ויש בניהם מסלול‬
‫‪3‬‬ ‫‪-9‬‬ ‫(הצומת שערכו ‪ 22‬אב קדמון של הצמתים שערכם‪.)9- ,3 ,7 ,0,15 :‬‬
‫צאצא‪ -‬צומת שנמצא מתחת הצומת ויש בניהם מסלול‬
‫(הצומת שערכו ‪ 15‬הוא צאצא של הצמתים שערכם ‪.)10 ,22‬‬

‫‪12‬‬
‫רמה‪ -‬מספר הקטעים במסלול בין שורש העץ לצומת‪ .‬הרמה של השורש היא ‪0‬‬
‫(ברמה ‪ 2‬נמצאים הצמתים שערכם הוא ‪.(5 ,15 ,0‬‬
‫גובה‪ -‬הרמה הגבוהה ביותר בעץ (גובה העץ‪.)4 :‬‬

‫שלוש סריקות עומק של עץ בינארי‪:‬‬


‫סריקה תחילית (‪ -)Preorder‬שורש‪ ,‬שמאל‪ ,‬ימין‪.‬‬
‫סריקה תוכית (‪ -)Inorder‬שמאל‪ ,‬שורש‪ ,‬ימין‪.‬‬
‫סריקה סופית (‪ -)Postorder‬שמאל‪ ,‬ימין ‪ ,‬שורש‪.‬‬

‫דוגמה (לפי העץ המודגם לעיל)‬


‫תחילית‪10, 11, 5, 40, 22, 15, 7, 3, -9,0 -‬‬
‫תוכית‪40, 5, 11, 10, 3, 7, -9, 15, 22, 0 -‬‬
‫סופית‪40, 5, 11, 3, -9, 7, 15, 0, 22, 10 -‬‬

‫ארבע תבניות בפתרון שאלות על עצים בינאריים‪:‬‬

‫תבנית סריקה (‪)void‬‬ ‫‪‬‬


‫תבנית מניה‪.‬‬ ‫‪‬‬
‫תבנית האם (האם תנאי מסוים מתקיים פעם אחת בעץ)‪.‬‬ ‫‪‬‬
‫תבנית לכל (האם תנאי מסוים מתקיים עבור כל צמתי העץ)‪.‬‬ ‫‪‬‬

‫‪13‬‬
‫תבנית סריקה‬

.‫פעולה המקבלת עץ של מספרים שלמים ומדפיסה את הערכים הזוגיים הנמצאים בו‬

:‫הפתרון מוצג בשלוש סריקות העומק‬


.‫שים לב היכן בקוד יש התייחסות לשורש ביחס לתת עץ שמאל ותת עץ ימין‬

‫סדר סריקה תחילי‬

public static void PrintEven(BinNode<int> t)


{
if (t != null)
{
if (t.GetValue() % 2 == 0)
Console.WriteLine(t.GetValue());
PrintEven(t.GetLeft());
PrintEven(t.GetRight());
}
}

‫סדר סריקה תוכי‬

public static void PrintEven(BinNode<int> t)


{
if (t != null)
{
PrintEven(t.GetLeft());
if (t.GetValue() % 2 == 0)
Console.WriteLine(t.GetValue());
PrintEven(t.GetRight());
}
}

‫סדר סריקה סופי‬

public static void PrintEven(BinNode<int> t)


{
if (t != null)
{
PrintEven(t.GetLeft());
PrintEven(t.GetRight());
if (t.GetValue() % 2 == 0)
Console.WriteLine(t.GetValue());
}
}

14
‫תבנית מניה‬

.‫פעולה המקבלת עץ של מספרים שלמים ומונה את מספר הצמתים‬

public static int NumNodes<T>(BinNode<T> t)


{
if (t == null)
return 0;
return 1 + NumNodes(t.GetLeft()) + NumNodes(t.GetRight());
}

.‫פעולה המקבלת עץ של מספרים ממשים ומחזירה את סכום ערכי הצמתים שיש להם שני בנים‬

public static double SumTwoChildren(BinNode<double> t)


{
if (t == null)
return 0;
if (t.HasLeft() && t.HasRight())
return t.GetValue() + SumTwoChildren(t.GetLeft()) + SumTwoChildren(t.GetRight());
return SumTwoChildren(t.GetLeft()) + SumTwoChildren(t.GetRight());
}

.‫פעולה המקבלת עץ של מספרים שלמים ומחזירה את ערך המקסימום‬

:'‫פתרון א‬

public static int MaxTree1(BinNode<int> t)


{
int max = t.GetValue();
if (t.HasLeft())
max = Math.Max(max, MaxTree1(t.GetLeft()));
if (t.HasRight())
max = Math.Max(max, MaxTree1(t.GetRight()));
return max;
}

.‫ ידוע שכל הערכים בעץ חיוביים‬:'‫פתרון ב‬

public static int MaxTree2(BinNode<int> t)


{
if (t == null)
return 0;
int maxChild = Math.Max(MaxTree2(t.GetLeft()), MaxTree2(t.GetRight()));
return Math.Max(t.GetValue(),maxChild);
} ‫תבנית האם‬
15
‫תבנית האם‬

.‫פעולה גנרית המקבלת עץ וערך ובודקת האם הערך נמצא בעץ‬

public static bool IsExist<T>(BinNode<T> t, T value)


{
if (t == null)
return false;
if (t.GetValue().Equals(value))
return true;
return IsExist(t.GetLeft(),value) || IsExist(t.GetRight(),value);
}

‫תבנית לכל‬
.‫פעולה גנרית המקבלת עץ ובודקת האם לכל צומת פנימי יש שני בנים‬

public static bool HasTwoChildren<T>(BinNode<T> t)


{
if (!t.HasLeft() && !t.HasRight())
return true;
if (!t.HasLeft() || !t.HasRight()) //‫נמצא בן יחיד‬
return false;
return HasTwoChildren(t.GetLeft()) && HasTwoChildren(t.GetRight());
}

.‫פעולה המקבלת שני עצים ובודקת האם כל ערך מהעץ הראשון נמצא בעץ השני‬
IsExist ‫הפעולה נעזרת בפעולה‬

public static bool IsContained(BinNode<int> t1,BinNode<int> t2)


{
if (t2 == null)
return true;
if (!IsExist(t1, t2.GetValue()))
return false;
return IsContained(t1, t2.GetLeft()) && IsContained(t1, t2.GetRight());
}

16
‫סריקה לרוחב‬
.‫סריקה לרוחב מתבצעת לפי רמות וממומשת באמצעות תור‬

‫פעולה המקבלת עץ ומדפיסה את ערכיו לפי רמות‬

public static void BreadthSearch(BinNode<int> t)


{
Queue<BinNode<int>> qu = new Queue<BinNode<int>>();
BinNode<int> temp;
qu.Insert(t);
while(!qu.IsEmpty())
{
temp = qu.Remove();
Console.Write(temp.GetValue()+" ");
if (temp.HasLeft()) ‫ במקרה הזה‬:‫טיפול בצומת נוכחי‬
qu.Insert(temp.GetLeft()); ‫הדפסה‬
if (temp.HasRight())
qu.Insert(temp.GetRight());
}
}

17

You might also like