breadth first search

W
Shared by: 4yeOQi7
Categories
Tags
-
Stats
views:
140
posted:
3/17/2012
language:
Thai
pages:
42
Document Sample
scope of work template
							Tree
          ลักษณะทัวไป
                  ่

                  1.




     2.           5.    6.



3.           4.              7.
• ตัว โนด บนสุ ดจะเรี ยกว่าเป็ น ราก (root) ของ tree
                                                     ่
• tree ส่ วนย่อย (มี โนด 2 เป็ น root) เรี ยกได้วาเป็ น subtree ของ tree
  ใหญ่
• โนด 1 จะเป็ น บัพแม่ (parent) ของ โนด 2,5,6 ส่ วน โนด 2 เป็ น parent
  ของ โนด 3,4 หรื อเรี ยกอีกอย่างว่า โนด 3,4 เป็ น บัพลูก (child) ของ โนด 2
• โนด 3 เป็ นบัพพีน้อง (sibling) กับ โนด 4
                  ่
• ถ้ามีความสัมพันธ์แบบ parent ตั้งแต่หนึ่ งทอดขึ้นไป เราเรี ยกว่า บัพบน
  (ancestor) เช่น โนด 1 เป็ น ancestor ของ โนด 7
• โนด ที่ไม่มีกิ่งออกไป เราเรี ยกว่า บัพใบ หรือ ใบ (leaf) เช่นในรู ป
  leaf คือ โนด 3, 4, 5 และ 7
                    ่
• เราจะสังเกตได้วา มีแค่ 1 เส้ นทาง (path) จาก root ไปยัง โนด แต่
  ละ โนด เท่านั้น
• ความลึก (depth) ของ โนด n คือความยาวของ path จาก
  root ถึง n ตัวอย่างเช่น depth ของ โนด เบอร์ 7 คือ 2
• ความสู ง (height) ของ โนด n คือความยาวของ path ที่ยาว
  ที่สุดจาก n ถึง leaf ตัวอย่างเช่น height ของ โนด เบอร์ 7 คือ 0
  และ height ของ โนด เบอร์ 1 คือ 2
• height ของ tree ก็คือ height ของ root นันเอง ถ้า tree
                                                  ่
  มีแค่ root เราให้ height เป็ น 0 และถ้า tree เป็ น empty
  tree เราให้ height เป็ น -1
• height ของต้นไม้ใดๆ จะเท่ากับ height ของ subtree ที่สูง
  ที่สุด บวกด้วย 1
• ระดับ (level) ของ โนด คือ ลาดับชั้นของโนดนั้น โดย child
  ของ โนด หนึ่งๆจะมีระดับ1 ระดับมากกว่า parent ของมัน (root
  ถือว่ามีระดับเป็ น 0)
                      ถ้าให้แต่ละโนด มีกี่กิ่งก็ได้
• เราไม่มีทางกาหนดจานวนกิ่งที่แน่นอนได้
• การเตรี ยมกิ่งไว้ล่วงหน้ามากๆก็เป็ นการเปลืองหน่วยความจา
• วิธีหนึ่งที่อาจแก้ปัญหานี้ได้คือ
                                                      1
   ข้อมูล          Link ไปยัง sibling ถัดไป
                                                  2           5          6


     Link ไปยังลูกกิ่งแรก                     3           4             7
     (first child)
                                       ลักษณะของต้นไม้จากรู ปแรกที่สร้างด้วยแนวคิดนี้
             การเรี ยงดูสมาชิกภายในต้นไม้
• ก่อนลาดับ (preorder)
• ดูของจาก root โนด ที่เราเริ่ มพิจารณา แล้วจึงไปดูของใน
  subtree โดยใน subtree ก็เริ่ มดูจาก root โนด เช่นเดียวกัน
          ผลการเรี ยงสมาชิกใน โนด จากรู ป คือ 1,2,3,4,5,6,7
                                                                  อันดับแรกที่ดู
                                        1.


       อันดับสองที่ดู เป็ น                                                  อันดับ4 ที่ดู เป็ น
       subtree                                                               subtree
                              2.        5.                   6.
                                                                                   ซึ่งภายในก็จะ
