tree - sci.feu.ac.thsci.feu.ac.th/faa/dsa/bookpdfs/chap6-binarytree.pdf · o binary search tree 6.1...

26
Tree เป็ นโครงสร ้างหลักอีกชนิดหนึ่งที่สามารถนามาใช ้ในการจัดการกับข ้อมูลได ้อย่างมี ประสิทธิภาพอีกรูปแบบหนึ่ง การจัดเก็บด ้วยการใช ้ tree ก็คล ้ายกับการจัดเก็บด ้วย Linked-List เพียงแต่มีเงื่อนไข และวิธีการในการจัดการที่ต่างกัน โดยทั่วไปในระบบปฏิบัติการ การจัดเก็บ ไฟล์มักจะใช ้ tree หรือโครงสร ้างที่มีรูปแบบคล ้ายกับ tree เป็ นตัวจัดเก็บ ในบทนี้เราจะมาทา ความรู้จักกับ tree ชนิดหนึ่งที่มีชื่อเรียกว่า Binary Tree หลังจากจบบทเรียนนี้แล ้ว ผู ้อ่านจะได ้ทราบถึง o โครงสร ้างของ Binary tree o การนาข ้อมูลเข ้าสูBinary tree o การเข ้าหา Binary tree ในรูปแบบของ o Pre-Order Traversal o In-Order Traversal o Post-Order Traversal o Level-Order Traversal o Binary Search Tree 6.1 ข้อมูลท ั ่วไปของ Tree โครงสร ้างที่มีหน ้าตาคล ้าย Tree โดยทั่วไปที่เราเห็นกันบ่อย ๆ ในการใช ้คอมพิวเตอร์มักจะเป็น โครงสร ้างที่แสดงถึงไฟล์ที่มีอยู่ในแฟ้มใดแฟ้มหนึ่ง (ถ ้าใช ้ Windows) และมีรูปร่างหน้าตา คล ้าย ๆ กับภาพที่เห็นนีภาพทางซ ้ายเป็ น Directory tree ที่เป็ นอยู่จริงใน Windows ส่วนภาพ ทางขวามือเป็นภาพจาลองจากภาพทางซ ้ายเพื่อให ้เห็นถึงโครงสร ้างที่มีส่วนคล ้ายกับ Tree จากโครงสร ้างของแฟ้มที่เห็น เรามีแฟ้ม Phoenix อยู่ด ้านบนสุด ถัดมาอีกระดับหนึ่งมีแฟ้ม 107221 แฟ้ม basic-java, และแฟ้ม bc221Book และภายในแฟ้ม basic-java เรามีแฟ้มอีกสอง แฟ้มคือ แฟ้ม Art และแฟ้ม Code สาหรับแฟ้ม bc221Book เรามีสี่แฟ้มคือ แฟ้ม PDF Format, PDF Format source basic-java Phoenix (E:) 107221 bc221Book Art Code pics Word Format Sample oneMore

Upload: others

Post on 19-Jun-2020

0 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Tree - sci.feu.ac.thsci.feu.ac.th/faa/dsa/bookPDFs/chap6-BinaryTree.pdf · o Binary Search Tree 6.1 ข้อมูลทั่วไปของ Tree โครงสร้างที่มีหน้าตาคล้าย

Tree เปนโครงสรางหลกอกชนดหนงทสามารถน ามาใชในการจดการกบขอมลไดอยางมประสทธภาพอกรปแบบหนง การจดเกบดวยการใช tree กคลายกบการจดเกบดวย Linked-List เพยงแตมเงอนไข และวธการในการจดการทตางกน โดยทวไปในระบบปฏบตการ การจดเกบไฟลมกจะใช tree หรอโครงสรางทมรปแบบคลายกบ tree เปนตวจดเกบ ในบทนเราจะมาท าความรจกกบ tree ชนดหนงทมช อเรยกวา Binary Tree หลงจากจบบทเรยนนแลว ผอานจะไดทราบถง o โครงสรางของ Binary tree o การน าขอมลเขาส Binary tree o การเขาหา Binary tree ในรปแบบของ

o Pre-Order Traversal o In-Order Traversal o Post-Order Traversal o Level-Order Traversal

o Binary Search Tree 6.1 ขอมลท วไปของ Tree โครงสรางทมหนาตาคลาย Tree โดยทวไปทเราเหนกนบอย ๆ ในการใชคอมพวเตอรมกจะเปนโครงสรางทแสดงถงไฟลทมอยในแฟมใดแฟมหนง (ถาใช Windows) และมรปรางหนาตา คลาย ๆ กบภาพทเหนน ภาพทางซายเปน Directory tree ทเปนอยจรงใน Windows สวนภาพทางขวามอเปนภาพจ าลองจากภาพทางซายเพอใหเหนถงโครงสรางทมสวนคลายกบ Tree

จากโครงสรางของแฟมทเหน เรามแฟม Phoenix อยดานบนสด ถดมาอกระดบหนงมแฟม 107221 แฟม basic-java, และแฟม bc221Book และภายในแฟม basic-java เรามแฟมอกสองแฟมคอ แฟม Art และแฟม Code ส าหรบแฟม bc221Book เรามสแฟมคอ แฟม PDF Format,

PDF Format

source

basic-java

Phoenix (E:)

107221 bc221Book

Art Code pics Word Format

Sample

oneMore

Page 2: Tree - sci.feu.ac.thsci.feu.ac.th/faa/dsa/bookPDFs/chap6-BinaryTree.pdf · o Binary Search Tree 6.1 ข้อมูลทั่วไปของ Tree โครงสร้างที่มีหน้าตาคล้าย

Binary Tree บทท 6

152

แฟม pics, แฟม source, และแฟม Word Format ในแฟม source เรามแฟม Sample ซงในแฟมนมแฟม oneMore อยอกหนงแฟม สวนแฟม Word Format นนไมมแฟมใดอยภายในเลย ถงแมวาการจดเกบไฟลทเหนจะมหนาตาคลายกบ Tree แตกยงไมใช Tree เสยทเดยว เนองจากวาภายในแฟมของ Windows ทเปน directory นนจะมแฟมอยอกสองแฟมคอ แฟม . และแฟม .. ซงเปนแฟมทอางถงตวเอง และอางถงแฟมทอยถดไปดานบน (parent directory) ซงผอานสามารถดไดจากการใชค าสง dir ใน Command prompt โดยทวไป Tree ประกอบไปดวย node หลาย ๆ ตวทเช อมตอกนดวย edge ดงแสดงใหเหนในภาพท 6.1

ภาพท 6.1 โครงสรางของ Tree โดยทวไป

กอนทเราพดถงโครงสรางหลกทใชในการจดการขอมลของ Tree เราควรทจะรถงนยามตาง ๆ ทใชใน Tree โดยทวไป ดงน Path หมายถง เสนทางจาก node ใด node หนงไปยง node สดทายทอยในเสนทางนน

Edge หมายถงเสนทางเชอมตอระหวาง node สอง node (บางครงเรยกวา link) Root หมายถง node ทอยบนสดใน tree นน ๆ ซงมเพยง node เดยวเทานน และเสนทางจาก node ใด ๆ ทอยใน tree ไปยง root จะมเพยงเสนทางเดยวเทานน Parent หมายถง node ทม node อน ๆ เชอมตอกบตวของมนเอง (ยกเวน root) ซง node ทเชอมตอนจะอยทางดานลางของ node ทเปน parent Child หมายถง node ทเชอมตอกบ node ทอยทางดานบน (node ลก) Leaf หมายถง node ทไมม node อน ๆ เชอมตออยทางดานลาง (no children) Sub-tree หมายถง กลมของ node ทอยใน tree โดยม node ใด node หนงเปน root Visiting หมายถง กระบวนการตาง ๆ ทสามารถกระท าไดใน tree นน ๆ เชน print คาของ node ใด node หนงหรอเปลยนคาของขอมลทเกบอยใน node นน ๆ กได Traversing หมายถงการเขาหา node ทมอยทก node ใน tree นน ๆ Level (หรอ height) หมายถงระดบชนของ tree วามกระดบ เชน ถา root เปนระดบ 0 ลก (children) ของ root กจะอยทระดบ 1 และหลานของ root จะอยทระดบ 2 เปนตน

Node

Edge

Page 3: Tree - sci.feu.ac.thsci.feu.ac.th/faa/dsa/bookPDFs/chap6-BinaryTree.pdf · o Binary Search Tree 6.1 ข้อมูลทั่วไปของ Tree โครงสร้างที่มีหน้าตาคล้าย

บทท 6 Binary Tree

153

