Download presentation
Presentation is loading. Please wait.
Published byDeirdre Rodgers Modified over 9 years ago
1
Kruse/Ryba ch101 Object Oriented Data Structures Binary Trees Binary Search Trees Height Balance:AVL Trees Splay Trees
2
Kruse/Ryba ch102 Tournament Trees A common form of tree used in everyday life is the tournament tree, used to describe the outcome of a series of games, such as a tennis tournament. Alice Antonia Anita Abigail Amy Agnes Angela Audrey Alice Abigail Agnes Angela Alice Angela Alice
3
Kruse/Ryba ch103 A Family Tree Much of the tree terminology derives from family trees. Gaea Cronus Phoebe Ocean ZeusPoseidonDemeterPlutoLetoIapetus Persephone Apollo AtlasPrometheus
4
Kruse/Ryba ch104 Ancestor Tree An inverted family tree. Important point - it is a binary tree. Iphigenia ClytemnestraAgamemnon LedaTyndareusAeropeAtreus Catreus
5
Kruse/Ryba ch105 Characteristics of Trees A node with no children is a tree. Such a node is called a leaf. A leaf node has height zero.
6
Kruse/Ryba ch106 Characteristics of Trees A node with a non-empty collection of trees is a tree. The trees in the collection are known as the children of the node. The tree so constructed is in turn called the parent to the children trees. A tree with a non-empty set of children is called an interior node. The height of an interior node is one greater than the maximum height of any child.
7
Kruse/Ryba ch107 Characteristics of Trees There is a single node with no parent, called the root of the tree.
8
Kruse/Ryba ch108 root
9
Kruse/Ryba ch109 root interior
10
Kruse/Ryba ch1010 leaf root interior
11
Kruse/Ryba ch1011 leaf root interior height 0 interior height 2
12
Kruse/Ryba ch1012 Legal Trees Non-trees
13
Kruse/Ryba ch1013 Trees & Subtrees We will often talk of a subtree of a tree as if it is a tree.
14
Kruse/Ryba ch1014 Height versus Number of Nodes One of the most important characteristics of a binary tree is the number of nodes versus the height of a tree. Height 0 1 node 1 leaf Height 1 3 nodes 2 leaves Height 2 7 nodes 4 leaves
15
Kruse/Ryba ch1015 Thin and Unbalanced Trees The previous results were predicted on the tree being full. In a thin and unbalanced tree, the results need not hold. This tree has height 3, but only four nodes.
16
Kruse/Ryba ch1016 Complete Binary Tree One way to ensure full trees is to make the trees be complete. This means the difference between longest and shortest paths is 1, and nodes are filled "left to right". A B C D E F G H I J
17
Kruse/Ryba ch1017 Complete Examples
18
Kruse/Ryba ch1018 Examples: Not Complete
19
Kruse/Ryba ch1019 Height versus Number of Nodes A full binary tree of height h will have 2 h leaves. The number of nodes in a full binary tree of height n is 2 h+1 - 1
20
Kruse/Ryba ch1020 Tree Traversals Process a node. Recursively visit and process the left child. Recursively visit and process the right child. Lists and Vectors have an obvious traversal order. For trees there is no such obvious ordering. Traversals are formed out of different combinations of:
21
Kruse/Ryba ch1021 Four Important Traversals preorder: value, left child, right child inorder: left child, value, right child postorder: left child, right child, value level order: sibling nodes by "level" There are generally four important traversal orders:
22
Kruse/Ryba ch1022 Traversals 23 18 6 19 2122 42 35 56 Lets Practice
23
Kruse/Ryba ch1023 Expression Trees Built from simple operands and operators of an expression, placing the simple operands as the leaves of a binary tree with the operators as the interior nodes.
24
Kruse/Ryba ch1024 x := / + x - x - 0.5 b a 2 x b 2 c a 4 What is the expression ?
25
Kruse/Ryba ch1025 Linked Implementation template class Binary_tree { public: // Add methods here. protected: // Function prototypes here. Binary_node *root; };
26
Kruse/Ryba ch1026 template struct Binary_node { // data members: Entry data; Binary_node *left; Binary_node *right; // constructors: Binary_node(); Binary_node(const Entry &x); };
27
Kruse/Ryba ch1027 template Binary_tree ::Binary_tree() /* Post: An empty binary tree has been created. */ { root = NULL; }
28
Kruse/Ryba ch1028 template bool Binary_tree ::empty() /* Post: True returned if empty, false otherwise */ { return root == NULL; }
29
Kruse/Ryba ch1029 template class Binary_tree { public: Binary_tree(); bool empty() const; void preorder(void (*visit)(Entry &)); void inorder(void (*visit)(Entry &)); void postorder(void (*visit)(Entry &)); int size() const; void clear(); int height() const; void insert(const Entry &); Binary_tree (const Binary_tree &original); Binary_tree & operator = (const Binary_tree &original); ~Binary_tree(); protected: // Add auxiliary function prototypes here. Binary_node *root; };
30
Kruse/Ryba ch1030 Traversals as Recursive Procedures template void Binary_tree :: recursive_inorder(Binary_node *sub_root, void (*visit)(Entry &)) { if (sub_root != NULL) { recursive_inorder(sub_root->left, visit); (*visit)(sub_root->data); recursive_inorder(sub_root->right, visit); } }
31
Kruse/Ryba ch1031 Traversals as Recursive Procedures template void Binary_tree :: recursive_preorder(Binary_node *sub_root, void (*visit)(Entry &)) { if (sub_root != NULL) { (*visit)(sub_root->data); recursive_preorder(sub_root->left, visit); recursive_preorder(sub_root->right, visit); } }
32
Kruse/Ryba ch1032 Traversals as Recursive Procedures template void Binary_tree :: recursive_postorder(Binary_node *sub_root, void (*visit)(Entry &)) { if (sub_root != NULL) { recursive_postorder(sub_root->left, visit); recursive_postorder(sub_root->right, visit); (*visit)(sub_root->data); } }
33
Kruse/Ryba ch1033 A Binary Search Tree is a binary tree that is either empty or in which every node has a key (within its data entry) and satisfies the following conditions: The key of the root (if it exists) is greater than the key in any node in the left subtree of the root. The key of the root (if it exists) is less than the key in any node in the right subtree of the root. The left and right subtrees of the root are again binary search trees. Binary Search Tree
34
Kruse/Ryba ch1034 23 18 620 1922 42 35 56 Binary Search Tree No two entries may have equal keys
35
Kruse/Ryba ch1035 Three Points of View We can regard binary search trees as a new abstract data type with its own definition and its own methods Since binary search trees are special kinds of binary trees, we may consider their methods as special kinds of binary tree methods. Since the entries in binary search trees contain keys, and since they are applied for information retrieval in the same way as ordered lists, we may study binary search trees as a new implementation of the abstract data type ordered list.
36
Kruse/Ryba ch1036 The Solution template class Search_tree: public Binary_tree { public: Error_code insert(const Record &new_data); Error_code remove(const Record &old_data); Error_code tree_search(Record &target) const; private: // Add aux prototypes here. };
37
Kruse/Ryba ch1037 Tree Search Error_code Search_tree :: tree_search(Record & target) const; postcondition: If there is an entry in the tree whose key matches that in target, the parameter target is replaced by the corresponding record from the tree and a code of success is returned. Otherwise a code of not_present is returned.
38
Kruse/Ryba ch1038 Search_for_node Binary_node *Search_tree :: search_for_node(Binary_node *sub_root, const Record & target) const; Preconditions: sub_root is either NULL or points to a subtree of a Search_tree Postconditions: If the key of target is not in the subtree, a result of NULL is returned. Otherwise, a pointer to the subtree node containing the target is returned.
39
Kruse/Ryba ch1039 Recursive Version template Binary_node *Search_tree :: search_for_node( Binary_node * sub_root, const Record &target) const { if (sub_root == NULL || sub_root->data == target) return sub_root; else if (sub_root->data right, target); else return search_for_node(sub_root->left, target); }
40
Kruse/Ryba ch1040 Iterative Version template Binary_node *Search_tree :: search_for_node(Binary_node *sub_root, const Record &target) const { while (sub_root!=NULL && sub_root->data!=target) if (sub_root->data right; else sub_root = sub_root->left; return sub_root; }
41
Kruse/Ryba ch1041 tree_search() template Error_code Search_tree :: tree_search(Record &target) const { Error_code result = success; Binary_node *found = search_for_node(root, target); if (found == NULL) result = not_present; else target = found->data; return result; }
42
Kruse/Ryba ch1042 Insertion template Error_code Search_tree :: insert(const Record &new_data) { return search_and_insert(root, new_data); }
43
Kruse/Ryba ch1043 Tree Sort 23 14 17 29 26 10 23 14 17 29 26 10 14 17 23 26 29 Process: Build a binary search tree and then traverse in-order. Input Binary search tree Sorted List
44
Kruse/Ryba ch1044 23 18 620 1922 42 35 56 Removing a Node
45
Kruse/Ryba ch1045 Removing a Node 23 18 620 22 42 35 56 New Link
46
Kruse/Ryba ch1046 23 18 620 1922 42 35 How it looks after deletion?
47
Kruse/Ryba ch1047 23 18 620 1922 42 35 56 Removing a Node New Links One possible solution
48
Kruse/Ryba ch1048 23 6 20 1922 42 35
49
Kruse/Ryba ch1049 template Error_code Search_tree :: search_and_insert(Binary_node *&sub_root, const Record &new_data) { if (sub_root == NULL) { sub_root = new Binary_node (new_data); return success; } else if (new_data data) return search_and_insert(sub_root->left, new_data); else if (new_data > sub_root->data) return search_and_insert(sub_root->right, new_data); else return duplicate_error; }
50
Kruse/Ryba ch1050 template Error_code Search_tree :: remove(const Record &target) /* Post: If a Record with a key matching that of target belongs to the Search_tree, a code of success is returned and the corresponding node is removed from the tree. Otherwise, a code of not_present is returned. Uses: Function search_and_destroy */ { return search_and_destroy(root, target); }
51
Kruse/Ryba ch1051 template Error_code Search_tree :: search_and_destroy(Binary_node * &sub_root, const Record &target) { if (sub_root == NULL || sub_root->data == target) return remove_root(sub_root); else if (target data) return search_and_destroy(sub_root->left, target); else return search_and_destroy(sub_root->right, target); }
52
Kruse/Ryba ch1052 template Error_code Search_tree :: remove_root(Binary_node *&sub_root) { if (sub_root == NULL) return not_present; Binary_node *to_delete = sub_root; if (sub_root->right == NULL) sub_root = sub_root->left; else if (sub_root->left == NULL) sub_root = sub_root->right; else { // Neither subtree is empty. to_delete = sub_root->left; // Move left to find predecessor. Binary_node *parent = sub_root; // parent of to_delete while (to_delete->right != NULL) { parent = to_delete; to_delete = to_delete->right; } sub_root->data = to_delete->data; // Move from to_delete to root if (parent == sub_root) sub_root->left = to_delete->left; else parent->right = to_delete->left; } delete to_delete; // Remove to_delete from tree. return success; }
53
Kruse/Ryba ch1053 Building a Balanced BST 'a' 'b''c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 1 2 3 4 5 6 7 8 9 10 'k' 11 Whether creating from a list, vector or file it is not unreasonable to assume that the number of entries is know.
54
Kruse/Ryba ch1054 Building a BST 'a' 1 'c' 3 'e' 5 'g' 7 'i' 9 'b' 2 'd' 4 'f' 6 'h' 8 'j' 10 'k' 11 2020 0 1 2121
55
Kruse/Ryba ch1055 Building a BST 'a' 1 'c' 3 'e' 5 'g' 7 'i' 9 'b' 2 'd' 4 'f' 6 'h' 8 'j' 10 'k' 11 2020 0 1 2121 2 2
56
Kruse/Ryba ch1056 Building a BST 'a' 1 'c' 3 'e' 5 'g' 7 'i' 9 'b' 2 'd' 4 'f' 6 'h' 8 'j' 10 'k' 11 2020 0 1 2121 2 2 3 2323
57
Kruse/Ryba ch1057 Building a BST 'a' 1 'c' 3 'e' 5 'g' 7 'i' 9 'b' 2 'd' 4 'f' 6 'h' 8 'j' 10 'k' 11 2020 0 1 2121 2 2 3 2323
58
Kruse/Ryba ch1058 Buildable Tree template class Buildable_tree: public Search_tree { public: Error_code build_tree( const List &supply); private: // Add auxiliary function prototypes // here. };
59
Kruse/Ryba ch1059 template Error_code Buildable_tree :: build_tree(const List &supply) { Error_code ordered_data = success; // Fail if keys do not increase. int count = 0; // number of entries inserted so far Record x, last_x; List *> last_node; // pointers to last nodes on each level Binary_node *none = NULL; last_node.insert(0, none); // permanently NULL (for children of leaves)
60
Kruse/Ryba ch1060 while (supply.retrieve(count, x) == success) { if (count > 0 && x <= last_x) { ordered_data = fail; break; } build_insert(++count, x, last_node); last_x = x; } root = find_root(last_node); connect_trees(last_node); return ordered_data; // Report data-ordering problems to client. }
61
Kruse/Ryba ch1061 template void Buildable_tree ::build_insert(int count, const Record &new_data, List *> &last_node) { int level; // level of new node above the leaves for (level = 1; count % 2 == 0; level++) count /= 2; // Use count to calculate level of next_node. Binary_node *next_node = new Binary_node (new_data),*parent; // one level higher in last_node last_node.retrieve(level - 1, next_node->left); if (last_node.size() right == NULL) parent->right = next_node; }
62
Kruse/Ryba ch1062 And the root? template Binary_node *Buildable_tree :: find_root(List *> &last_node) { Binary_node *high_node; last_node.retrieve(last_node.size() - 1, high_node); // Find root in the highest occupied // level in last_node. return high_node; }
63
Kruse/Ryba ch1063 template void Buildable_tree :: connect_trees(const List *> &last_node) /* Pre: The nearly-completed binary search tree has been initialized. The List last_node has been initialized and contains links to the last node on each level of the tree. Post: The final links have been added to complete the binary search tree. Uses: Methods of class List */ { Binary_node *high_node, // from last_node with NULL right child *low_node; // candidate for right child of high_node int high_level = last_node.size() - 1, low_level;
64
Kruse/Ryba ch1064 while (high_level > 2) { // Nodes on levels 1 and 2 are already OK. last_node.retrieve(high_level, high_node); if (high_node->right != NULL) high_level--; // Search down for highest dangling node. else { // Case: undefined right tree low_level = high_level; // Find the highest entry not in the left subtree. do { last_node.retrieve(--low_level, low_node); } while (low_node != NULL && low_node->data data); high_node->right = low_node; high_level = low_level; } } }
65
Kruse/Ryba ch10 Obtaining Guaranteed Performance Operations on search trees are proportional to the length of the path from root to leaf. Unfortunately, in the worst case, this could be the same as the number of nodes in the tree (remember the thin unbalanced trees?) To assure good performance, we need a way to make sure our trees are relatively "full". 1 2 3 4 5 6
66
Kruse/Ryba ch10 Height Balance Property Associate with each node a value which is the difference between the longest path in the left child and the longest path in the right child. A tree is height balanced if this value is never smaller than -1 or larger than 1. 4:1 2:0 6:1 1:03:05:0 15:0 7:016:0 Key_balance_factor
67
Kruse/Ryba ch10 AVL Trees In 1962 two Russian mathematicians, G. M. Adel'son- Vel'skii and E. M. Landis, developed algorithms for the insertion and removal from height balanced trees so that the height balance property is maintained. The resulting binary search trees are named in their honor.
68
Kruse/Ryba ch10 AVL Trees The key insight is that height balance can be restored through rotation. For example, assume we have inserted the value 3 into a tree containing 1 and 2. 1:2 2:1 3:0 1:0 2:0 3:0
69
Kruse/Ryba ch10 Double Rotation Occasionally, a single rotation is not adequate. Consider the insertion of 15 into the following tree. 4:0 2:0 6:0 1:0 3:05:0 7:1 16:0
70
Kruse/Ryba ch10 Double Rotation The solution is a pair of rotations, called a double rotation 4:2 2:0 6:2 1:0 3:05:0 7:2 16:-1 15:0
71
Kruse/Ryba ch10 Double Rotation The solution is a pair of rotations, called a double rotation 4:2 2:0 6:2 1:0 3:05:0 7:2 16:-1 15:0 4:2 2:0 6:2 1:0 3:05:0 7:27:2 15:1 16:0 First: rotate the child subtree right.
72
Kruse/Ryba ch10 Double Rotation The solution is a pair of rotations, called a double rotation 4:2 2:0 6:2 1:0 3:05:0 7:27:2 15:0 16:0 4:1 2:0 6:1 1:0 3:05:0 15:0 16:07:0 Then, rotate the parent subtree left.
73
Kruse/Ryba ch10 Addition & Removal Algorithms Move down to the correct location where insertion is to be performed Insert new element, which may cause things to become unbalanced Move back up tree, performing rotations to make sure tree becomes balanced once again. The addition algorithm is then roughly as follows:
74
Kruse/Ryba ch1074 template struct AVL_node: public Binary_node { // additional data member: Balance_factor balance = equal_height; // constructors: AVL_node(); AVL_node(const Record &x); // overridden virtual functions: void set_balance(Balance_factor b); Balance_factor get_balance() const; };
75
Kruse/Ryba ch1075 template void AVL_node :: set_balance(Balance_factor b) { balance = b; } template Balance_factor AVL_node :: get_balance() const { return balance; }
76
Kruse/Ryba ch1076 template struct Binary_node { // data members: Entry data; Binary_node *left; Binary_node *right; // constructors: Binary_node(); Binary_node(const Entry &x); // virtual methods: virtual void set_balance(Balance_factor b); virtual Balance_factor get_balance() const; };
77
Kruse/Ryba ch1077 template class AVL_tree: public Search_tree { public: Error_code insert(const Record &new_data); Error_code remove(const Record &old_data); private: // Add auxiliary function prototypes here. };
78
Kruse/Ryba ch1078 template Error_code AVL_tree :: insert(const Record &new_data) /* Post: If the key of new_data is already in the AVL_tree, a code of duplicate_error is returned. Otherwise, a code of success is returned and the Record new_data is inserted into the tree in such a way that the properties of an AVL tree are preserved. Uses: avl_insert. */ { bool taller; return avl_insert(root, new_data, taller); }
79
Kruse/Ryba ch1079 template Error_code AVL_tree :: avl_insert(Binary_node *&sub_root, const Record &new_data, bool &taller) /* Pre: sub_root is either NULL or points to a subtree of the AVL_tree Post: If the key of new_data is already in the subtree, a code of duplicate_error is returned. Otherwise, a code of success is returned and the Record new_data is inserted into the subtree in such a way that the properties of an AVL tree have been preserved. If the subtree is increased in height, the parameter taller is set to true; otherwise it is set to false. Uses: Methods of struct AVL_node; functions avl_insert recursively, left_balance, and right_balance. */
80
Kruse/Ryba ch1080 { Error_code result = success; if (sub_root == NULL) { sub_root = new AVL_node (new_data); taller = true; } else if (new_data == sub_root->data) { result = duplicate_error; taller = false; } else if (new_data data) { // Insert in left subtree. result = avl_insert(sub_root->left, new_data, taller); if (taller == true) switch (sub_root->get_balance()) { // Change balance factors.
81
Kruse/Ryba ch1081 case left_higher: left_balance(sub_root); taller = false; // Rebalancing always shortens the tree. break; case equal_height: sub_root->set_balance(left_higher); break; case right_higher: sub_root->set_balance(equal_height); taller = false; break; }// end switch }// end insert in left subtree
82
Kruse/Ryba ch1082 else { // Insert in right subtree. result = avl_insert(sub_root->right, new_data, taller); if (taller == true) switch (sub_root->get_balance()) { case left_higher: sub_root->set_balance(equal_height); taller = false; break; case equal_height: sub_root->set_balance(right_higher); break; case right_higher: right_balance(sub_root); taller = false; // Rebalancing always shortens the tree. break; } } return result; }
83
Kruse/Ryba ch1083 template void AVL_tree :: rotate_left(Binary_node *&sub_root) /* Pre: sub_root points to a subtree of the AVL_tree. This subtree has a nonempty right subtree. Post: sub_root is reset to point to its former right child, and the former sub_root node is the left child of the new sub_root node. */ { if (sub_root == NULL || sub_root->right == NULL) cout *right_tree = sub_root->right; sub_root->right = right_tree->left; right_tree->left = sub_root; sub_root = right_tree; } }
84
Kruse/Ryba ch1084 template void AVL_tree :: right_balance(Binary_node *&sub_root) /* Pre: sub_root points to a subtree of an AVL_tree that is doubly unbalanced on the right. Post: The AVL properties have been restored to the subtree. Uses: Methods of struct AVL_node; functions rotate_right and rotate_left. */
85
Kruse/Ryba ch1085 { Binary_node *&right_tree = sub_root->right; switch (right_tree->get_balance()) { case right_higher: // single rotation left sub_root->set_balance(equal_height); right_tree->set_balance(equal_height); rotate_left(sub_root); break; case equal_height: // impossible case cout << "WARNING: program error detected in right_balance" << endl;
86
Kruse/Ryba ch1086 case left_higher: // double rotation left Binary_node *sub_tree = right_tree->left; switch (sub_tree->get_balance()) { case equal_height: sub_root->set_balance(equal_height); right_tree->set_balance(equal_height); break; case left_higher: sub_root->set_balance(equal_height); right_tree->set_balance(right_higher); break; case right_higher: sub_root->set_balance(left_higher); right_tree->set_balance(equal_height); break; } sub_tree->set_balance(equal_height); rotate_right(right_tree); rotate_left(sub_root); break; } }
87
Kruse/Ryba ch1087 Splay Trees Binary Search Trees that self-adjust to bring records closer to the root as they are more frequently accessed, allowing inactive records to drift slowly out toward the leaves.
88
Kruse/Ryba ch1088 zig T1T1 T2T2 T3T3 T4T4
89
Kruse/Ryba ch1089 zig T4T4 T3T3 T1T1 T2T2
90
Kruse/Ryba ch1090 zig T1T1 T2T2 T3T3 T4T4
91
Kruse/Ryba ch1091 T1T1 T2T2 T3T3 T4T4
92
Kruse/Ryba ch1092 T1T1 T2T2 T3T3 T4T4
93
Kruse/Ryba ch1093 T1T1 T2T2 T3T3 T4T4
94
Kruse/Ryba ch1094 Binary Tree Representation of General Trees An interesting fact to note is that binary trees can be used to represent general trees. A BC D EF G H I Left pointer is "eldest" child, right pointer is sibling. In this fashion, any tree can be written as a binary tree. A B E FG H I J CD J
95
Kruse/Ryba ch1095 General Tree A B E FG H I J CD A B C D GE F H I J
96
Kruse/Ryba ch1096 Postorder Tree Traversal template postTT ::postTT(node * root) // initialize postorder tree traversal iter { current = root; // slide left to find leftmost descendant while(true){ while (current && current->leftChild) current = current->leftChild; if (current -> rightChile) current = current->rightChild; else break; }}
97
Kruse/Ryba ch1097 Postorder Tree Traversal ++ template postTT & postTT ::operator ++() // increment for postorder traversal { node * child = current; current = current->parent; while(current && current->rightChild && current->rightChild != child){ current=current->rightChild; while(current->leftChild) //left slide current = current->leftChild;} return *this; //return ourselves }
98
Kruse/Ryba ch1098 Chapter 10 Fades Away
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.