תצוגה

../images/Emo20.gif תצוגה

יש לי טבלה המכילה מידע בצורה הררכית, כלומר לכל רשומה יש עמודה עם מפתח רשומת האבא. (נניח שאבא 0 הוא האב עליון, שאין לו אבות) למשל :
Number Value ParentNumber 1 A 0 2 B 0 3 A1 1 4 A2 1 5 B1 2​
אני רוצה לכתוב פונקציה שמדפיסה את כל השרשרת, בצורץ עץ היררכי. כיצד אני עושה זאת ? עם רקורסיה ? כיצד אני מדביק זאת לאובייקט TREE בדוט נט ? (אני יודע שבאורקל אפשר לשלוף עם connect by, אבל ב SQLSERVER אי אפשר..) תודה !
 

עידו פ

New member
כמה דברים

- ב-sql server 2005 כבר אפשר (אני משער שיגידו לך איך בפורום בסיסי נתונים) - רקורסיה נשמע הגיוני - להעביר כל פעם לפונקציה שלך את האבא הנוכחי ואת הבנים שלו, רק תדאג לכך שמבנה הנתונים שלך מאפשר לדעת לכל איבר מי הבנים שלו (אפשר לממש את זה ע"י כתיבת class ייעודי שיכיל שדות מתאימים או ע"י שימוש באובייקטים טבלאיים כגון DataTable של דוטנט) - איך לי מושג איך עובד אובייקט TREE בדוטנט - בשביל זה יש את פורום דוטנט
 
רקורסיה

אם נצמד לרגע לפסאודו קוד, ולא לדוט נט, מדוע הרקורסיה צריכה לקבל את האבא וגם הבנים ? הרקורסיה לא אמורה לקבל קוד של אב/בן כלשהו, לבדוק לבד האם יש לו בנים, ואם כן, אז לקרוא לרקורסיה עבור כל בן ?
 

עידו פ

New member
הכוונה היתה

להעביר למתודה את אובייקט האבא בעץ (ב-tree view) ואת רשימת הבנים (מערך של אובייקטים). לחילופין, אפשר להעביר את אובייקט האבא בעץ, ואת אובייקט האבא של מבנה הנתונים ולתת למתודה למצוא את הבנים של האבא (בהתאם למבנה הנתונים) ולקרוא בצורה רקורסיבית עבור כל אחד מהבנים משהו בסגנון: 1. הוסף אבא נוכחי תחת שורש X שהועבר (אם לא הועבר, הוסף לשורש העץ) 2. אתר בנים של אבא נוכחי 3. לכל בן: 3.1 הפעל מתודה שוב - הפעם עם מיקום של אבא נוכחי בעץ ובן נוכחי שנמצא
 
אני קצת מבולבל...

חשבתי על פונקיה שתקבל מצביע כלשהו לעץ (מפתח הרשומה למשל), בדיקה האם המצביע הוא "עלה" בעץ. אם המצביע הוא עלה - תדפיס אותו (או למשל, תוסיף אותו לאובייקט העץ) אחרת (יש בנים), קרא לפונקציה הרקורסיבית עבור כל אחד מהבנים שנמצאו. האם אני בכיוון ? האם זה יעבוד ? במידה ואני רוצה להוסיף את העלה לעץ (ההדפסה), איך אני יודע לאיזה אבא ? האם זה אומר שגם האבא צריך להיות פרמטר לפונקציה הרקורסיבית ?
 

עידו פ

New member
-->

כתבת בהודעה המקורית שאתה רוצה להשתמש ב-Tree של דוטנט, אז שיערתי שמדובר ב-tree view (רכיב ויזואלי) ולכן הבדלתי בין מבנה הנתונים שמחזיק את המידע של ההררכיה לבין האובייקט שמחזיק את העץ הויזואלי. כוונתי בפונקציה היתה שהיא מקבלת שני פרמטרים - האחד מתייחס לעץ הויזואלי והשני למבנה הנתונים ומה שהפונקציה עושה זה לבנות את העץ הויזואלי עפ"י מבנה הנתונים. הבעיתיות במה שאתה מציג היא שאתה לא יודע מה אתה רוצה לעשות עם איבר בעץ ברגע שאתה נתקל בו - האם להדפיס אותו או להוסיף אותו לאיזהו עץ ויזואלי. להלן מספר דוגמאות לבעיתיות במה שאתה מציג: נניח אתה רוצה להדפיס את העץ עם אינדנטציה (כניסה פנימה של הטקסט) לכל רמה - אם אתה רק עובר מאב לבן, חסר לך המידע לגבי מספר הרמה בה אתה נמצא על-מנת לדעת כמה אינדנטציה אתה צריך !! נניח אתה רוצה לבנות tree view ממבנה הנתונים - כשאתה נמצא בבן כלשהו, איך אתה יודע לאיזה ענף ב-tree view הבן הזה צריך להתווסף ?! לסיכום - יש בעיתיות במה שאתה רוצה לעשות כי לא הגדרת את זה עד הסוף. דרך אגב, ישנו מנגנון לטיפול בעצמים במבוסס על סריקת עץ (מבנה נתונים של עץ) והעלאת אירוע בכל פעם שנתקלים בבן חדש - ואז אם אתה רוצה לממש מנגנון כלשהו שמבוסס על העץ, כל מה שאתה צריך זה לדעת "לתפוס" את האירוע של "בן חדש" ושל "אין עוד בנים" ולבצע את הפעולה בהתאם (להוסיף/להפחית רמה באינדנטציה או לדוגמה, לעבור ב-tree view לאיבר הקודם בעץ). דוגמה למנגנון זה אפשר למצוא ב-SAX שזו טכניקה לביצוע parsing על XML (בשונה מהטכניקה המוכרת שנקראת DOM)
 