Tree มรปรางหนาตาทแตกตางกนออกไป มากมายทงนกข นอยกบการออกแบบ และการก าหนดวา Tree ควรจะมรปรางทเหมาะสมกบการใชงานอยางไร ในบทนเราจะมาท าความรจกกบ Binary Tree ซงเปน Tree แบบหนงทมการน าไปใชในการจดเกบขอมลมากพอสมควร 6.2 Binary Tree

Binary tree เปน tree ท node แตละ node สามารถทจะมลก (children) ไดสงสด 2 node อยทางซายหนง node อยทางขวาหนง node และ node ทอยใน Binary tree ไมจ าเปนทจะตองมลกอยทงสองขางอาจมลกเพยงขางเดยวกได หรอไมจ าเปนตองมลกเลยกได ซงถาไมมลกอยเลยตวมนเองกคอ leaf node นนเอง ในการออกแบบ node ทตองใชส าหรบ Binary tree นนเราสามารถท าไดหลายแบบ ทงนกตองข นอยกบการใชงานของ Binary tree นน ส าหรบ node ทเราออกแบบนจะเปน node ทเกบขอมลตามความตองการของผใช ซงมโครงสรางดงน class BinaryNode<T extends Comparable> {

private T item;

private BinaryNode<T> left, right;

}

โครงสรางทไดออกแบบไว มสมาชกอยสามตวคอ ขอมลทอยใน node (item) ตวเชอม node ซาย (left) และตวเชอม node ขวา (right) เราไดท าการตดเอา code สวนอน ๆ ออกเพอใหเหนเฉพาะโครงสรางส าคญทงสามตวน (สมาชกอน ๆ ทเหลอเปน method ทท าหนาทตาง ๆ กน) ภาพท 6.2 แสดงถงโครงสรางของ node ทวาน

ภาพท 6.2 โครงสรางของ node ส าหรบใชใน Binary tree (L = left node, R = right node)

ในการน าขอมลเขาส node นนเรากอาจท าไดสองวธคอ 1) ผานทาง constructor และ 2) ผานทาง method ส าหรบการน าเขาทเราไดออกแบบนนเราใชทงสองวธ เพราะท าใหการน าขอมลเขาส node ของเรานนงายขน กอนทเราจะอธบายถงการท างานในสวนตาง ๆ เราไดน าเอา code ทงหมดของ BinaryNode มาใหดกอน

1: /**

2: Simple BinaryNode for Binary tree

3: */

4:

5: class BinaryNode<T extends Comparable> {

6: public T item;

7: public BinaryNode<T> left, right;

8:

9: //for empty node

10: BinaryNode() {

11: item = null;

12: left = right = null;

13: }

14:

15: BinaryNode(T item) {

16: this.item = item;

17: left = right = null;

18: }

19:

20: //assign data to this node and set

null หรอ node อน null หรอ node อน

item

L R

Page 4: Tree - sci.feu.ac.thsci.feu.ac.th/faa/dsa/bookPDFs/chap6-BinaryTree.pdf · o Binary Search Tree 6.1 ข้อมูลทั่วไปของ Tree โครงสร้างที่มีหน้าตาคล้าย

Binary Tree บทท 6

154

21: //left and right node to given nodes, respectively

22: BinaryNode(T item, BinaryNode<T> left, BinaryNode<T> right) {

23: this.item = item;

24: this.left = left;

25: this.right = right;

26: }

27:

28: //calculate number of nodes

29: public int size(BinaryNode<T> t) {

30: if(t == null)

31: return 0;

32: else

33: return size(t.left) + size(t.right) + 1;

34: }

35:

36: //calculate height

37: public int height(BinaryNode<T> t) {

38: if(t == null)

39: return -1;

40: else

41: return Math.max(height(t.left), height(t.right)) + 1;

42: }

43:

44: //print data of node in Pre-order fashion

45: public void preorderPrint() {

46: System.out.print(item + " ");

47: if(left != null) {

48: left.preorderPrint();

49: }

50: if(right != null) {

51: right.preorderPrint();

52: }

53: }

54:

55: //print data of node in In-order fashion

56: public void inorderPrint() {

57: if(left != null) {

58: left.inorderPrint();

59: }

60: System.out.print(item + " ");

61: if(right != null) {

62: right.inorderPrint();

63: }

64: }

65:

66: //print data of node in Post-order fashion

67: public void postorderPrint() {

68: if(left != null) {

69: left.postorderPrint();

70: }

71: if(right != null) {

72: right.postorderPrint();

73: }

74: System.out.print(item + " ");

75: }

76: }

เราม constructor สองตวคอ ตวทไมม parameter และตวทม parameter ซงมทใชตางกน คอ เราจะใช constructor ตวทไมม parameter เปนตวสราง node ทไมมขอมลอยเลย พรอมทงก าหนดให field ทงสอง (left และ right) มคาเปน null คอไมมการเชอมตอกบ node ใด ๆ เลย สวนตวทสอง เราก าหนดคาใหกบ field ทงสามของ node ตามสงทสงเขามาทาง parameter ซงกคอ ตวแรกเปนคาของขอมลทอยใน node สวนอกสองคาเปน node ทตองถกเชอมกบ node น ส าหรบ method ตวทอ น ๆ ทเหลออยนนเราจะไดอธบายในโอกาสตอไป หลงจากทมโครงสรางของ node เรยบรอยแลว เรากตองมาออกแบบโครงสรางของ Binary tree ทเราตองการใชในการจดการกบขอมลของเรา ซงส งส าคญทเราตองท านอกเหนอจากการน าขอมลเขากคอ การเชอม node ตาง ๆ เขาดวยกน เรามาดภาพของ Binary tree ทมการเชอม

node วามหนาตาอยางไร ถาน า node ทเราไดออกแบบมาใช

Page 5: Tree - sci.feu.ac.thsci.feu.ac.th/faa/dsa/bookPDFs/chap6-BinaryTree.pdf · o Binary Search Tree 6.1 ข้อมูลทั่วไปของ Tree โครงสร้างที่มีหน้าตาคล้าย

บทท 6 Binary Tree

155

ภาพท 6.3 โครงสรางของ Binary tree

ในการเขยน code ของ Binary tree ตามทเราไดออกแบบไวนนเรากไมตองท าอะไรมากเพยงแต เรยกใช constructor ของ node เปนตวจดการใหเรา ดงน

1: /**

2: Simple Binary tree

3: */

4:

5: class BinaryTree<T extends Comparable> {

6: private BinaryNode<T> root;

7:

8: //create an empty tree

9: BinaryTree() {

10: root = null;

11: }

12:

13: //tree with one node

14: BinaryTree(T item) {

15: root = new BinaryNode<T>(item, null, null);

16: }

17:

18: //calculate size of tree

19: public int size() {

20: return root.size(root);

21: }

22:

23: //calculate height of tree

24: public int height() {

25: return root.height(root);

26: }

27:

28: //make this tree with given data and

29: //connect its left and right to the given trees

30: public void makeTree(T item, BinaryTree<T> left, BinaryTree<T> right) {

31: root = new BinaryNode<T>(item, left.root, right.root);

32: }

33:

34: //return true if tree is empty

35: private boolean empty() {

36: if(root == null)

37: return true;

38: else

39: return false;

40: }

41:

root

item

L R

item

L R

item

L R

item

L R

null null null

null null

Page 6: Tree - sci.feu.ac.thsci.feu.ac.th/faa/dsa/bookPDFs/chap6-BinaryTree.pdf · o Binary Search Tree 6.1 ข้อมูลทั่วไปของ Tree โครงสร้างที่มีหน้าตาคล้าย

Binary Tree บทท 6

156

42: //print data of each node in tree

43: public void printBinaryTree() {

44: System.out.print("Items in tree: ");

45: if(!empty())

46: root.postorderPrint();

47: else

48: System.err.println("Sorry! Tree is empty.");

49: System.out.println();

50: }

51: }

จากไฟล BinaryTree.java เราจะเหนวาม constructor อยสองตวโดยตวแรกจะเปนตวสราง Binary tree ทม node ทไมมขอมลเพยง node เดยวเทานน (ซงเราเรยกวา root node) สวน constructor ตวทสองเราก าหนดใหเปน constructor ทน าขอมลเขาส node พรอมทงก าหนดให left และ right มคาเปน null ซงเราจะใชเปนตวเชอมกบ node อน ๆ ตอไป สวนการสราง Binary tree นนเราใช makeTree() เปนตวจดการใหเรา ซง makeTree() จะม parameter อยสามตวคอ

1. ขอมลของ node ใหมน (T item) 2. node ทอยทางดานซายของ node น (BinaryTree<T> left) 3. node ทอยทางดานขวาของ node น (BinaryTree<T> right)

และภายใน makeTree() เรากสราง node ขนมาใหมผานทาง constructor ของ BinaryNode ดงน root = new BinaryNode<T>(item, left.root, right.root);

