Presentation is loading. Please wait.

Presentation is loading. Please wait.

A Binary Search Tree 17 1026 1462034 113137. Binary Search Trees.

Similar presentations


Presentation on theme: "A Binary Search Tree 17 1026 1462034 113137. Binary Search Trees."— Presentation transcript:

1 A Binary Search Tree 17 1026 1462034 113137

2 Binary Search Trees

3 An ordered tree ADT BSTs are ordered BSTs provide for fast retrieval and insertion BSTs also support sequential processing of elements

4 Definition of BST A Binary Search Tree (BST) is either 1. An empty tree, or 2. A tree consisting of a node, called the root, and two children called left and right, each of which is also a BST. Each node contains a value such that the root is greater than all node values stored in its left subtree and less than all values stored in the right subtree.

5 The BST invariant The invariant is the ordering property “less than goes left, greater than goes right.”

6 Not a BST: invariant is violated 17 1026 1461534 113137

7 Not a BST: subtree is not a BST 17 1026 1462028 113137

8 Binary Search Tree ADT Characteristics A Binary Search Tree ADT T stores data of some type (btElementType) Obeys definition of BST (see earlier slide)

9 BST ADT Prerequisites Prerequisites The data type btElementType must implement the < and == operators. (operator overloading)

10 BST ADT Operations isEmpty()// check for empty BST getData()// accessor insert()// inserts new node retrieve()// returns pointer to a BST left()// returns left child right()// returns right child

11 isEmpty bool T.isEmpty() Precondition: None. Postcondition: None. Returns: true if and only if T is an empty tree.

12 getData() btElementType T.getData() Precondition: !T.isEmpty() Postcondition: None. Returns: The data associated with the root of the tree

13 Insert() void T.insert(btElementType d) Precondition: !T.isEmpty(); T meets the BST invariant Postcondition: T.retrieve(d).getData() == d; T meets the BST invariant.

14 retrieve() BinaryTree T.retrieve(btElementType d) Precondition: T meets the BST invariant. Postcondition: T meets the BST invariant. Returns:if T contains a node with data d, then T.retrieve(d).getData() == d; otherwise, T.retrieve(d).isEmpty().

15 left() and right() BinaryTree T.left() Precondition: !T.isEmpty() Postcondtion: None. Returns: The left child of T BinaryTree T.right() Precondition: !T.isEmpty() Postcondtion: None. Returns: The right child of T

16 Where 12 would be inserted 17 1026 1462028 113137

17 After 12 inserted 17 1026 1462028 113137 12

18 BST class definition template class BST { public: BST(); bool isEmpty() const; // Precondition: None. // Postcondition: None. // Returns: true if and only if T is an empty tree

19 getData() btElementType getData() const; // Precondition: !this->isEmpty() // Postcondition: None // Returns: The data associated with the root of the tree

20 Insert() void insert(const btElementType & d); // Precondition: if d is a left child, then d must be getData(); // if d is a right child, then d must be > parent->getData(); // Postconditions: T->retrieve(d)->getData() == d

21 retrieve() BST * retrieve(const btElementType & d); // Precondition: none // Postcondition: none // Returns: if T contains a node matching d, // then T->retrieve(d)->getData() == d; otherwise, T->isEmpty()

22 left(), right() BST * left(); // Precondition: !this->isEmpty() // Postcondition: None // Returns: (a pointer to) the left child of T BST * right(); // Precondition: !this->isEmpty() // Postcondition: None // Returns: (a pointer to) the right child of T

23 private section private: bool nullTree; btElementType treeData; BST * leftTree; BST * rightTree; }; nullTree leftright treeData

24 Implementation: constructor template BST :: BST() { nullTree = true; leftTree = 0; rightTree = 0; } true 00 nullTree leftright ? treeData DANGER

25 isEmpty() template bool BST :: isEmpty() const { return nullTree; } true 00 nullTree leftright data treeData

26 getData() template btElementType BST :: getData() const { assert(!isEmpty()); return treeData; } true 00 nullTree leftright data treeData