ซึ่งภายในก็จะ
                                                                                   เรี ยงดูแบบ
เรี ยงดูแบบ
                                                                                   preorder
preorder
                       3.          4.                               7.



                                             อันดับ3 ที่ดู
• หลังลาดับ (postorder)
   – คือการเรี ยงดู subtree ทั้งหมด แล้วจึงมาดูของใน root ซึ่งภายใน subtree นั้น
         ้
     ก็ตองมีการเรี ยงดูแบบเดียวกัน
   – เพราะฉะนั้นถ้าเราเรี ยงสมาชิกใน tree ในรู ปที่แล้วแบบ postorder จะได้ผลลัพธ์
     เป็ น 3,4,2,5,7,6,1
• ตามลาดับ (inorder)
   – คือการเรี ยงสมาชิกโดยสมาชิกของ subtree ด้านซ้ายของ root จะถือว่าต้องมาก่อน
                                             ่ ้
     root ส่ วนสมาชิกของ subtree ที่อยูดานขวาของ root จะถือว่ามาทีหลัง root
     นอกจากนี้ส่วนข้างในตัว subtree ก็ใช้วธีการเรี ยงอย่างเดียวกัน
                                                 ิ
                              ั                                    ่ ้
   – ดังนั้นถ้าดูจากรู ป (ไม่นบ subtree ที่มี 5 เพราะไม่รู้จะจัดอยูขางไหนของ root) เรา
     จะเรี ยงสมาชิกได้เป็ น 3,2,4,1,6,7
การค้นหาในแนวกว้าง (breadth-first search)
• วิธีการสามแบบแรกที่กล่าวมาข้างต้นนั้น เป็ นวิธีการค้นหาในแนวลึก
  (depth-first search)
• ซึ่งถ้ามีการดู subtree ใดแล้วจะต้องตรวจสอบทั้ง subtree นั้น
  ให้เสร็ จ จึงจะสารวจ root หรื อ subtree อื่นๆที่เป็ น sibling
  ต่อไปได้
• breadth-first จะตรวจสอบทีละระดับของ tree โดยเริ่ มจาก
  ระดับของ root ดังนั้น tree ในรู ปหน้าก่อนโน้นจะมีการเรี ยง
  สมาชิกได้เป็ น 1,2,5,6,3,4,7
    breadth-first implementation
• ตอนที่ดูโนดโนดหนึ่ง เราจะบันทึก child ของโนดนั้นลงในคิวที่
  สร้างไว้สาหรับเก็บโนดในระดับถัดลงมา (next level queue)
  เช่น ถ้าเรามี                  *

                        +               -


               a            *       d       e


                    b           c
    breadth-first implementation(2)
•    เมื่อเราดู root เราจะบันทึก child โนด ของ root ไว้บน next level queue ดังนั้น ใน
     ขั้นนึ้ next level queue มี + กับ –
•    update ให้ this level queue = next level queue แล้ว เคลียร์ next level queue
•                                                                   ั           ู
     สารวจ this level queue จะพบ + เป็ นตัวแรก ตอนนี้ให้ดูตวต้นไม้แล้วใส่ ลกของ +
     ลงใน next level queue นันคือ ในตอนนี้ next level queue = a,*
                                  ่
•                                                                      ู
     สารวจ this level queue ต่อ จะพบ – เป็ นสมาชิกตัวต่อมา ใส่ ลกของ - ลงใน next
     level queue นันคือ ในตอนนี้ next level queue = a,*,d,e
                       ่
•    ไม่มีสมาชิกใน this level queue แล้ว ดังนั้น update ให้ this level queue = next
     level queue นันคือ this level queue = a,*,d,e
                         ่