ซงค าสงดงกลาวจะท าการสราง node ใหมทมขอมลเปน item และท าการเชอม left ของ node ใหมเขากบ root ของ node ทเขามา (node ทเขามามชอวา left ดงนนจงตองเรยก left.root) รวมทงเชอม right ของ node ใหมนเขากบ root ของ node ทเขามาดวยเชนกน เพราะฉะนนถาเราลองเรยก makeTree() ดวยขอมลน BinaryTree<Integer> t1 = new BinaryTree<Integer>();

BinaryTree<Integer> t2 = new BinaryTree<Integer>();

BinaryTree<Integer> t3 = new BinaryTree<Integer>(3);

BinaryTree<Integer> t4 = new BinaryTree<Integer>(4);

BinaryTree<Integer> t5 = new BinaryTree<Integer>();

BinaryTree<Integer> t6 = new BinaryTree<Integer>(6);

//connect those trees together

t5.makeTree(5, t6, new BinaryTree<Integer>());

t2.makeTree(2, t4, t5);

t1.makeTree(1, t2, t3);

โดยเราก าหนดให t1, t2, และ t5 เปน Binary tree ทไมมขอมลใด ๆ อยเลย กลาวคอ root

ของ Binary tree ทงสามมคาเปน null สวน t3, t4, และ t6 นนเราก าหนดใหมขอมลเปน 3, 4, และ 6 ตามล าดบ หลงจากนนเรากท าการเชอม node ตาง ๆ เหลานเขาดวยกนผานทางการเรยกใช makeTree() ภาพท 6.4 แสดงถง Binary tree ทเกดข นจากการสรางดวยขอมลตวอยางทกลาวถง

Page 7: Tree - sci.feu.ac.thsci.feu.ac.th/faa/dsa/bookPDFs/chap6-BinaryTree.pdf · o Binary Search Tree 6.1 ข้อมูลทั่วไปของ Tree โครงสร้างที่มีหน้าตาคล้าย

บทท 6 Binary Tree

157

ภาพท 6.4 Binary tree จากการสรางดวยขอมลตวอยาง (X หมายถง null)

ถาเราตองการทจะแสดงขอมลของ Binary tree ทเราไดสรางข นออกทางหนาจอ เรากใชค าสง

t1.printBinaryTree();

ซงกจะท าใหเราไดผลลพธดงน Items in tree: 4 6 5 2 3 1

และถาเราใชค าสง t2.printBinaryTree(); เรากจะไดผลลพธเปน

Items in tree: 4 6 5 2

ถาเราตองการทจะหาขนาด (size) ของ Binary tree เรากสามารถท าไดดวยการเขยน code ขนมานบจ านวนของ node ทมอยใน Binary tree ซงกไมยาก โดยภายใน class BinaryTree เรากเขยน method size() ดวยการเรยกใช size() ทมอยใน class BinaryNode ดงน public int size() {

return root.size(root);

}

สวนใน class BinaryNode เรากเขยน code ดงน public int size(BinaryNode<T> t) {

if(t == null)

return 0;

else

return size(t.left) + size(t.right) + 1;

}

ใน method size() ของ BinaryNode เราใชวธการของ Recursion เขามาชวยทงนเพราะเรารวา ขนาดของ Binary tree กคอขนาดของ Binary tree ทางดานซาย บวกกบขนาดของ Binary tree ทางดานขวา บวกกบตวมนเอง (ซงกคอ 1) และเรากรอกวาในการหา base case ของการนบจ านวน node นนเราตองตรวจสอบกบ null เพราะฉะนนทกครงทการเขาหา Binary tree ของเราเจอ null เรากสงคา 0 กลบท าใหการนบจ านวน node ของเราเปนการนบทถกตองเสมอ

root

1

2

5

3

6

4

Page 8: Tree - sci.feu.ac.thsci.feu.ac.th/faa/dsa/bookPDFs/chap6-BinaryTree.pdf · o Binary Search Tree 6.1 ข้อมูลทั่วไปของ Tree โครงสร้างที่มีหน้าตาคล้าย

Binary Tree บทท 6

158

