תרגול 13 עצים
Transcription
תרגול 13 עצים
תרגול 13 עצים U U U הגדרות: עץ – מבנה נתונים של קודקודים )צמתים( וקשתות כך שלכל קודקוד יש אב יחיד ,פרט לקודקוד השורש )שלו אין אבא(. U צומת Xהוא אב קדמון של צומת ,Yו Yהנו צאצא של Xאם המסלול מהשורש אל Yעובר דרך .X צומת Xהוא האבא של ,Yו Yהנו הבן של Xאם Xהנו אב קדמון של Yויש ביניהם צלע. עלה – צומת אשר אין לו בנים. צומת פנימי – צומת אשר אינו עלה. עומק – מרחק הצומת מהשורש. גובה – המרחק המקסימאלי של צומת מעלה )בתת העץ שלו(. עץ בינארי עץ אשר בו מספר הבנים של כל צומת אינו עולה על .2 עץ חיפוש בינארי עץ בינארי אשר בו עבור כל צומת הערכים של כל האיברים בתת העץ השמאלי שלו קטנים )או שווים( ממנו, וכל האיברים בתת העץ הימני שלו גדולים ממנו. שלוש שיטות לסריקת עץ ).(pre, in & post עקוב אחר שלוש הסריקות בעץ הנתון ורשום מהו סדר האיברים הנסרקים בכל אחת מהן. תשובה: תחילי ):(pre-order תוכי ):(in-order סופי ):(post-order U U 1,6,8,5,2,9,3 8,6,2,5,9,1,3 8,2,9,5,6,3,1 :מימוש U public class BinaryTree { U U protected BinaryNode root; U U public BinaryTree() { root = null; } // BinaryTree U U public boolean isEmpty() { return root == null; } // isEmpty U U public void insert(Object toAdd) { if (isEmpty()) root = new BinaryNode(toAdd); else root.insert(toAdd); } // insert U U U U U U public String inOrder() { if (isEmpty()) return ""; else return root.inOrder(); } // inOrder U U public String preOrder() { if (isEmpty()) return ""; else return root.preOrder(); } // preOrder U U public String postOrder() { if (isEmpty()) return ""; else return root.postOrder(); } // postOrder } // class BinaryTree U U public class BinaryNode { protected Object data; protected BinaryNode left; protected BinaryNode right; public BinaryNode(Object data) { this.data = data; left = null; right = null; } // BinaryNode public void insert(Object toAdd) { double select = Math.random(); if (select > 0.5) { if (left == null) left = new BinaryNode(toAdd); else left.insert(toAdd); } else { if (right == null) right = new BinaryNode(toAdd); else right.insert(toAdd); } } // insert public String inOrder() { String res = ""; if (left != null) res = res + left.inOrder(); if (data == null) res = res + " <null> "; else res = res + " " + data.toString() + " "; if (right != null) res = res + right.inOrder(); return res; } // inOrder public String preOrder() { String res = ""; if (data == null) res = res + " <null> "; else res = res + " " + data.toString() + " "; if (left != null) res = res + left.preOrder(); if (right != null) res = res + right.preOrder(); return res; } // preOrder public String postOrder() { String res = ""; if (left != null) res = res + left.postOrder(); if (right != null) res = res + right.postOrder(); if (data == null) res = res + " <null> "; else res = res + " " + data.toString() + " "; return res; } // postOrder } // class BinaryNode import java.util.Comparator; public class BST extends BinaryTree { private Comparator comp; public BST(Comparator comp) { super(); this.comp = comp; } // BST … // (override insert, remove, etc.) } // class BST public class BSN extends BinaryNode { private Comparator comp; public BSN(Object data, Comparator comp) { super(data); this.comp = comp; } // BSN … // (override insert, remove, etc.) } // class BSN public class IntegerComparator implements Comparator { public int compare(Object o1, Object o2) { if (((Integer)o1).intValue() > ((Integer)o2).intValue()) return 1; else if (((Integer)o1).intValue() == ((Integer)o2).intValue()) return 0; else return -1; } } import java.util.Comparator; public class Main { public static void main(String[] args) { Comparator comp = new IntegerComparator(); BST tree1 = new BST(comp); tree1.insert(new tree1.insert(new tree1.insert(new tree1.insert(new tree1.insert(new tree1.insert(new tree1.insert(new Integer(50)); Integer(60)); Integer(40)); Integer(30)); Integer(20)); Integer(45)); Integer(65)); System.out.println("InOrder: " + tree1.inOrder()); System.out.println("PreOrder: " + tree1.preOrder()); System.out.println("PostOrder: " + tree1.postOrder()); System.out.println("Find Minimum: " + tree1.findMin()); System.out.println("Height: " + tree1.height()); System.out.println("Is Perfect?: " + tree1.isPerfect()); System.out.println("Is Complete? " + tree1.isComplete()); } } .חישוב גובה בעץ חיפוש בינארי :BinaryTree במחלקה public int height() { if (isEmpty()) { return -1; } else { return root.height(); } } // height :BinaryNode במחלקה public int height() { int resLeft = -1; int resRight = -1; if (left != null) { resLeft = left.height(); } if (right != null) { resRight = right.height(); } return Math.max(resLeft, resRight) + 1; } // height .מציאת קודקוד בעל מפתח מינימאלי בעץ חיפוש בינארי :BST במחלקה public Object findMin() { if (isEmpty()) { return null; // Exceptions are needed... } return ((BSN)root).findMin(); } // findMin :BSN במחלקה public Object findMin() { BinaryNode t=this; while( t.left != null ) t = t.left; return t.data; } // findMin :הכנסת איבר חדש לעץ :BST במחלקה public void insert(Object toAdd) { if (isEmpty()) { root = new BSN(toAdd, this.comp); } else { root.insert(toAdd); } } // insert :BSN במחלקה public void insert(Object toAdd) { if (comp.compare(toAdd, this.data) < 0) { if (left == null) left = new BSN(toAdd,this.comp); else left.insert(toAdd); } if (comp.compare(toAdd, this.data) > 0) { if (right == null) right = new BSN(toAdd,this.comp); else right.insert(toAdd); } } // insert עוקב וקודם העוקב לצומת Xהוא הצומת בעל מפתח הקטן ביותר הגדול מהערך של X הקודם לצומת הוא הצומת בעל מפתח הגדול ביותר הקטן מערך של X הקודם של ,R – Wהעוקב של .Y – W הקודם של ,B – Cהעוקב של .E – C עץ בינארי מלא )(FULL עץ בינארי אשר בו לכל צומת פנימי יש )בדיוק( שני בנים. דוגמא (COMPLETE) עץ בינארי שלם : ומתקייםh עץ בינארי שגובהו . בנים2 יש בדיוקh-2 • לכל הקודקודים שלו עד שכבה . מרוכזים לשמאלh-• כל הקודקודים ברמה ה (PERFECT) עץ בינארי מושלם .עץ בינארי מלא שבו לכל העלים יש אותו עומק בדיקה האם עץ בינארי הוא עץ בינארי מושלם:דוגמא :BST :במחלקה public boolean isPerfect(){ return ((BSN)root).isPerfect(); } :BSN במחלקה public boolean isPerfect(){ int h = height(); //class method if (h==0) return true; if (h==1) return (!(left==null) && !(right==null)); return (!(left==null) && (left.height() == h - 1) && ((BSN)left).isPerfect() && !(right==null) &&(right.height() == h - 1) && ((BSN)right).isPerfect()); } U U בדיקה האם עץ בינארי הוא עץ בינארי שלם ראינו את ההגדרות הבאות: עץ מושלם ) :(perfectעץ בינארי מלא שבו לכל העלים אותו עומק עץ בינארי שלם ) :(completeעץ בינארי שגובהו hומתקיים • כל הקדקודים שלו עד שכבה h-2יש בדיוק 2בנים. • כל הקודקודים ברמה ה h-מרוכזים לשמאל. בהגדרה רקורסיבית: עץ בינארי הוא שלם אם ורק אם ) hהוא גובה העץ( .1הוא ריק או .2הבן השמאלי שלו הוא שורש של עץ שלם בגובה h-1והבן הימני שלו הוא שורש של עץ מושלם בגובה h-2 או .3הבן השמאלי שלו הוא שורש של עץ מושלם בגובה h-1והבן הימני שלו הוא שורש של עץ שלם בגובה h-1 אנחנו נבדוק כמה מקרי קצה כי אם גובה העץ הוא 0או 1נקבל שדרוש לבדוק אם גובה תת העץ הוא 0או :1 במחלקה :BST )(public boolean isComplete { ;)(return ((BSN)root).isComplete } במחלקה :BSN )(public boolean isComplete { ;)(int h = height //class method ;if (h==0) return true ;))if (h==1) return (!(left==null //the height is 2 and up: ;))boolean has2Sons = (!(left==null) && !(right==null ;boolean case1=false, case2=false {)if (has2Sons ;)(int leftH = left.height ;)(int rightH = right.height && ))(case1 = (((leftH == h-1) && ((BSN)left).isComplete && )(rightH == h-2 ;))(((BSN)right).isPerfect && )case2 = (((leftH == h-1 && ))( ((BSN)left).isPerfect && )(rightH == h-1 ;))(((BSN)right).isComplete } ;return case1 || case2 }