•             ่                           ้
     เริ่ มเยียม this level queue ตั้งแต่ตนอีกครั้ง และทาซ้ าไปเรื่ อยๆ
         ต้นไม้แบบทวิภาค (Binary Tree)
• แต่ละ โนด มีกิ่งออกไปได้มากที่สุดสองกิ่ง
• ดังนั้นอาจมีกิ่งเดียวในทุกระดับก็ได้ ซึ่งก็จะกลายเป็ น linked list
                               ่
  ไป หรื ออาจเรี ยกอีกอย่างได้วา skewed tree
        full binary tree หรื อ perfectly
                balanced tree
• เป็ นรู ปสามเหลี่ยมอย่างสมบูรณ์ ไม่ขาด leaf ใดๆในระดับของ leaf
  ที่สูงที่สุด
             ต้นไม้บริ บูรณ์ (complete tree)
  • เต็มถึงระดับก่อน leaf ที่สูงที่สุดแต่ระดับของ leaf ที่สูงที่สุดอาจไม่
              ั                 ้
    เต็ม (แต่ยงมี leaf เติมใส่ ตนจากซ้ายไปขวา)
                                          A


                                 N                 E


                          T          O         X

                                                     ้
ต้นไม้แบบเต็มต้นถือว่าเป็ นต้นไม้บริ บูรณ์แน่นอน แต่ตนไม้บริ บูรณ์ไม่จาเป็ นต้องเต็มต้น
                            ต้นไม้บริ บูรณ์ (2)
• ข้อสังเกตอีกอย่างคือ ถ้าเราเอาสมาชิกของต้นไม้บริ บูรณ์ใส่ ในอาร์ เรย์ โดยเรี ยงใส่
  แบบตามแนวกว้าง (breadth-first)
                                       ่
    – สมาชิกที่ตาแหน่ง i จะมีลูกซ้ายอยูที่ตาแหน่ง 2i+1
                   ่
    – และลูกขวาอยูที่ตาแหน่ง 2i+2
                                    ่
    – ส่ วนตัว parent ของ i จะอยูที่ตาแหน่ง (i-1)/2 (ปั ดทศนิยมทิ้งไป)

       A          N          E         T          O          X

      ลูกซ้ายของ E จะต้องมี index =2*2+1 =5 ซึ่ งก็คือ X
      นันเอง ส่ วน parent ของ E ก็จะมี index = (2-1)/2 =
        ่
      0 เมื่อปัดลง
                     two-tree
                                  ็
• จะต้องเป็ น empty tree หรื อไม่กมี non-leaf node ที่
  ต้องมีสองกิ่งเท่านั้น
              ทฤษฎีต่างๆของต้ นไม้ ทวิภาค
ถ้าเราให้
                        ั่
• leaves(t) แทนฟังก์ชนที่บอกจานวนใบของต้นไม้ t
• n(t) เป็ นจานวนโนดของ ต้นไม้ t
• height(t) เป็ นความสูงของต้นไม้ t
                                ่
• leftsubtree(t) เป็ นต้นไม้ยอยด้านซ้ายของ t
                                   ่
• rightsubtree(t) เป็ นต้นไม้ยอยด้านขวาของ t
• max(a,b) เป็ นค่าที่มากที่สุดเมื่อเทียบ a กับ b
                               ้ ่
สาหรับต้นไม้ทวิภาคที่ไม่ใช่ตนไม้วาง จะมีความสัมพันธ์
                            ั่
             ระหว่างฟังก์ชนต่างๆดังนี้
                                        n(t )  1
                           leaves(t ) 
                                          2.0

                           n(t )  1
                                      2 height ( t )
                             2.0
                                                          n (t )  1
  ถ้า t เป็ น two-tree แล้วละก็        leaves (t ) 
                                                             2.0
                          n (t )  1
   ถ้า   leaves (t )                  แล้วละก็ t เป็ น two-tree แน่นอน
                             2.0
   ถ้า t เป็ นต้นไม้แบบเต็มต้น แล้วละก็    n (t )  1                (t )
                                                       2height
                                              2.0
              n (t )  1
        ถ้า               2height   (t )
                                            แล้วละก็ t เป็ นต้นไม้แบบเต็มต้น
                 2.0