อกส งหนงทเราอาจตองการหากคอ ความสงของ Binary tree (height) ซงวธการหากคลาย ๆ กบการหาขนาดของ Binary tree จะตางกนกตรงทเราตองสงคา -1 กลบในกรณของ base case ทงนกเพราะวาเรานบ node ทเปน root อยในระดบ 0 และเนองจากวา root ทอยใน Binary tree อาจมลกทงซายและขวา ดงนนเราจงจ าเปนทจะตองหาคาสงสดของลกทงสอง บวกกบ 1 ซงเปนคาของตว node root เอง ลองมาด code ของการหาความสงของ Binary tree ( height() ตวแรกอยใน class BinaryTree และ height() ตวทสองอยใน class BinaryNode public int height() {

return root.height(root);

}

public int height(BinaryNode<T> t) {

if(t == null)

return -1;

else

return Math.max(height(t.left), height(t.right)) + 1;

}

หลงจากทลองใช method ทงสองกบ Binary tree (t1) ทเราไดสรางขน ผลลพธทไดคอ Items in tree: 4 6 5 2 3 1

Size of Binary tree - t1 is 6

Height of Binary tree - t1 is 3

Binary tree ทเราไดกลาวถงเปน Binary tree แบบทวไปทไมมขอจ ากดหรอเงอนไขใด ๆ ในการน าขอมลเขา เราสามารถทจะน าขอมลเขาในลกษณะใดกได ทงนกตองข นอยกบผใชวาตองการสราง Binary tree ในลกษณะใด โดยสวนใหญแลวการน า Binary tree แบบนไปใชนนจะน าไปใชใน expression tree ซงเปนเรองของการออกแบบ compiler และการน าไปใชใน Huffman coding tree ซงเปนวธการบบอดขอมลแบบหนง 6.3 การเขาหา Binary tree การแสดงผลของขอมลทอยใน Binary tree ทเราไดเหนดานบนนเปนการแสดงผลดวยการเขาหาในรปแบบทเรยกวา Pre-order Traversal ซงเปนหนงในวธการเขาหา tree ทนยมใชกนพอสมควร อกสองวธทเหลอคอ In-order Traversal และ Post-order Traversal ในการเขาหา tree นนเมอเรามาถง node ทตองการแลว เราสามารถทจะท ากระบวนการตาง ๆ ทเราตองการไดเชน ดงขอมลของ node ออกพรอมกบแสดงผล หรอแมแตกระทงการลบ node นออกจาก tree 6.3.1 การเขาหาแบบ Pre-order การเขาหาแบบ Pre-order นนเราจะกระท ากระบวนการ (visiting) กบ node ทเราเจอกอน หลงจากนนเรากจะกระท ากบลกทงสองของ node ดวยวธการของ Recursion ดงขนตอนน

1. เรมกระบวนการกบ node (Visiting the node) 2. เดนทางเขาหาลกของ node ทางซาย (ดวยการเรยกตวเอง) 3. เดนทางเขาหาลกของ node ทางขวา (ดวยการเรยกตวเอง)

กระบวนการดงกลาวจะส นสดลงเมอ node ทก node ทอยใน tree ไดผานการเขาหาเรยบรอยแลว เรากลบมาด code ของการเขาแบบ Pre-order ทเราไดเขยนไวกอนหนานในการแสดงผลของ Binary tree public void preorderPrint() {

System.out.print(item + " ");

if(left != null)

left.preorderPrint();

if(right != null)

right.preorderPrint();

}

Page 9: Tree - sci.feu.ac.thsci.feu.ac.th/faa/dsa/bookPDFs/chap6-BinaryTree.pdf · o Binary Search Tree 6.1 ข้อมูลทั่วไปของ Tree โครงสร้างที่มีหน้าตาคล้าย

บทท 6 Binary Tree

159

จาก code ดานบนนจะเหนวาเราไดท ากระบวนการ "แสดงผล" ของ node ไปยงหนาจอกอน หลงจากนนเราจงเขาหาลกของ node นทางดานซาย หลงจากทลกของ node ทางดานซายไดรบการ "แสดงผล" แลวเรากเรมท าแบบเดยวกนกบลกของ node ทอยทางดานขวา สมมตวาเราใชการเขาหา tree แบบ Pre-order นกบ Binary tree ทเราสรางขนในภาพท 7.4 (ซงไดจ าลองมาใหดทางดานขวาของผลลพธ) พรอมกบใส code ส าหรบการ trace กระบวนการของ Pre-order Traversal เรากจะไดผลลพธดงน 1 Process child on the left of 1 2 Process child on the left of 2

4 Finish child on the left of 2 Process child on the right of 2 5 Process child on the left of 5 6 Finish child on the left of 5

Finish child on the right of 2 Finish child on the left of 1 Process child on the right of 1 3 Finish child on the right of 1 ผอานควรวเคราะหจากผลลพธทเหนกบโครงสรางของ Binary tree ทเราใชเปนตวอยาง เพอท าความเขาใจกบการเขาหาแบบ Pre-order ใหดย งข น 6.3.2 การเขาหาแบบ In-order การเขาหาแบบ In-order นเราจะกระท าการกบ node ระหวางการเขาหาลกของ node ทางซายและลกของ node ทางขวา ดงขนตอนน

1. เขาหา node ทางดานซาย (ดวยการเรยกตวเอง) 2. เรมกระบวนการกบ node (Visiting the node) 3. เขาหา node ทางดานขวา (ดวยการเรยกตวเอง)

ซง code ของการเขาหาแบบ In-order มดงน public void inorderPrint() {

if(left != null)

left.inorderPrint();

System.out.print(item + " ");

if(right != null)

right.inorderPrint();

}

และเมอเราลองใชการเขาหาแบบ In-order กบ Binary tree ตวเดยวกน เรากจะไดผลลพธ ดงน Process child on the left of 1

Process child on the left of 2

4

Finish child on the left of 2

2

Process child on the right of 2

Process child on the left of 5

6

Finish child on the left of 5

5

Finish child on the right of 2

Finish child on the left of 1

1

start node 1

3 2

5

6

4

start node

1

3 2

5

6

4

Page 10: Tree - sci.feu.ac.thsci.feu.ac.th/faa/dsa/bookPDFs/chap6-BinaryTree.pdf · o Binary Search Tree 6.1 ข้อมูลทั่วไปของ Tree โครงสร้างที่มีหน้าตาคล้าย

Binary Tree บทท 6

160

Process child on the right of 1

3

Finish child on the right of 1

6.3.3 การเขาหาแบบ Post-order การเขาหาแบบ Post-order นนเราจะท าการกบ node หลงจากทเราเสรจส นการเขาหาลกของ node ทงสองจนหมดแลว ดงขนตอนน

1. เดนทางเขาหาลกของ node ทางดานซาย (ดวยการเรยกตวเอง) 2. เดนทางเขาหาลกของ node ทางดานขวา (ดวยการเรยกตวเอง) 3. เรมกระบวนการกบ node (Visiting the node)

ดง code ทไดแสดงไวน public void postorderPrint() {

if(left != null)

left.postorderPrint();

if(right != null)

right.postorderPrint();

System.out.println(item);

}

และเมอใชกบ Binary tree ตวเดยวกน ผลลพธทไดคอ Process child on the left of 1

Process child on the left of 2

4

Finish child on the left of 2

Process child on the right of 2

Process child on the left of 5

6

Finish child on the left of 5

5

Finish child on the right of 2

2

Finish child on the left of 1

Process child on the right of 1

3

Finish child on the right of 1

1

หลาย ๆ คนอาจสงสยวาท าไมเราถงใช Recursion ในการเขยน code ส าหรบการเขาหาและอาจสงสยอกวา ไมใช Recursion ไดไหม ค าตอบกคอ ได เพราะโดยทวไปแลว compiler กใช Stack ในการจ าขนตอนการท างานของ Recursion เพราะฉะนนเรากสามารถทจะใช Stack มาเปนตวชวยในการเขยน code ส าหรบการเขาหา tree ได แตเนองจากวาการน าเอา Recursion เขามาใชท าใหการด code ทท างานจะท าไดงายขน ท าใหเหนภาพการท างานของ Algorithm อยางชดเจน เราคงจะจบเรองของการเขาหา tree ไวเพยงเทานกอน เราจะน าการเขาหาแบบตาง ๆ ซงรวมไปถงการเขาหาแบบ level-order มาใชกบ Binary Search Tree ตอไป

start node

1

3 2

5

6

4

Page 11: Tree - sci.feu.ac.thsci.feu.ac.th/faa/dsa/bookPDFs/chap6-BinaryTree.pdf · o Binary Search Tree 6.1 ข้อมูลทั่วไปของ Tree โครงสร้างที่มีหน้าตาคล้าย

บทท 6 Binary Tree

161

6.4 Binary Search Tree (BST) Binary tree ทเราจะมาท าความรจกเปนพเศษคอ Binary Search Tree ซงเปน Binary tree ทมขอก าหนดพเศษเฉพาะตวคอขอมลของ node ลกทอยทางซายของ node parent จะตองมคา นอยกวาคาของขอมลทอยใน node parent และ คาของขอมลทอยใน node ลกทอยทางขวาของ node parent จะมคามากกวาคาของขอมลทอยใน node parent ดงตวอยางของ tree ทแสดงใหเหนน

ภาพท 6.4 ตวอยาง Binary Search Tree ทมขอมลอย

ในการออกแบบ Binary Search tree นนเราไมจ าเปนทจะตองสราง class BinaryNode ขนมา

ใหม เราสามารถทจะใช BinaryNode ทเราไดสรางขนมากอนหนานไดเลย สวนทเราตองออกแบบ และสรางขนมาใหมคอ class BinarySearchTree ซงจะตองมกระบวนการน าขอมลเขาแบบใหม เนองจากขอก าหนดของ Binary Search tree ทมอย รวมไปถงกระบวนการอน ๆ ทจ าเปน เชน o การคนหาขอมล o การเขาหา BST

o การคนหา node ทมขอมลต าสด o การคนหา node ทมขอมลสงสด o การลบขอมลทก าหนดให o การลบ node ทมขอมลนอยทสด o การลบ node ทมขอมลมากทสด 6.4.1 การน าขอมลเขาส BST ในการน าขอมลเขาส BST นนเราตองตรวจสอบเงอนไขเสยกอนวาขอมลควรจะอยสวนไหนของ BST ซงตองตรวจสอบดวยกนสามเงอนไข คอ

1. BST ยงไมมขอมลใด ๆ อยเลย (empty) 2. ขอมลทตองน าเขานอยกวา node ณ ต าแหนงทท าการตรวจสอบ 3. ขอมลทตองน าเขามากกวา node ณ ต าแหนงทท าการตรวจสอบ

และอกเงอนไขหนงทเราอาจตองท า ถาเรากลววาขอมลทน าเขามอยใน BST แลว ซงเรากเพยงแตฟองผใชวาขอมลมอยใน BST เทานนเอง เรามาลองด code ของการน าขอมลเขากน public void insert(T item) {

root = insert(item, root);

}

53

72 30

14 39 61 84

9 23 34 47 79

Page 12: Tree - sci.feu.ac.thsci.feu.ac.th/faa/dsa/bookPDFs/chap6-BinaryTree.pdf · o Binary Search Tree 6.1 ข้อมูลทั่วไปของ Tree โครงสร้างที่มีหน้าตาคล้าย

Binary Tree บทท 6

162

private BinaryNode<T> insert(T item, BinaryNode<T> node) {

if(node == null)

node = new BinaryNode<T>(item);

else if(item.compareTo(node.item) < 0)

node.left = insert(item, node.left);

else if(item.compareTo(node.item) > 0)

node.right = insert(item, node.right);

else

;//item is already in tree!

return node;

}

เราใช Recursion ในการเขยน code กเพอทจะใหการด code นนท าไดงายขน ตามทเราไดพดไวในเรองของการน าขอมลเขาตามเงอนไข กลาวคอ ถา BST ไมมขอมลเรากเรยกใช

constructor ของ BinaryNode ถามขอมลอยกอนแลว และขอมลทตองการน าเขามคานอยกวาขอมลของ node ทเราตรวจสอบอยเรากท าการน าขอมลเขาทางดายซาย แตถามากกวาเรากน าขอมลเขาทางดานขวา ส าหรบการเขยน code ในรปแบบทไมใช Recursion นนเรากท าได ดงน //insert item into BST without using recursion

public void insert(T item) {

BinaryNode<T> node = new BinaryNode<T>(item);

//BST is empty

if(root == null)

root = node;

//at least there's one node in BST

else {

BinaryNode<T> walk = root;

BinaryNode<T> parent = new BinaryNode<T>();

//locate position for new node

while(walk != null) {

parent = walk;

if((node.item).compareTo(walk.item) < 0)

walk = walk.left; //must be in the left

else

walk = walk.right;//must be in the right

}

//found location; connect new node to this node

if((node.item).compareTo(parent.item) < 0)

parent.left = node;

else

parent.right = node;

}

}

การ insert node เขาส BST นนเราจ าเปนทจะตองตรวจสอบดวา คาของ node ทจะน ามาใสนน มากหรอนอยกวาคาของ node ทมอยแลวใน tree ถานอยกวาเรากตองใส node นทางดานซาย ถามากกวาเรากใส node นทางดานขวา เชนเดยวกนกบทเราท าการน าขอมลเขาดวยการใช

Recursion เรมตนดวยการสราง node ดวย object ทก าหนดไว BinaryNode<T> node = new BinaryNode<T>(item);

หลงจากนนก ตรวจสอบดวานเปนครงแรกทน าขอมลใสใน BST หรอไม ถาใช เรากเชอม node

root กบ node ใหมน แตถาไมใช (ม node อย) เรากตองหาต าแหนงทเหมาะสมของ node ใหมใน BST ของเรา

Page 13: Tree - sci.feu.ac.thsci.feu.ac.th/faa/dsa/bookPDFs/chap6-BinaryTree.pdf · o Binary Search Tree 6.1 ข้อมูลทั่วไปของ Tree โครงสร้างที่มีหน้าตาคล้าย

บทท 6 Binary Tree

163

if(root == null)

root = node;

//at least there's one node in BST

else {

BinaryNode<T> walk = root;

BinaryNode<T> parent = new BinaryNode<T>();

//locate position for new node

while(walk != null) {

parent = walk;

if((node.item).compareTo(walk.item) < 0)

walk = walk.left; //go left

else

walk = walk.right; //go right

}

}

เรมดวยการก าหนดให node walk ชไปท root เพอเอาไวใชส าหรบการเขาหา BST เราไมสามารถทจะใช root โดยตรงไดเพราะวา ในการเดนเขาหา BST นน เราเปลยนต าแหนงของ node ไปเรอย ๆ ซงถาใช root เปนตวเดน เรากไมสามารถน า BST กลบคนมาได เราใช node parent เปนตวเชอม node ใหมเขากบ BST ของเราเพราะฉะนน เราจ าเปนทจะตองจ าคาของ node walk ดวยการก าหนดให parent มคาเทากบ walk

เราท าการเปรยบเทยบคาของ item ท node walk ชอย กบคาของ item ของ node ใหม ถาคา item ของ node ใหม นอยกวา คาของ item ของ node walk เรากจะเดนไปทางซายจนกวาเราจะไปไมได (เทากบ null) แตถาคาของ node ใหมไมนอยกวาเรากจะเดนไปทางขวา จนไปไมได (เทากบ null เชนกน) ถาเราไปไมไดแลว ต าแหนงนจะเปนต าแหนงท เราตองเชอม node ใหมเขากบ BST ของเรา แตกอนทเราจะเชอม node ใหมเขาส BST เราตองตรวจดวาควรจะเชอม node ทางดานซาย หรอ ทางดานขวา //found location; connect new node to this node

if((node.item).compareTo(parent.item) < 0)

parent.left = node;

else

parent.right = node;

}

