490 likes | 858 Views
ต้นไม้ Tree (1). อาจารย์สุวิชยะ รัตตะรมย์ คณะเทคโนโลยีสารสนเทศและการสื่อสาร. หัวข้อวันนี้. โครงสร้างทั่วไปของต้นไม้ (Introduction) การเรียกชื่อส่วนต่างๆ ของต้นไม้ (terminology) ต้นไม้แบบทวิภาค ( binary tree ) ต้นไม้ทวิภาคแบบสมบูรณ์ (complete binary tree )
E N D
ต้นไม้Tree (1) อาจารย์สุวิชยะ รัตตะรมย์ คณะเทคโนโลยีสารสนเทศและการสื่อสาร
หัวข้อวันนี้ • โครงสร้างทั่วไปของต้นไม้ (Introduction) • การเรียกชื่อส่วนต่างๆ ของต้นไม้ (terminology) • ต้นไม้แบบทวิภาค (binary tree) • ต้นไม้ทวิภาคแบบสมบูรณ์ (complete binary tree) • ต้นไม้ทวิภาคแบบเกือบสมบูรณ์(nearly complete binary tree) • การแทนต้นไม้แบบทวิภาคในคอมพิวเตอร์
หัวข้อวันนี้ • การท่องต้นไม้ (binary tree traversal) • breath-first traversal • depth-first traversal • Preorder traversal • Inorder traversal • Postrder traversal • ต้นไม้นิพจน์ (Expression tree) • สร้าง expression tree จากนิพจน์ postfix
root node branch ลักษณะของโครงสร้างข้อมูลแบบต้นไม้
โครงสร้างทั่วไปของต้นไม้โครงสร้างทั่วไปของต้นไม้ • เป็น โครงสร้างข้อมูลแบบไม่เป็นรายการเชิงเส้น (Non-Linear Data Structure) • ลักษณะคล้ายกิ่งก้านของต้นไม้ (แต่กลับหัว) • ประกอบด้วยจุดยอดของต้นไม้เรียกว่า ราก (Root) • จุดที่มีการแตกกิ่งก้านสาขาออกไปเรียกว่า โหนด (Node) • กิ่งก้านสาขาที่เชื่อมต่อระหว่างโหนดเรียกว่า กิ่ง (Branch) หรือ ลิงค์ (Link) • ส่วนย่อยของต้นไม้ ก็เป็นต้นไม้ (subtree) • ทุกโหนดเป็น root ของ subtree ของตัวมันเอง
R เป็น root ของ subtree A,B,C,D A เป็น root ของ subtree E,F,G F เป็น root ของ subtree J C เป็น subtree ที่มีแต่ root C
A B C การเรียกชื่อส่วนต่างๆ ของต้นไม้ • ต้นไม้ (tree) ประกอบด้วย 1.nodeส่วนเก็บข้อมูล 2.branch ใช้เชื่อม node เข้าด้วยกัน node A, B, C branch AB, AC
A B C • rootหมายถึง node แรกของ tree root A โหนดอื่นๆ B , C Degreeหมายถึง จำนวน subtree ที่สัมพันธ์กับ Node นั้นๆ node A มี degree เท่ากับ 2 node B มี degree เท่ากับ 0 node C มี degree เท่ากับ 0
A B B C D E • leaf หมายถึง node ที่มีดีกรีเท่ากับ 0 root A leaf D , E , C internal node , branch nodeหมายถึง node ที่ไม่ใช่ root และ leaf branch node B
A B B C D E • parent หมายถึง node ที่มีดีกรีมากกว่า 0 (node ที่มี subtree ) parent A , B childหมายถึง node ที่เป็น subtree ของ tree อื่น child B , C , D , E
level 0 A level 1 B B C level 2 D E • level หมายถึงระยะทางจาก root จนถึง node นั้นๆ height หรือ depth ของ treeหมายถึง level สูงสุด ของ leaf บวกด้วย 1 depth = 2 + 1 = 3
A B B C D E F • sibling หมายถึงโหนดที่มี parent ร่วมกัน sibling ของ B คือ C sibling ของ D คือ E และ F
parents children leaves internal nodes depth degree(A) degree(B) degree(H) degree(C) degree(E) A, B, F 3 B, E, F, C, D, G, H, I 2 E, C, D, G, H, I 0 B, F 0 3 0
Exercise 1 A - node ที่เป็น parent - node ที่เป็น child - level ของ tree - height ของ tree - degree ของแต่ละโหนด - parent ของแต่ละโหนด - children ของแต่ละโหนด - sibling ของแต่ละโหนด C B H G E D F L I K J L 1.จาก tree ต่อไปนี้ จงหา - node ที่เป็น root - node ที่เป็น leaf - node ที่เป็น internal node
ต้นไม้แบบทวิภาค (binary tree) หมายถึง tree ที่แต่ละ node มีจำนวน subtree <= 2 ( แต่ละ node มี degree<= 2 )
Empty หรือ Null Tree
คุณลักษณะของต้นไม้แบบทวิภาคคุณลักษณะของต้นไม้แบบทวิภาค • ความสัมพันธ์ระหว่างความสูง(hight)และจำนวน node ใน binary tree กำหนดให้ hเป็นความสูงของ binary tree nเป็นจำนวน node ใน binary tree • ถ้าเรารู้ความสูง (h) ต้องสามารถหาจำนวน node (n)มากที่สุดและน้อยที่สุดที่เป็นไปได้ของ binary tree นั้นได้ • ถ้าเรารู้จำนวน node (n)ต้องสามารถหาความสูง (h) มากที่สุดและน้อยที่สุดที่เป็นไปได้ของ binary tree นั้นได้
A A B C B F G D E D • ถ้าเรารู้ความสูงของ binary tree = 3 nmax = 7 nmin = 3 จะได้ว่า nmax = 2h – 1 nmin = h
A A B C B C D D E E • ถ้าเรารู้ความจำนวน node ของ binary tree =5 hmax = 5 hmin = 3 จะได้ว่า hmin = log2n + 1 hmax = n
ต้นไม้ทวิภาคแบบสมบูรณ์ (complete binary tree) • คือ binary tree ที่มี node เต็มทุก level (ทุก node ที่ไม่ใช่ leaf มี child ทั้งด้านซ้ายและด้านขวา) nearly complete binary tree คือ binary tree ที่มี node เต็มทุก level ยกเว้น level สุดท้าย และ node ใน level สุดท้ายอยู่เรียงกันทางซ้ายมือ
การแทนต้นไม้แบบทวิภาคในคอมพิวเตอร์การแทนต้นไม้แบบทวิภาคในคอมพิวเตอร์ • binary tree สามารถแทนในคอมพิวเตอร์ได้ 2 แบบ คือ • การแทนโดยอาศัยอาร์เรย์ • ใช้อาร์เรย์ 3 อาร์เรย์ในการจัดเก็บ • ใช้อาร์เรย์ 1 มิติอาร์เรย์เดียวในการจัดเก็บ • การแทนโดยอาศัย pointer
การแทนโดยใช้อาร์เรย์ 3 อาร์เรย์ในการจัดเก็บ • จะใช้อาร์เรย์ที่มีขนาดเท่ากันจำนวน 3 ชุด คือ • data – เก็บข้อมูลในแต่ละ node • left – เก็บตำแหน่งของ node ลูกทางด้านซ้ายมือ • right – เก็บตำแหน่งของ node ลูกทางด้านขวามือ • ถ้า node ใดไม่มี node ลูก ให้เก็บค่า -1 (แทน NULL) • และใช้ตัวแปร root เก็บตำแหน่งของ node แรกใน tree
ตัวอย่าง ข้อมูลในหน่วยความจำ general binary tree root data left right A 1 1 A 2 3 2 B 6 4 B C 3 C 7 -1 4 E 8 5 5 H -1 -1 D E F 6 D -1 -1 7 F -1 -1 G H 8 G -1 -1
การแทนโดยใช้อาร์เรย์ 1 มิติอาร์เรย์เดียวในการจัดเก็บ • เหมาะกับโครงสร้างแบบ complete binary tree • โดยการกำหนดหมายเลขให้แต่ละ node ตั้งแต่ level 0 , 1 , … , k ตามลำดับ • ในแต่ละ level จะแทนตัวเลขจาก node ทางด้านซ้ายสุดไปถึงโหนดทางขวาสุด ตามลำดับ • ในการจัดเก็บต้องถือว่า tree ที่ต้องการจัดเก็บ เป็น complete binary tree
A B C D E F 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 A B C D E - - F - - - - - - - ตัวอย่าง general binary tree 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ข้อมูลในหน่วยความจำ
จะได้ความสัมพันธ์ระหว่าง tree และ อาร์เรย์ ดังนี้ • ถ้า binary tree มีความสูงเท่ากับ h จะต้องใช้อาร์เรย์ที่มีขนาด 2h – 1 ในการจัดเก็บ • parent ของโหนด i ใดๆ จะอยู่ที่ตำแหน่ง i/2 ถ้า i ไม่เท่ากับ 1 • left child ของโหนด i ใดๆ จะอยู่ที่ตำแหน่ง 2i • right child ของโหนด i ใดๆ จะอยู่ที่ตำแหน่ง 2i + 1
การแทนโดยอาศัย pointer • เป็นวิธีการจัดเก็บที่มีประสิทธิภาพ เนื่องจากไม่เกิดปัญหาการจองข้อมูลมากหรือน้อยเกินไป • โดยข้อมูลแต่ละ node ของ tree จะประกอบไปด้วย • data – เก็บข้อมูลในแต่ละ node • Lptr – เก็บ address ของ node ลูกทางด้านซ้ายมือ • Rptr – เก็บ address ของ node ลูกทางด้านขวามือ
การท่องต้นไม้ (binary tree traversal) • การเข้าถึงแต่ละโหนดในทรี ทีละโหนดจนครบทุกโหนด • เพื่อค้นหาโหนดที่ต้องการ, สร้างนิพจน์การคำนวณ ฯลฯ • การกำหนดวิธีในการ ท่อง อย่างมีแบบแผนที่ชัดเจน จะช่วยลดความสับสน, แน่ใจได้ว่าการค้นหาอย่างมีระบบและครบถ้วนทุกโหนด • วิธีที่ใช้ในการ ท่องไปใน tree ที่นิยมมี 2 วิธี คือ • breath-first Traversal • depth-first Traversal
breath-first Traversal - การท่องไปใน binary tree ทีละ level จากบนลงล่าง และจากซ้ายไปขวา • depth-firstTraversal- การท่องไปใน binary tree ลึกลงไปใน node ลูกด้านซ้ายหรือด้านขวาจนหมด แล้วจึงท่องไปในโหนดลูกอีกด้านที่เหลือ แบ่งได้เป็น 3 วิธี คือ
breath-first Traversal • เข้าถึงทีละโหนด • เริ่มจาก level 0 • level 1 จากซ้าย -> ขวา • level 2 จากซ้าย -> ขวา • ... result = ABECDF
preorder traversal • NLR(node,left,right) • เข้าถึงทีละโหนด • เข้าถึง root • ท่องแบบ preorder ที่ left subtree • ท่องแบบ preorder ที่ rightsubtree result = ABCDEF
inorder traversal • LNR(left,node,right) • เข้าถึงทีละโหนด • ท่องแบบ inorder ที่ left subtree • เข้าถึง root • ท่องแบบ inorder ที่ rightsubtree result = CBDAEF
postorder traversal • LRN(left,right, node) • เข้าถึงทีละโหนด • ท่องแบบ postorder ที่ left subtree • ท่องแบบ postorder ที่ rightsubtree • เข้าถึง root result = CDBFEA
ต้นไม้นิพจน์ (expression tree) • เราสามารถแทนนิพจน์ทางคณิตศาสตร์เช่น (a + b) * c ด้วยต้นไม้ เรียกว่าต้นไม้นิพจน์ (expression tree) โดยที่ • leaf แทนตัวถูกดําเนินการเช่น a, b และ c • root และ internal node แทนตัวดําเนินการ เช่น + และ * • ตัวดําเนินการหนึ่งๆ จะกระทํากับนิพจน์ย่อยที่แทนด้วยต้นไม้ย่อยต่างๆ ที่เป็นลูกของตัวดำเนินการนั้น • ดังนั้น จะไม่มีการเก็บเครื่องหมายวงเล็บลงในต้นไม้
+ * * / + C - 4 12 3 A B 5 2 ( 12 / 3 ) + ( 4 * ( 5 – 2 )) ( A + B ) * C
* + c a b expression tree Vs Traversal • นิพจน์ทางคณิตศาสตร์ สามารถเขียนได้ 3 รูปแบบ คือ infix , prefix , postfix เช่น (a + b) * c มี • infix • prefix • postfix • ซึ่งถ้าเราเปรียบเทียบกับ expression tree จะพบว่า • inorder traversal (LNR) • preorder traversal (NLR) • postorder traversal (LRN) (a + b) * c *+abc ab+c* infix prefix postfix (a + b) * c *+abc ab+c*
สร้างนิพจน์ prefix จาก expression tree algorithm prefix if (root is not null) print(root) prefix(root->leftSubtree) prefix(root->rightSubtree) return + * a + b c d
สร้างนิพจน์ postfix จาก expression tree algorithm postfix if (root is not null) postfix(root->leftSubtree) postfix(root->rightSubtree) print(root) return a b c + * d +
สร้างนิพจน์ infix จาก expression tree algorithm infix if (root is not null) if root is operand print(root) else print(open parenthesis) infix(root->leftSubtree) print(root) infix(root->rightSubtree) print(close parenthesis) return ( ( a * ( b + c ) ) + d )
สร้าง expression tree จากนิพจน์ postfix • อ่านนิพจน์เข้ามาทีละตัวอักษร • ถ้าข้อมูลที่อ่านเข้ามาเป็นoperand • สร้างtreeใหม่จากข้อมูลที่อ่านเข้ามา (เป็น tree ที่มีแค่โหนดเดียว) • push ลง stack • ถ้าข้อมูลที่อ่านเข้ามาเป็นoperator • pop ขึ้นมา 2 tree เชื่อมเป็น tree ใหม่โดยใช้ operator ที่อ่านเข้ามาเป็น root • push ลง stack
b a a stack stack a b c + * d + initial read a read b stack
* c + + a b b c c b a a stack stack stack a b c + * d + read c read + read *
+ * * d d + + a a b b c c stack stack a b c + * d + read d read + เมื่อหมดข้อมูล จะได้ผลลัพธ์ว่า tree ที่อยู่ในสแตกคือ expression tree
การบ้าน 1. จงแสดงผลลัพธ์ของการท่องต้นไม้ทั้งแบบ breath-first , preorder , inorder และ postorder A C B E F G D J K I L M H N O P Q
การบ้าน 2. จากนิพจน์แบบ postfix ดังต่อไปนี้ A B C + * D E F + – G H I + + / - 2.1 จงแสดงวิธีสร้าง expression tree 2.2 จาก expression tree จงเขียนนิพจน์แบบ infix 2.3 จาก expression tree จงเขียนนิพจน์แบบ prefix