อย่าลืมว่าเราใช้ 2.0 เพราะฉะนั้นค่าจากสู ตรเหล่านี้ผมจะถือว่าเป็ นทศนิยมนะ
                         ั
เพราะจานวนเต็มจะใช้กบกฎข้อ 4 ไม่ได้
                          n(t )  1
 พิสูจน์     leaves(t ) 
                            2.0
base case คือเมื่อ t เป็ น ต้นไม้ที่มีแต่ราก

             leaves        (t )  1
              n(t)  1
                               1
                  2.0
               ซึ่งเห็นชัดว่าทาให้สมการเป็ นจริ ง
inductive case คือ เมื่อ t เป็ นต้นไม้ที่สูง h
ให้
                         n(t )  1
            leaves(t ) 
                           2.0
                                                                         n(t )  1
สิ่ งทีต้องพิสูจน์ คือ เมื่อ t เป็ นต้นไม้ที่สูง h+1 แล้ว leaves(t ) 
       ่
                                                                           2.0
 leaves(t)  leaves(leftsubtree(t  leaves(rightsubtree(t))
                                ))
             n(leftsubtree(t)) 1 n(rightsubtree(t)) 1
                                
                     2.0                  2.0
       ่
เรารู้วา
      n(t)  n(leftsubtree(t))  n(rightsubtree(t)) 1
       เพราะฉะนั้นเราสามารถแทนค่า n(t) ลงไปในอสมการได้ ผลคือได้

                                  n(t )  1
                     leaves(t ) 
                                    2.0
             External Path length
                                        ่
• ให้ t เป็ นต้นไม้ทวิภาคที่มีราก จะได้วา External Path
  length, E(t) คือผลบวกของความลึกของทุกใบ
                                                                    ่
• ถ้า t เป็ นต้นไม้ทวิภาคที่มีจานวนใบเป็ น k (ซึ่ งมากกว่า 0) จะได้วา

                E (t )  (k / 2) log 2 k 
            ้
     ต้นไม้คนหาแบบทวิภาค (Binary Search
                     Tree)
เป็ น empty tree หรื อเป็ นต้นไม้ซ่ ึง
• ทุกสมาชิกใน leftsubtree(t) มีค่าน้อยกว่าสมาชิกที่รากของ t
• ทุกสมาชิกใน rightsubtree(t) มีค่ามากกว่าสมาชิกที่รากของ t
• ทั้ง leftsubtree(t) และ rightsubtree(t) ต่างก็เป็ น
    binary search tree
                                   7

                         5                    11


               2             6                          14


                   4

                                           ่
สื บค้นได้ง่าย เช่นถ้าเราต้องการหาว่า 4 อยูในต้นไม้หรื อไม่ เมื่อเราดูโนดแต่ละโนด
                   ั ่                       ้
เราสามารถรู ้ได้ทนทีวาจะไปสารวจต้นไม้ขางใดต่อไป
                              ่ ั