หลงจากทขอมลไดถก insert เขาส BST เปนทเรยบรอยแลว เรากสามารถทจะกระท ากระบวนการตาง ๆ ทเราท าได เชน การคนหาขอมล การแสดงขอมลทงหมดทมอยใน tree การลบ node ใด node หนงออกจาก tree หรอแมแตกระทงการน า node ใหมเขาส tree 6.4.2 การคนหาขอมลใน BST การคนหาขอมลใน BST นนท าไดไมยาก มนคลาย ๆ กบการคนหาขอมลใน Linked-List ทเรา

ไดเคยท ามากอนหนาน จะตางกน ตรงทเราตองเลอกทางคนหา วาจะเปนทางซาย หรอ ทางขวา ถาขอมลทตองการคนหามคานอยกวาขอมลทอยใน node ทท าการเปรยบเทยบ เรากคนไปทางซายเรอย ๆ ถาเจอเรากหยด แตถาไมเจอแสดงวา ขอมลนไมมอยใน BST เชนเดยวกนถาขอมลมากกวา หรอ เทากบขอมลของ node ทท าการเปรยบเทยบอย เรากคนไปทางขวาจนกวาจะเจอ ถาไปจนหมด node แลวไมเจอกแสดงวา ไมม node นในBST //search BST for a given data

public boolean search(T item) {

return search(item, root);

}

Page 14: Tree - sci.feu.ac.thsci.feu.ac.th/faa/dsa/bookPDFs/chap6-BinaryTree.pdf · o Binary Search Tree 6.1 ข้อมูลทั่วไปของ Tree โครงสร้างที่มีหน้าตาคล้าย

Binary Tree บทท 6

164

//internal search() for BST

private boolean search(T item, BinaryNode<T> node) {

while(node != null) {

if(item.compareTo(node.item) < 0)

node = node.left;

else if(item.compareTo(node.item) > 0)

node = node.right;

else

return true; //found item

}

return false; //no item found

}

การสงคากลบออกไปจาก method ของการคนหาอาจเปนการสงคาของขอมลทอยใน node นนออกไป หรอสงคา true เพอบอกวาขอมลมอยใน BST หรอ false เพอบอกวาไมมขอมลอยกได

ทงนกข นอยกบการใชงานของแตละคน ในทนเราจะใชการสงคา true หรอ false เราเรมตนดวยการเดนเขาหา BST ดวยการใช while loop พรอมกบท าการเปรยบเทยบขอมลของ node ทเราเจอกบขอมลทตองการคนหา ถาขอมลทตองการคนหามคานอยกวาขอมล ณ node นน ๆ เรากเดนทางเขาหาลกของ node ทางดานซาย แตถามากกวาเรากเดนเขาหาลกของ node นนทางดานขวา จนกวาจะเจอ หรอจนกวาเราจะเขาหา node ทมอยใน BST จนหมด ซงหมายถงการส นสดการคนหาทไมประสพผลส าเรจ

เราจะมาทดลองท าการน าขอมลเขาส BST พรอมทงแสดงขอมลทงหมดดวยการเขาทงสามแบบ (Pre-order, In-order, และ Post-order) ทเราไดพดถงกอนหนาน รวมไปถงการคนหาขอมลภายใน BST ดวย เราจะใชขอมลดานลางนเปนขอมลตวอยาง (ขอมลจากภาพท 6.4) 53 30 72 14 39 61 84 9 23 34 47 79

เราจะใชโปรแกรม BinarySearchTreeTest.java เปนโปรแกรมทดสอบ

1: /**

2: Testing module for binary search tree

3: */

4:

5: class BinarySearchTreeTest {

6: public static void main(String[] args) {

7: BinarySearchTree<Integer> t = new BinarySearchTree<Integer>();

8:

9: t.insert(53);

10: t.insert(30);

11: t.insert(72);

12: t.insert(14);

13: t.insert(39);

14: t.insert(61);

15: t.insert(84);

16: t.insert(9);

17: t.insert(23);

18: t.insert(34);

19: t.insert(47);

20: t.insert(79);

21:

22: System.out.println("Pre-order Traversal");

23: t.preOrderPrint();

24:

25: System.out.println("In-order Traversal");

26: t.inOrderPrint();

27:

28: System.out.println("Post-order Traversal");

29: t.postOrderPrint();

30:

31: Integer searchValue1 = new Integer(14);

32: if(t.search(searchValue1))

33: System.out.println("Found " + searchValue1);

34: else

35: System.out.println(searchValue1 + " Not found!");

36:

37: Integer searchValue2 = new Integer(66);

38: if(t.search(searchValue2))

Page 15: Tree - sci.feu.ac.thsci.feu.ac.th/faa/dsa/bookPDFs/chap6-BinaryTree.pdf · o Binary Search Tree 6.1 ข้อมูลทั่วไปของ Tree โครงสร้างที่มีหน้าตาคล้าย

บทท 6 Binary Tree

165

39: System.out.println("Found " + searchValue2);

40: else

41: System.out.println(searchValue2 + " Not found!");

42: }

43: }

ผลลพธทเราไดคอ Pre-order Traversal

Items in tree: 53 30 14 9 23 39 34 47 72 61 84 79

In-order Traversal

Items in tree: 9 14 23 30 34 39 47 53 61 72 79 84

Post-order Traversal

Items in tree: 9 23 14 34 47 39 30 61 79 84 72 53

Found 14

66 Not found!

ผอานควรสงเกตถงผลลพธทไดจากการเขาหา BST ทงสามแบบ โดยเฉพาะ การเขาหาแบบ In-order ทท าใหการแสดงผลขอมลทอยใน BST เปนการแสดงผลทเรมตนจากขอมลทนอยทสดไปหาขอมลทมากทสด 6.4.3 การเขาหาแบบ Level-Order

การเขาหาขอมลใน BST (หรอ tree แบบอน ๆ) ทเรยกวา level-order traversal นนจะท าการเขาหา node ทกตวในแตละชนกอนทจะเลอนระดบลงไป โดยเรมตนทระดบ 0 จนถงระดบลางสด ดงแสดงในภาพท 6.5