המממ...

ראשית, תודה רבה על ההסברים ! שנית, צודק, לא הגדרתי זאת עד הסוף, ואני עדיין לא מבין עד הסוף
נניח שאני אכן רוצה רק להדפיס את כל העץ, אבל עם אינדנטציה, איך אני עושה זאת ? אם אני כותב פונקציה המקבלת כפרמטר צומת בעץ, אם זה עלה = הדפס אחרת, שלוף את כל הבנים,קרא לפונקציה הרקורסיבית עבור כל אחד מהבנים. לדעתי זה אכן ידפיס את כל איברי העץ, אבל כיצד אני משפר את הפסאודו קוד הזה כדי שידפיס את העץ מעומד (אינדנטציה) ?
 

עידו פ

New member
אם אתה רוצה אותו מעומד

תצטרך בכל קריאה למתודה, לשלוח את הרמה הנוכחית בעץ. לדוגמה: המתודה נקראת בפעם הראשונה עם רמה 0 כשהמתודה קוראת לעצמה, היא תקרא עם רמה 0+1 = 1 כשהמתודה שוב תקרא לעצמה, היא תקרא עם רמה 1+1 = 2 וכן הלאה ברגע שיש לך את הרמה, אתה יכול לעשות אינדנטציה (נניח הדפסת 4 רווחים כפול הרמה, לפני כתיבת האיבר שבעץ)
 
בוא נראה אם הבנתי :

פונקציה רקורסיבית המקבלת 2 פרמטרים : פוינטר לצומת בעץ, ורמת הפויינטר בעץ. הדפס רווח כפול רמת הפוינטר בעץ הדפס צומת שלוף את כל הבנים הישירים של הצומת עבור כל בן, בצע קריאה רקורסיבית ושלח כפרמטרים את הפוינטר של הבן, ורמה +1 1. האם זה יעבוד ? 2. באלגוריתם שהצגתי בהודעתי הקודמת, יש באג הגורם לכך שרץ העלים יודפסו, ולא כל העץ, לא ? תודה !
 

עידו פ

New member
-->

1. נשמע שזה יעבוד (לפחות מבחינה תיאורטית) 2. נראה שאכן האלגור' הראשון אינו נכון, כי הדפסה של עלים בלבד לא תדפיס צמתים (ההגיון אומר להדפיס את האיבר ואז לעבוד על הבנים שלו, אם יש כאלו)
 
../images/Emo51.gif וחידוד אחרון :

אם כעת במקום סתם להדפיס, אני אכן רוצה למלא קונפוננטה של TreeView, אז הפונקציה לא צריכה פרמטרים נוספים, אלא במקו לקבל את "רמת הפויינט בעץ" היא תקבל פוינטר למקום בעץ, שאליו צריכים להוסיף את האיבר, ואז ההבדל היחיד באלגוריתם, לעומת הודעתי הקודמת הוא, שבמקום להדפיס את העץ, אני מוסיף אותו ל TreeView ? כלומר : 1. פונקציה המקבלת 2 פרמטרים, פוינטר ל TreeView ופויינטר לצומת שצריך להוסיף (הקריאה הראשונה תהיה עם ה ROOT) 2. הוספת הפרמטר השני לעץ, במיקום הפרמטר הראשון 3. שליפת הבנים 4. עבור כל בן, לבצע קריאה קרורסיבית, כעת הפרמטר הראשון יהיה הפרמטר השני שקיבלנו קודם, והפרמטר השני יהיה הבן שמצאנו יעבוד ?
 
למעלה