ทาให้เวลาในการค้นหาขึ้นอยูกบความสู งของต้นไม้เท่านั้น
ซึ่ งก็แปรตาม log ของจานวน โนด อีกทีหนึ่ง
1. class BinaryNode
2.    {
3.         // Constructors
4.      BinaryNode( Comparable theElement )
5.      {
6.         this( theElement, null, null );
7.      }

8.        BinaryNode( Comparable theElement, BinaryNode lt, BinaryNode rt )
9.        {
10.         element = theElement;
11.         left = lt;
12.         right = rt;
13.       }

14.         // Friendly data; accessible by other package routines
15.       Comparable element;         // The data in the node
16.       BinaryNode left;       // Left child
17.       BinaryNode right;       // Right child
18.   }
// BinarySearchTree class
   //
   // CONSTRUCTION: with no initializer
   //
   // ******************PUBLIC OPERATIONS*********************
   // void insert( x )    --> Insert x
   // void remove( x )       --> Remove x
   // Comparable find( x ) --> Return item that matches x
   // Comparable findMin( ) --> Return smallest item
   // Comparable findMax( ) --> Return largest item
   // boolean isEmpty( ) --> Return true if empty; else false
   // void makeEmpty( )        --> Remove all items
   // void printTree( )     --> Print tree in sorted order
  private BinaryNode root;