27 insert() template void BST :: insert(const btElementType & d) { if (nullTree) { nullTree = false; leftTree = new BST; rightTree = new BST; treeData = d; } true false 00 nullTree leftright d treeData

28 insert (if not empty) else if (d == treeData) ; // do nothing -- it's already here! else if (d < treeData) leftTree->insert(d); // insert in left subtree else rightTree->insert(d); // insert in right subtree }

29 retrieve() template BST * BST :: retrieve(const btElementType & d) { if (nullTree || d == treeData) // return pointer to tree for which retrieve was called return this; else if (d < treeData) return leftTree->retrieve(d); // recurse left else return rightTree->retrieve(d); // recurse right }

30 left() template BST * BST :: left() { assert(!isEmpty()); return leftTree; } false nullTree leftright d treeData

31 right() template BST * BST :: right() { assert(!isEmpty()); return rightTree; } false nullTree leftright d treeData

32 Client of BST int main() { typedef BST intBST; typedef intBST * intBSTPtr; intBSTPtr b(new intBST); b->insert(17); b->insert(10); b->insert(26); b->insert(6); b->insert(14); b->insert(20); b->insert(28); b->insert(11); b->insert(31); b->insert(37); b->insert(12);

33 BST result 17 1026 1462028 113137 12

34 Retrieval // is 11 in the tree? intBSTPtr get11(b->retrieve(11)); if (get11->isEmpty()) cout << "11 not found.\n"; else cout << "11 found.\n"; // is 13 in the tree? intBSTPtr get13(b->retrieve(13)); if (get13->isEmpty()) cout << "13 not found.\n"; else cout << "13 found.\n"; return 0; }

35 17 1026 1462028 113137 12 11 found 13 not found

36 Reuse through inheritance Important OOP language features 1.Encapsulation: for abstractions like classes, types, objects. 2. Inheritance: abstractions can be reused 3. Polymorphism: statements that use more than one abstraction, with the language choosing the right one while the program is running.

37 “is-a” relations Defining one abstraction in terms of another. The Binary Tree ADT is a general class of which binary search trees are one type. Therefore, if we define a Binary Tree ADT we should be able to define a BST as a special case which inherits the characteristics of the Binary Tree ADT. A BST “is a” Binary Tree, with special features

38 Inheritance terminology Base class - the one from which others inherit Derived class - one which inherits from others So, the BST is a derived class of the Binary Tree base class.

39 Inheritance diagram BST BinaryTree

40 Implementing inheritance in C++ Base classes are designed so that they can be inherited from. One crucial aspect of inheritance is that the derived class may wish to implement member functions of the base case a little differently. Good examples are insertion for BST (which must follow the ordering principle) and constructors.

41 Virtual functions A virtual function is one which can be inherited. Base class functions should be virtual. Example: virtual BinaryTree* right();

42 Protected members We have used public and private sections of our class definitions. There is also ‘protected’. Protected means that the members are hidden from access (private) for everything except derived classes, which have public access rights. Derived classes can use the data members of base classes directly, without accessors

43 Example: Binary Tree ADT base

44 Binary Tree base class template class BinaryTree { public: BinaryTree();

45 isEmpty() and getData() virtual bool isEmpty() const; // Precondition: None. // Postcondition: None. // Returns: true if and only if T is an empty tree virtual btElementType getData() const; // Precondition: !this->isEmpty() // Postcondition: None // Returns: data associated with the root of the tree

46 insert() and retrieve() virtual void insert(const btElementType & d); // Precondition: none // Postconditions: this->getData() == d; !this->isEmpty() virtual BinaryTree * retrieve(const btElementType & d); // Precondition: none // Postcondition: none // Returns: this // Note: A useless stub, will be redefined by child class

47 left() and right() virtual BinaryTree * left(); // Precondition: !this->isEmpty() // Postcondition: None // Returns: (a pointer to) the left child of T virtual BinaryTree * right(); // Precondition: !this->isEmpty() // Postcondition: None // Returns: (a pointer to) the right child of T

48 makeleft() and makeRight() virtual void makeLeft(BinaryTree * T1); // Precondition: !this->isEmpty(); // this->left()->isEmpty() // Postcondition: this->left() == T1 virtual void makeRight(BinaryTree * T1); // Precondition: !this->isEmpty() // this->right()->isEmpty() // Postcondition: this->right() == T1

49 Binary tree class: protected section protected: bool nullTree; btElementType treeData; BinaryTree * leftTree; BinaryTree * rightTree; }; nullTree leftTreerightTree treeData

50 Public inheritance Inheritance notation is done like this class BST : public BinaryTree public means that BST client code must be able to access the public members of the base class. (public inheritance) It means that derived functions will only redefine member functions that they must (like insert() for BST). All other functions will be the public ones in the base class.

51 Derived class example: BST

52 BST class: the whole thing! template class BST : public BinaryTree { public: BST(); virtual void insert(const btElementType & d); virtual BinaryTree * retrieve(const btElementType & d); };

53 Why so short? The BST derived class definition was so short because it only needed to declare member functions that represented changes from the public functions of the base class. All other functions come from the already defined base class.

54 BST Derived Class Binary Tree Base Class public: protected: insert()retrieve() getData() retrieve() BinaryTree() isEmpty() insert() left() right() makeLeft() makeRight() nullTree treeData leftTreerightTree BST()

55 Derived class constructors To construct a BST we must first call the Binary Tree constructor (the base class) Once this has been called, then the body of the BST constructor can add additional things on to it. In this case, we have nothing to add (see next slide)

56 Constructor (inheritance) template BST :: BST() : BinaryTree () { }

57 Performance of binary trees Shape and balance are very important Short and wide trees are better than long and narrow ones. The depth of the tree is the main consideration in all traversal routines. Traversals are used by insertion and retrieval functions which must first look up a location in the tree. Examples using the preorder traversal

58 Reminder of the preorder traversal if the tree is not empty visit the root preOrderTraverse(left child) preOrderTraverse(right child)

59 A tree that is expensive to process 3 5 6 8

60 An efficient tree 14 620 9 712 3 14 18 1619 25 2227

61 Shallowest trees for n=1,3,7, and 15

62 Recurrence relation Let d stand for the depth of the tree (0,1,2...) The maximum number of nodes a balanced tree of a given depth can contain is given by the equation below (note recursive definition). With base case f(0) = 1 f(d) = f(d - 1) + f(d - 1) + 1 = 2f(d - 1) + 1

63 results f(0) = 1 f(1) = 3 f(2) = 7 f(3) = 15 f(4) = 31

64 Non-recursive recurrence relation

65 How many nodes as f(d)

66 How deep is a tree with n nodes? hence:

67 So, if a tree has n nodes, and is balanced, its depth can be approximated. Example: n = 37 2^5 = 32, 2^6 = 64 Therefore,the tree must be at least 5 levels deep, no less.

68 Analysis Earlier we talked about how an inorder BST can access data in sorted order using a preorder traversal. What is the efficiency of this kind of sort?

69 Efficiency of Treesort Placing all items in the tree: –There are n items –On average, if tree is balanced, it takes logn (log(base2)n) operations to find the place to insert each item. –Therefore, we have O(nlogn) To print it out is O(n) So the whole operation is O(nlogn) + O(n)

70 In the final analysis The total complexity of sorting and printing is O(nlogn) + O(n) Taking the highest order term we get O(nlogn) This is on the same order as Quicksort and Mergesort. - VERY FAST

71 Chapter Summary Tree represent data in a hierarchical manner. In a Binary Tree, each node has a left and a right child. Expression Trees are a Binary Tree that can represent arithmetic expressions. The data in a tree can be visited using in-order, pre-order, and post-order traversals. Function pointers can be used to pass one function to another as an argument. The Binary Search Tree is an ordered tree ADT.

72 Chapter Summary Binary Search Trees support efficient retrieval by key Inheritance can be used to model is-a relations. Inheritance can be implemented in C++ through base and derived classes. Inheritance supports code reuse. Binary Search Tree can have bad performance if they’re unbalanced, but very good performance when balanced. Treesort sorts a list using a Binary Search Tree.


Download ppt "A Binary Search Tree 17 1026 1462034 113137. Binary Search Trees."

Similar presentations


Ads by Google