ภาพท 6.5 ทศทางการเขาหา BST แบบ Level-Order Traversal

เนองจากวาการเขาหาแบบนเปนการเขาหา node ลกทงสองของ BST (ถาม) ดงนนเราจงตองใช queue มาเปนตวชวยในการเกบต าแหนงของลกทงสองไว เพอเปน node เรมตนในการเขาหา node อน ๆ ในระดบทต าลงไป และเพอใหเปนการงายตอการท างานเราจะก าหนด class Queue ใหเปน class ทอยภายใน class BinarySearchTree โดยเราจะใช class LinkedList ของ Java เปนโครงสรางหลกของ Queue ซงม code ในการท างานทงหมดดงน

//internal queue for level-order print

class Queue<T> {

//use Java's LinkedList to keep track of nodes

private LinkedList<T> list = new LinkedList<T>();

//put node into queue

public void put(T object) {

list.addFirst(object);

}

53

72 30

14 39 61 84

9 23 34 47 79

Page 16: Tree - sci.feu.ac.thsci.feu.ac.th/faa/dsa/bookPDFs/chap6-BinaryTree.pdf · o Binary Search Tree 6.1 ข้อมูลทั่วไปของ Tree โครงสร้างที่มีหน้าตาคล้าย

Binary Tree บทท 6

166

//get node from queue

public T get() {

if(isEmpty())

return null;

return list.removeLast();

}

//empty?

public boolean isEmpty() {

return list.isEmpty();

}

}

ส าหรบ code ของ levelOrderPrint() นนเราก าหนดใหมโครงสรางดงน //level-order print

public void levelOrderPrint() {

//queue to keep track of nodes

Queue<BinaryNode<T>> q = new Queue<BinaryNode<T>>();

BinaryNode<T> current = root;//points to root of tree

//loop until all nodes have been processed

while(current != null) {

System.out.print(current.item + " ");

if(current.left != null) //add left child to queue

q.put(current.left);

if(current.right != null)//add right child to queue

q.put(current.right);

//get next node in queue

if(!q.isEmpty())

current = q.get();

else

current = null;

}

System.out.println();

}

การท างานของ levelOrderPrint() เรมดวยการสราง queue ทไมมขอมลใด ๆ และก าหนดให current เปน node ทช ไปยง root ของ tree หลงจากนนเราจะเขาหา node ทกตวใน tree ซงหลงจากทเราแสดงขอมลทอยใน current ไปยงหนาจอแลว (node แรกสดใน tree) เรากจะน า node ลกทอยทางซายและขวาของ current (ถาม) เขาส queue เพราะฉะนน node แรกสดท

อยใน queue จะเปน node ทอยทางซาย ถาเราใช tree จากภาพท 6.5 node นมคาเปน 30 และ node ทมคาเปน 72 จะเปน node ทอยถดไป ดงนนเมอเราดงเอาขอมลออกจาก queue เรากจะได node 30 เปน node ถดไปของการประมวลผล และเรากจะน าเอาลกทงสองของ node 30 เขาส queue (node 14 และ node 39) หลงจากนนเรากจะดงเอา node ทอยถดไปใน queue ออกซงกคอ node 72 พรอมกบการเอาลกทงสองของ node 72 เขาส queue ซงกคอ node 61 และ node 84 เราจะท ากระบวนแบบนไปจนกวา node ทกตวจะไดรบการประมวลผล จงออกจาก loop ซงเปนการจบกระบวนการทงหมดของ levelOrderPrint() และเมอเราได

ทดสอบดวยขอมลทอยใน tree จากภาพท 6.5 ผลลพธทเราไดคอ Level-order Traversal

53 30 72 14 39 61 84 9 23 34 47 79

การเขาหา tree แบบนมช ออกอยางหนงวา Breadth-First Traversal ซงเราจะกลบมาพดถงการเขาหาแบบนอกครงในเรองของ Graph 6.4.4 การคนหา node ทมขอมลนอยทสด การคนหา node ทมขอมลนอยทสดเปนการคนหาทงายพอสมควร เนองจากวาเราแทบจะไมตองเขยน code ใหซบซอนมากมายอะไร เพยงแตเดนเขา BST ไปทางซายจนกวา node ลกของ node ซายสดทเราเจอมคาเทากบ null เรากยตการเขาหาพรอมกบสงคาของขอมล ณ node กลบออกไป ดง code ทแสดงใหดน

Page 17: Tree - sci.feu.ac.thsci.feu.ac.th/faa/dsa/bookPDFs/chap6-BinaryTree.pdf · o Binary Search Tree 6.1 ข้อมูลทั่วไปของ Tree โครงสร้างที่มีหน้าตาคล้าย

บทท 6 Binary Tree

167

//search for node that has smallest value

public T findMin() {

return findMin(root);

}

//internal method for findMin()

public T findMin(BinaryNode<T> node) {

if(node != null) {

while(node.left != null)

node = node.left;

}

return node == null ? null : node.item;

}

6.4.5 การคนหา node ทมขอมลมากทสด

เชนเดยวกนกบการคนหา node ทมขอมลนอยทสดทเราไดแสดงใหดกอนหนาน เราไมตองท าอะไรมาก เพยงแตเดนเขาหา BST ไปทางขวาจนกวา node ลกของ node ทอยขวาสดมคาเปน null และเมอเจอเรากสงคา ณ node กลบออกไป ดง code ทแสดงใหดน //search for node that has biggest value

public T findMax() {

return findMax(root);

}

//internal method for findMax()

public T findMax(BinaryNode<T> node) {

if(node != null) {

while(node.right != null)

node = node.right;

}

return node == null ? null : node.item;

}

หลงจากทลองใช method ทงสองหาคาของ node ทนอยทสด และมากทสดใน BST ตวอยาง ผลลพธทเราได คอ Smallest node: 9

Biggest node: 84

6.4.6 การลบ node ออกจาก tree กระบวนการทเราจะดตอไป คอ การลบ node ออกจาก BST ซงการลบ node ออกจาก tree นนมขนตอนการท างาน ทยงยากพอสมควร เราจะตองค านงถงลกษณะของ node วาเปน node ในลกษณะใด เชน 1. เปน node ทไมมลกหลานอยเลย (leaf node) ในกรณท BST ไมมลกหลานอยเลย ส งทเราตองท ากคอ ก าหนดให parent ของ node ท

ตองการลบชไปท null (node ทตองการลบ = null) ดงแสดงในภาพท 6.6

Page 18: Tree - sci.feu.ac.thsci.feu.ac.th/faa/dsa/bookPDFs/chap6-BinaryTree.pdf · o Binary Search Tree 6.1 ข้อมูลทั่วไปของ Tree โครงสร้างที่มีหน้าตาคล้าย

Binary Tree บทท 6

168

(กอนลบ) (หลงลบ)

ภาพท 6.6 การลบ leaf node (node 9 และ node 34)

2. เปน node ทมลกอยเพยง node เดยว ถา node มลกเพยงแค node เดยวเรากก าหนดให parent ของ node ทตองการลบมคา

เทากบ ลกของ node น ดงแสดงในภาพท 6.7

(กอนลบ) (หลงลบ)

ภาพท 6.7 การลบ node (84) ทม node ลกเพยง node เดยว (79)

3. เปน node ทมลกอยครบทงค วธการลบ node ทมลกอยทงทางดานซาย และทางดานขวานน เราสามารถท าไดสองวธคอ

หา node ทมคามากทสดทางดานซายของ node ทตองการลบออกมาแทนท หรอหา node ทมคานอยทสดทางดานขวามาแทนท node ทตองการลบออก ไมวาจะใชวธไหน เรากยงคงรกษารปแบบและขอก าหนดของ BST ไว (ผอานควรวเคราะหดวยตวเองวาประโยคทกลาวนเปนจรง)

30

14 39

23 47 null null

30

14 39

23 47 9 34

72

61 84

79

72

61 79

Page 19: Tree - sci.feu.ac.thsci.feu.ac.th/faa/dsa/bookPDFs/chap6-BinaryTree.pdf · o Binary Search Tree 6.1 ข้อมูลทั่วไปของ Tree โครงสร้างที่มีหน้าตาคล้าย

บทท 6 Binary Tree

169

ภาพท 6.8 การลบ node ทม ลกอยทง 2 node (node 14 และ node 39)

สมมตวาเราตองการลบ node 30 ออกจาก tree ดวยการหา node ทมคามากทสดทาง

ดานซายมาแทนเรากจะได tree ดงทเหนน

ภาพท 6.9 การแทนท node ทถกลบออก (30) ดวย node ทางซาย (23)