1. public class BinarySearchTree
2.   {
3.      private BinaryNode root;

4.     /**
5.      * Construct the tree.
6.      */
7.     public BinarySearchTree( )
8.     {
9.         root = null;
10.    }

11.    /**
12.     * Insert into the tree; duplicates are ignored.
13.     * @param x the item to insert.
14.     */
15.    public void insert( Comparable x )
16.    {
17.        root = insert( x, root );
18.    }
19.   /**
20.    * Remove from the tree. Nothing is done if x is not found.
21.    * @param x the item to remove.
22.    */
23.   public void remove( Comparable x )
24.   {
25.       root = remove( x, root );
26.   }

27.   /**
28.    * Find the smallest item in the tree.
29.    * @return smallest item or null if empty.
30.    */
31.   public Comparable findMin( )
32.   {
33.       return elementAt( findMin( root ) );
34.   }
35.   /**
36.    * Find the largest item in the tree.
37.    * @return the largest item of null if empty.
38.    */
39.   public Comparable findMax( )
40.   {
41.       return elementAt( findMax( root ) );
42.   }

43.    /**
44.    * Find an item in the tree.
45.    * @param x the item to search for.
46.    * @return the matching item or null if not found.
47.    */
48.   public Comparable find( Comparable x )
49.   {
50.       return elementAt( find( x, root ) );
51.   }
52.   /**
53.    * Make the tree logically empty.
54.    */
55.   public void makeEmpty( )
56.   {
57.       root = null;
58.   }

59.   /**
60.    * Test if the tree is logically empty.
61.    * @return true if empty, false otherwise.
62.    */
63.   public boolean isEmpty( )
64.   {
65.       return root == null;
66.   }
67.   /**
68.    * Print the tree contents in sorted order.
69.    */
70.   public void printTree( )
71.   {
72.       if( isEmpty( ) )
73.           System.out.println( "Empty tree" );
74.       else
75.           printTree( root );
76.   }

77.   /**
78.    * Internal method to get element field.
79.    * @param t the node.
80.    * @return the element field or null if t is null.
81.    */
82.   private Comparable elementAt( BinaryNode t )
83.   {
84.       return t == null ? null : t.element;
85.   }
86.         /**
87.         * Internal method to insert into a subtree.
88.         * @param x the item to insert.
89.         * @param t the node that roots the tree.
90.         * @return the new root.
91.         */
92.        private BinaryNode insert( Comparable x, BinaryNode t )
93.        {
94. /* 1*/      if( t == null )
95. /* 2*/          t = new BinaryNode( x, null, null );
96. /* 3*/      else if( x.compareTo( t.element ) < 0 )
97. /* 4*/          t.left = insert( x, t.left );
98. /* 5*/      else if( x.compareTo( t.element ) > 0 )
99. /* 6*/          t.right = insert( x, t.right );
100./* 7*/        else
101./* 8*/            ; // Duplicate; do nothing
102./* 9*/        return t;
103.         }
104.   /**
105.          * Internal method to remove from a subtree.
106.          * @param x the item to remove.
107.          * @param t the node that roots the tree.
108.          * @return the new root.
109.          */
110.         private BinaryNode remove( Comparable x, BinaryNode t )
111.         {
112.             if( t == null )
113.                 return t; // Item not found; do nothing
114.             if( x.compareTo( t.element ) < 0 )
115.                 t.left = remove( x, t.left );
116.             else if( x.compareTo( t.element ) > 0 )
117.                 t.right = remove( x, t.right );
118.             else if( t.left != null && t.right != null ) // Two children
119.             {
120.                 t.element = findMin( t.right ).element;
121.                 t.right = remove( t.element, t.right );
122.             }
123.             else
124.                 t = ( t.left != null ) ? t.left : t.right;
125.             return t;
126.         }
           X                        y




               y                        y

การเอาสมาชิกค่าน้อยที่สุดของกิ่งขวาขึ้นมาแทนสมาชิกตัวที่
                         ถูกลบ
        x                  y

              y




การเอา subtree ขึ้นมาแทนที่โนดที่ถูกลบ
127.   /**
128.    * Internal method to find the smallest item in a subtree.
129.    * @param t the node that roots the tree.
130.    * @return node containing the smallest item.
131.    */
132.   private BinaryNode findMin( BinaryNode t )
133.   {
134.       if( t == null )
135.           return null;
136.       else if( t.left == null )
137.           return t;
138.       return findMin( t.left );
139.   }
140.   /**
141.    * Internal method to find the largest item in a subtree.
142.    * @param t the node that roots the tree.
143.    * @return node containing the largest item.
144.    */
145.   private BinaryNode findMax( BinaryNode t )
146.   {
147.       if( t != null )
148.           while( t.right != null )
149.              t = t.right;

150.       return t;
151.   }
152.   /**
153.    * Internal method to find an item in a subtree.
154.    * @param x is item to search for.
155.    * @param t the node that roots the tree.
156.    * @return node containing the matched item.
157.    */
158.   private BinaryNode find( Comparable x, BinaryNode t )
159.   {
160.       if( t == null )
161.           return null;
162.       if( x.compareTo( t.element ) < 0 )
163.           return find( x, t.left );
164.       else if( x.compareTo( t.element ) > 0 )
165.           return find( x, t.right );
166.       else
167.           return t; // Match
168.   }
169.   /**
170.    * Internal method to print a subtree in sorted order.
171.    * @param t the node that roots the tree.
172.    */
173.   private void printTree( BinaryNode t )
174.   {
175.       if( t != null )
176.       {
177.           printTree( t.left );
178.           System.out.println( t.element );
179.           printTree( t.right );
180.       }
181.   }
182. // Test program
183.      public static void main( String [ ] args )
184.      {
185.         BinarySearchTree t = new BinarySearchTree( );
186.         final int NUMS = 4000;
187.         final int GAP = 37;

188.         System.out.println( "Checking... (no more output means
       success)" );

189.          for( int i = GAP; i != 0; i = ( i + GAP ) % NUMS )
190.             t.insert( new MyInteger( i ) );

191.          for( int i = 1; i < NUMS; i+= 2 )
192.             t.remove( new MyInteger( i ) );
193.if( NUMS < 40 )
194.           t.printTree( );
195.       if( ((MyInteger)(t.findMin( ))).intValue( ) != 2 ||
196.           ((MyInteger)(t.findMax( ))).intValue( ) != NUMS - 2 )
197.           System.out.println( "FindMin or FindMax error!" );

198.           for( int i = 2; i < NUMS; i+=2 )
199.               if( ((MyInteger)(t.find( new MyInteger( i ) ))).intValue( ) != i )
200.                   System.out.println( "Find error1!" );

201.           for( int i = 1; i < NUMS; i+=2 )
202.           {
203.              if( t.find( new MyInteger( i ) ) != null )
204.                  System.out.println( "Find error2!" );
205.           }
206.       }
207.   }

						
Related docs
Other docs by 4yeOQi7