แตถาเราใชวธแทนทดวย node ทมคานอยทสดทางดานขวาเรากจะได BST ดงน

ภาพท 6.10 การแทนท node ทถกลบออก (30) ดวย node ทางขวา (34)

30

14 39

23 47 9 34

23

14 39

47 9 34

34

14 39

23 47 9

Page 20: Tree - sci.feu.ac.thsci.feu.ac.th/faa/dsa/bookPDFs/chap6-BinaryTree.pdf · o Binary Search Tree 6.1 ข้อมูลทั่วไปของ Tree โครงสร้างที่มีหน้าตาคล้าย

Binary Tree บทท 6

170

6.4.7 การลบ node ทมคานอยทสด กอนทเราจะออกแบบ code ส าหรบการลบ node ออกจาก BST ตามเงอนไขทพดไวเรามาด การลบ node ทมคานอยทสดใน BST กนกอน เพราะเปนการลบทงายทสด และเรากจะน าเอาการลบ node ทมคานอยทสดนมาใชกบการลบ node ทมขอก าหนดตามเงอนไขทไดก าหนดไว //remove smallest node

public void removeMin() {

root = removeMin(root);

}

//internal method to remove smallest node

private BinaryNode<T> removeMin(BinaryNode<T> node) {

if(node == null) {

System.out.println("ERROR! BST is empty.");

return null;

}

else if(node.left != null) {

node.left = removeMin(node.left);

return node;

}

else {

return node.right;

}

}

เนองจากวา node ทมคานอยทสดนนจะอยทางดานซายสดของ BST และเปน node ทไมมลกอยทางดานซาย ดงนนการลบ node กเปนเพยงการเดนเขาหา node ทอยซายสดพรอมกบการจดจ า node ทไดเดนผานมาแลวใน BST ขนตอนในการลบ node ทมคานอยทสดเรมตนดวยการตรวจสอบวา BST ม node อยหรอไม ถามเรากตรวจสอบอกวาลกของ node ทอยทางดานซายเปน null หรอไม ถาไมเปนเรากเรยก removeMin() ดวย node ทอยทางดานซายนไปจนกวา node.left หรอลกของ node ทอยทางซายเปน null จาก code ทเหนดานบน ถาการท างานของ code มาถงประโยค else สดทายเรารทนทวาเราไดมาถง node ทมคานอยทสด เราจงสงคาของ parent ของ node ทมคานอยทสดนกลบออกไป ภาพท 6.11 และ 6.12 แสดงถง BST 2 ตวทม node ทมคานอยทสดทอยทางซาย และทอยทางขวา

ภาพท 6.11 ถาลบ node 9 node ทแทนคอ null ภาพท 6.12 ถาลบ node 14 node ทแทนคอ 23

การสงคากลบออกไปจาก removeMin() นนเราตองค านงถงกรณทงสองทไดกลาวถง สมมตวาเราลบ node 9 ในภาพท 6.11 ออกสงทเราตองก าหนดให left ของ node 14 กคอ null แตถาเราลบ node 14 ในภาพท 6.12 ออกสงทเราตองก าหนดให left ของ node 30 คอ node 23 ดงนนการสงคา node.right ในบรรทดสดทายจงเปนการเชอม node ทครอบคลมถงกรณทงสองไดเปนอยางด

30

14 39

23 47 34 null

30

23 39

47 9 34 null

Page 21: Tree - sci.feu.ac.thsci.feu.ac.th/faa/dsa/bookPDFs/chap6-BinaryTree.pdf · o Binary Search Tree 6.1 ข้อมูลทั่วไปของ Tree โครงสร้างที่มีหน้าตาคล้าย

บทท 6 Binary Tree

171

หลงจากททดสอบการลบ node ทมคานอยทสดทงสองกรณ (พรอมทงเพม code ส าหรบการ trace) เรากจะไดผลลพธดงน ผลลพธอนแรกเปนการลบ node 9 ในภาพท 6.11 สวนผลลพธทสองเปนการลบ node ในภาพท 6.12 (ขอมลทใชจรงตามภาพท 6.4) Smallest node: 9

Biggest node: 84

node = 53

node = 30

node = 14

node to be deleted = 9

node.left = null

node.right = null

returning node = 14

returning node = 30

returning node = 53

Items in tree: 14 23 30 34 39 47 53 61 72 79 84

Smallest node: 14

Biggest node: 84

node = 53

node = 30

node to be deleted = 14

node.left = null

node.right = BinaryNode@108786b returning node = 30

returning node = 53

Items in tree: 23 30 34 39 47 53 61 72 79 84

ผอานควรตรวจสอบถงผลลพธทไดทงสองเพอใหเขาใจถงการท างานของ removeMin() ไดดย งข น 6.4.8 การลบ node ทก าหนดใหออกจาก BST ในการลบ node ใด ๆ ออกจาก BST เราจ าเปนทจะตองค านงถงต าแหนงของ node ทเราตองการลบออก ทงนกเพราะวาเราจ าเปนทจะตองโยกยาย node อน ๆ ทเกยวของใหอยในต าแหนงทเหมาะสมเพอทจะรกษาคณสมบตของ BST ไว ดงกรณตาง ๆ ทงสามทไดกลาวไว กอนหนาน //remove a given node

public void remove(T item) {

root = remove(item, root);

}

//internal method to remove a given node

private BinaryNode<T> remove(T item, BinaryNode<T> node) {

if(node == null) {

System.out.println("ERROR! BST is empty");

System.exit(1);

}

if(item.compareTo(node.item) < 0) {

node.left = remove(item, node.left);

}

else if(item.compareTo(node.item) > 0) {

node.right = remove(item, node.right);

}

else if(node.left != null && node.right != null) {

node.item = findMin(node.right);

node.right = removeMin(node.right);

}

else

node = (node.left != null) ? node.left : node.right;

return node;

}

สงทเราตองท าส าหรบการลบ node คอการเดนเขาหา node ทมขอมลตามทเราตองการลบออก โดยเราจะเรมดวยการตรวจสอบวา BST นนมขอมลหรอไม ถาไมมการลบกยต แตถามเรากท าการคนหาขอมลทตองการลบออกทางดานซาย หรอทางดานขวาดวยวธการของ Recursion

Page 22: Tree - sci.feu.ac.thsci.feu.ac.th/faa/dsa/bookPDFs/chap6-BinaryTree.pdf · o Binary Search Tree 6.1 ข้อมูลทั่วไปของ Tree โครงสร้างที่มีหน้าตาคล้าย

Binary Tree บทท 6

172

ตามเงอนไขทก าหนดไว ถาเราเจอ node ทมลกอยทงสองดาน เรากก าหนดให node นมคาเทากบ node ทนอยทสดทอยทางขวาของ node นพรอมทงลบ node ทนอยทสดนออก แตถา node มลกอยเพยงตวเดยว เราตองดวาลกตวนเอยทางซายหรอไม ถาอยทางซายเรากก าหนดให node นเทากบ node ลกทางดานซายน แตถาไมใชเรากก าหนดให node นมคาเปน node ลกทางดานขวา หลงจากททดสอบดวยการลบ node 30 ออกจาก BST ในภาพท 6.4 เราไดผลลพธดงน node: 53 left node = 30

Found node to delete: 30

Find minimum node and set 30 to this node: 34

Remove minimum node

Return from removeMin(), set node.right to 39

return from node: 53

Items in tree: 9 14 23 34 39 47 53 61 72 79 84

เราเลอกทจะลบ node 30 กเพราะวาเราตองการทจะแสดงถงการลบ node ทมลกอยทงทางดานซายและทางดานขวา ภาพท 6.13 และ 6.14 แสดงถง BST กอนและหลงจากการลบ node 30

ภาพท 6.13 BST กอนการลบ node 30 ภาพท 6.14 BST หลงจากการลบ node 30

ขนตอนการท างานในสวนของการคดเลอก node ทจะมาแทนท node 30 นนเราใชการเลอก node ทมคาทนอยทสดทอยทางดานขวาของ node 30 ซงกคอ node 34 ดงนน BST ทเราได หลงจากการลบ node 30 แลวจงมหนาตาดงทเหน หากผอานตองการทจะใชการคดเลอกทเอา node ทมคามากทสดทางดานซาย (node 23 ในภาพ) มาแทนท node 30 กยอมทจะท าได เราไดรวบรวม code ทงหมดของ Binary Search Tree มาแสดงใหดอกครงหนง

1: /**

2: Binary Search Tree implementation

3: */

4:

5: import java.util.LinkedList;

6:

7: class BinarySearchTree<T extends Comparable<? super T>> {

8: protected BinaryNode<T> root;

9:

10: public BinarySearchTree() {

11: root = null;

12: }

13:

14: public void insert(T item) {

3. เปลยนคา node 30 ใหเปน 34

2. หา node ทนอยทสด (34)

1. เจอ node 30 ทตองการลบ

53

30

14 39

9 23 34 47

53

34

14 39

9 23 47

Page 23: Tree - sci.feu.ac.thsci.feu.ac.th/faa/dsa/bookPDFs/chap6-BinaryTree.pdf · o Binary Search Tree 6.1 ข้อมูลทั่วไปของ Tree โครงสร้างที่มีหน้าตาคล้าย

บทท 6 Binary Tree

173

15: root = insert(item, root);

16: }

17:

18: //insert item into BST (recursive version)

19: private BinaryNode<T> insert(T item, BinaryNode<T> node) {

20: if(node == null)

21: node = new BinaryNode<T>(item);

22: else if(item.compareTo(node.item) < 0)

23: node.left = insert(item, node.left);

24: else if(item.compareTo(node.item) > 0)

25: node.right = insert(item, node.right);

26: else

27: ;//item is already in tree!

28:

29: return node;

30: }

31:

32: //search BST for a given data

33: public boolean search(T item) {

34: return search(item, root);

35: }

36:

37: //internal search() for BST

38: private boolean search(T item, BinaryNode<T> node) {

39: while(node != null) {

40: if(item.compareTo(node.item) < 0)

41: node = node.left;

42: else if(item.compareTo(node.item) > 0)

43: node = node.right;

44: else

45: return true; //found item

46: }

47: return false; //no item found

48: }

49:

50: //search for node that has smallest value

51: public T findMin() {

52: return findMin(root);

53: }

54:

55: //internal method for findMin()

56: public T findMin(BinaryNode<T> node) {

57: if(node != null) {

58: while(node.left != null)

59: node = node.left;

60: }

61: return node == null ? null : node.item;

62: }

63:

64: //search for node that has biggest value

65: public T findMax() {

66: return findMax(root);

67: }

68:

69: //internal method for findMax()

70: public T findMax(BinaryNode<T> node) {

71: if(node != null) {

72: while(node.right != null)

73: node = node.right;

74: }

75: return node == null ? null : node.item;

76: }

77:

78: //remove smallest node

79: public void removeMin() {

80: root = removeMin(root);

81: }

82:

83: //internal method to remove smallest node

84: private BinaryNode<T> removeMin(BinaryNode<T> node) {

85: if(node == null) {

86: System.out.println("ERROR! BST is empty.");

87: return null;

88: }

Page 24: Tree - sci.feu.ac.thsci.feu.ac.th/faa/dsa/bookPDFs/chap6-BinaryTree.pdf · o Binary Search Tree 6.1 ข้อมูลทั่วไปของ Tree โครงสร้างที่มีหน้าตาคล้าย

Binary Tree บทท 6

174

89: else if(node.left != null) {

90: node.left = removeMin(node.left);

91: return node;

92: }

93: else {

94: return node.right;

95: }

96: }

97:

98: //remove a given node

99: public void remove(T item) {

100: root = remove(item, root);

101: }

102:

103: //internal method to remove a given node

104: private BinaryNode<T> remove(T item, BinaryNode<T> node) {

105: if(node == null) {

106: System.out.println("ERROR! BST is empty");

107: System.exit(1);

108: }

109: if(item.compareTo(node.item) < 0) {

110: node.left = remove(item, node.left);

111: }

112: else if(item.compareTo(node.item) > 0) {

113: node.right = remove(item, node.right);

114: }

115: else if(node.left != null && node.right != null) {

116: node.item = findMin(node.right);

117: node.right = removeMin(node.right);

118: }

119: else

120: node = (node.left != null) ? node.left : node.right;

121:

122: return node;

123: }

124:

125:

126: public void preOrderPrint() {

127: System.out.print("Items in tree: ");

128: if(root != null)

129: root.preorderPrint();

130: else

131: System.err.println("Sorry! Tree is empty.");

132: System.out.println();

133: }

134:

135: public void inOrderPrint() {

136: System.out.print("Items in tree: ");

137: if(root != null)

138: root.inorderPrint();

139: else

140: System.err.println("Sorry! Tree is empty.");

141: System.out.println();

142: }

143:

144: public void postOrderPrint() {

145: System.out.print("Items in tree: ");

146: if(root != null)

147: root.postorderPrint();

148: else

149: System.err.println("Sorry! Tree is empty.");

150: System.out.println();

151: }

152:

153: //level-order print

154: public void levelOrderPrint() {

155: //queue to keep track of nodes

156: Queue<BinaryNode<T>> q = new Queue<BinaryNode<T>>();

157: BinaryNode<T> current = root;//points to root

158:

159: //loop until all nodes have been processed

160: while(current != null) {

161: System.out.print(current.item + " ");

162: if(current.left != null) //add left child to queue

Page 25: Tree - sci.feu.ac.thsci.feu.ac.th/faa/dsa/bookPDFs/chap6-BinaryTree.pdf · o Binary Search Tree 6.1 ข้อมูลทั่วไปของ Tree โครงสร้างที่มีหน้าตาคล้าย

บทท 6 Binary Tree

175

163: q.put(current.left);

164: if(current.right != null) //add right child to queue

165: q.put(current.right);

166:

167: //get next node in queue

168: if(!q.isEmpty())

169: current = q.get();

170: else

171: current = null;

172: }

173: System.out.println();

174: }

175: }

176:

177: //internal queue for level-order print

178: class Queue<T> {

179: //use Java's LinkedList to keep track of nodes

180: private LinkedList<T> list = new LinkedList<T>();

181:

182: //put node into queue

183: public void put(T object) {

184: list.addFirst(object);

185: }

186:

187: //get node from queue

188: public T get() {

189: if(isEmpty())

190: return null;

191: return list.removeLast();

192: }

193:

194: //empty?

195: public boolean isEmpty() {

196: return list.isEmpty();

197: }

198: }

สรป เราไดท าความรจกกบโครงสรางของ Binary tree และกระบวนการตาง ๆ ทจ าเปนในการจดการกบขอมลทมอยใน Binary tree แบบตาง ๆ เชน การน าขอมลเขา การคนหาขอมล การดงขอมลออก การหาความสง เราไดพดถงโครงสรางของ Binary Tree ชนดพเศษคอ Binary Search

Tree โดยรวมแลวเราไดพดถง โครงสรางของ Binary tree โดยทวไป การเขาหา Binary tree แบบตาง ๆ เชน pre-order, in-order, post-order, และ level-

order โครงสรางของ Binary Search Tree การคนหาขอมลใน Tree

การน าขอมลเขา/ออก จาก Binary Search Tree แบบฝกหด 1. จงแสดงถงผลลพธของการเขาหา tree จากภาพดวย pre-order, in-order, และ post-

order

Page 26: Tree - sci.feu.ac.thsci.feu.ac.th/faa/dsa/bookPDFs/chap6-BinaryTree.pdf · o Binary Search Tree 6.1 ข้อมูลทั่วไปของ Tree โครงสร้างที่มีหน้าตาคล้าย

Binary Tree บทท 6

176

2. จากภาพในขอหนง ก. และ ข. จงวาดภาพของ tree ใหมถาเปลยนโครงสรางของ tree ดวย

การน าเอา BST มาใช 3. จงเขยน method ทท าหนาทนบจ านวนของ node ทเปน leaf node ทงหมดทอยใน

Binary Tree พรอมทงเขยนโปรแกรมทดสอบ 4. จงเขยน method ทท าหนาทนบจ านวนของ node ทก node ใน Binary Tree ทมลกเพยง

หนงตว พรอมทงเขยนโปรแกรมทดสอบ 5. จงเขยน method ทท าหนาทนบจ านวนของ node ทก node ใน Binary Tree ทมลกครบ

ทงค พรอมทงเขยนโปรแกรมทดสอบ 6. จากโจทยในขอสาม ใหเปลยนจาก Binary Tree เปน Binary Search Tree

7. จงเขยน method ทท าหนาทในการสลบขอมลของ node ซายขวาดงทแสดงใหดเปนตวอยางจากภาพดานลางน

8. จงเขยน method ทเขาหา tree ตามล าดบชนของ tree เชนถาเราเขาหา tree ในขอ 7

ผลลพธทไดคอ 1 2 3 4 5 6 7 8 (ภาพทางซาย) หรอ 1 3 2 6 5 4 8 7 (ภาพทางขวา) ให เขยนโปรแกรมทดสอบ

1

3

2

4

7

5 6

8

1

5

3

6

2

4

8 9 7

(ก) (ข)

1

5

3

6

2

4

8 7

1

5

2

4

3

6

7 8

เปลยนเปน