summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlshprung <lshprung@yahoo.com>2021-03-09 10:33:09 -0800
committerlshprung <lshprung@yahoo.com>2021-03-09 10:33:09 -0800
commitdef65eaddb4c3669daf67c766776b7025633d65d (patch)
tree84e749923828b12b4506933db2bbce7fc7b3606d
parent5c4bb344e9d23c8f5943160108f5f8730656edc0 (diff)
Post-class 03/09
-rw-r--r--03-02.md215
-rw-r--r--03-02_17.pngbin0 -> 81436 bytes
-rw-r--r--03-02_18.pngbin0 -> 46922 bytes
-rw-r--r--03-02_19.pngbin0 -> 40298 bytes
-rw-r--r--03-02_20.pngbin0 -> 34360 bytes
-rw-r--r--03-02_21.pngbin0 -> 22924 bytes
-rw-r--r--03-09.md550
-rw-r--r--03-09_1.pngbin0 -> 21227 bytes
-rw-r--r--03-09_10.pngbin0 -> 25319 bytes
-rw-r--r--03-09_11.pngbin0 -> 44674 bytes
-rw-r--r--03-09_12.pngbin0 -> 46834 bytes
-rw-r--r--03-09_13.pngbin0 -> 18374 bytes
-rw-r--r--03-09_2.pngbin0 -> 56305 bytes
-rw-r--r--03-09_3.pngbin0 -> 25855 bytes
-rw-r--r--03-09_4.pngbin0 -> 40027 bytes
-rw-r--r--03-09_5.pngbin0 -> 39222 bytes
-rw-r--r--03-09_6.pngbin0 -> 34866 bytes
-rw-r--r--03-09_7.pngbin0 -> 6382 bytes
-rw-r--r--03-09_8.pngbin0 -> 44083 bytes
-rw-r--r--03-09_9.pngbin0 -> 23741 bytes
20 files changed, 765 insertions, 0 deletions
diff --git a/03-02.md b/03-02.md
index d691839..d0c052e 100644
--- a/03-02.md
+++ b/03-02.md
@@ -514,3 +514,218 @@ void bag<Item>::insert(const Item& entry){
- For example consider insertion of keys 12, 10, 20, 9, 11, 10, 12, 12 in an empty Binary Search Tree
![diagram](03-02_16.png)
+
+## The erase_one member function
+
+- The `erase_one` member function: Remoes a specified item from a binary search tree
+ - Prototype: `bool erase_one(const Item& target);`
+
+- We implement the `erase_one` function with two auxiliary functions to reduce the complexity of implementation
+
+```
+template <class Item>
+bool bag<Item>::erase_one(const Item& target){
+ return bst_remove(root_ptr, target);
+}
+
+template <class Item>
+bool bst_remove(binary_tree_node<Item>*& root_ptr, const Item& target);
+
+template <class Item>
+void bst_remove_max(binary_tree_node<Item>*& root_ptr, Item& removed);
+```
+
+### bst_remove
+
+```
+template <class Item>
+bool bst_remove(binary_tree_node<Item>*& root_ptr, const Item& target);
+
+//Precondition: root_ptr is a root pointer of a binary search tree (or may be NULL for the empty tree
+//Postcondition: If target was in the tree, then one copy of target has been removed, root_ptr now points to the root of the new (smaller) binary search tree, and the function returns true. Otherwise, if target was not in the tree, then the tree is unchanged, and the function returns false
+
+template <class Item>
+bool bst_remove(binary_tree_node<Item>*& root_ptr, const Item& target){
+ binary_tree_node<Item> *oldroot_ptr;
+
+ if(root_ptr == NULL) return false;
+
+ if(target < root_ptr->data()) return bst_remove(root_ptr->left(), target); //target not yet found
+ if(target > root_ptr->data()) return bst_remove(root_ptr->right(), target); //target not yet found
+
+ if(root_ptr->left() == NULL){
+ ...
+ return true;
+ }
+
+ bst_remove_max(root_ptr->left(), root_ptr->data());
+
+ return true;
+}
+```
+
+- Employs a recursive implementation to remove the target
+- Handles these cases:
+ 1. Empty tree: return
+ 2. The target < root entry: make a recursive call to delete the target from the left subtree
+ 3. The target > root entry: make a recursive call to delete the target from the right subtree
+ 4. The target = root entry
+ - Case a) The root node has no left child
+ - Case b) The root node does have a left child
+
+**The root node has no left child**:
+
+- We can delete the root entry and make the right child the new root node
+
+```
+oldroot_ptr = root_ptr;
+root_ptr = root_ptr->right();
+delete oldroot_ptr;
+```
+
+- This scheme also works properly if there is no right child
+
+**The root node does have a left child**:
+
+- If there is no right child, then the left child can become the new root
+ - What if it has a right child? We need a better solution...
+
+- We need to find the largest entry in the left subtree and remove it
+
+- We want to design a more general solution
+ - To find some entry in the non-empty left subtree, and move this entry up to the root
+ - This case works even when the node to be deleted has a right child
+- Questino: How to find this entry?
+
+### bst_remove_max
+
+```
+template <class Item>
+void bst_remove_max(binary_tree_node<Item>*& root_ptr, Item& removed);
+
+//Precondition: root_ptr is a root pointer of a non-empty binary search tree
+//Postcondition: The largest item in the binary search tree has been removed, and root_ptr now points to the root of the new (smaller) binary search tree. The reference parameter, removed, has been set to a copy of the removed item
+```
+
+- Implementing the `bst_remove_max` function: Cases
+ 1. No right child: The largest item is at the root, so you can set `removed` equal to the data from the root, move the root pointer down to the left, and delete the root node
+ 2. There is a right child: There are larger items in the right subtree. In this case, make a recursive call to delete the largest item from the right subtree
+
+![diagram](03-02_17.png)
+
+## The erase member function
+
+- The `erase` member function: Removes all the occurrences of an item from a binary search tree
+ - Prototype: `bool erase(const Item& target)`
+
+```
+template <class Item>
+bool bag<Item>::erase(const Item& target){
+ return bst_remove_all(root_ptr, target);
+}
+
+template <class Item>
+bag<Item>::size_type bst_remove_all(binary_tree_node<Item>*& root_ptr, const Item& target);
+
+template <class Item>
+void bst_remove_max(binary_tree_node<Item>*& root_ptr, Item& removed);
+```
+
+### bst_remove_all
+
+```
+template <class Item>
+typename bag<Item>::size_type bst_remove_all(binary_tree_node<Item>*& root_ptr, const Item& target){
+ binary_tree_node<Item> *oldroot_ptr;
+
+ if(root_ptr == NULL) return 0;
+
+ if(target < root_ptr->data()) return bst_remove_all(root_ptr->left(), target);
+ if(target > root_ptr->data()) return bst_remove_all(root_ptr->right(), target);
+
+ if(root_ptr->left() == NULL){
+ ...
+ return 1;
+ }
+
+ bst_remove_max(root_ptr->left(), root_ptr->data());
+
+ return 1 + bst_remove_all(root_ptr, target);
+}
+```
+
+![diagram1](03-02_18.png)
+
+```
+if(root_ptr->left() == NULL){
+ //Target was found and there is no left subtree, so we can remove this node, amking the right child be the new root
+ oldroot_ptr = root_ptr;
+ root_ptr = root_ptr->right();
+ delete oldroot_ptr;
+ return 1;
+}
+```
+
+![diagram2](03-02_19.png)
+![diagram3](03-02_20.png)
+![diagram4](03-02_21.png)
+
+## The += member function
+
+```
+template <class Item>
+void bag<Item>::operator +=(const bag<Item>& addend){
+ if(root_ptr = addend.root_ptr){ //b += b
+ bag<Item> copy = addend;
+ insert_all(copy.root_ptr);
+ }
+
+ else insert_all(addend.root_ptr); //b += c
+```
+
+- Benefits from an auxiliary function `insert_all`
+- `insert_all` is actually another bag member function
+- The `insert_all` member function:
+
+```
+template <class Item>
+void bag<Item>::insert_all(binary_tree_node<Item>* addroot_ptr){
+ //Precondition: addroot_ptr is the root pointer of a binary search tree that is separate from the binary search tree of the bag that activated this method
+ //Postcondition: All the items from the addN's binary search tree have been added to the binary search tree of the bag that activated this method
+
+ if(addroot_ptr != NULL){ //Explicity uses the pre-order traversal of the tree
+ insert(addroot_ptr->data());
+ insert_all(addroot_ptr->left());
+ insert_all(addroot_ptr->right());
+ }
+}
+```
+
+### insert_all
+
+- We could also use the post-order traversal
+- Avoid in-order because:
+ - The nodes of the addend tree will be processed in order from smallest to largest
+ - These nodes will be inserted into the other bag from smallest to largest
+ - The resulting tree ends up with a single long, narrow path, with only right children
+ - Searching and other algorithms are inefficient when the trees lose their branching structure
+
+## Summary
+
+- Trees are a nonlinear structure
+- Applications such as:
+ - Organizing information (such as taxonomy trees)
+ - Implementing an efficient version of the bag class (using binary search trees)
+- Trees may be implemented with:
+ - Fixed-size arrays: Appropriate for complete binary trees
+ - Dynamic data structures
+- A tree traversal consists of processing a tree by applying some action to each node
+ - Using parameters that are functions, we can write extremely flexible tree traversals
+- Binary search trees are one common application of trees
+ - Permit us to store a bag of ordered items in a manner where adding, deleting, and searching for entries is potentially much faster with a linear structure
+- Operations on trees are good candidates for recursive thinking
+ - Because many tree operations include a step to process one or more sub-trees, and this step is "a smaller version of the same problem"
+
+---
+
+[03/09 ->](03-09.md)
diff --git a/03-02_17.png b/03-02_17.png
new file mode 100644
index 0000000..3b7c063
--- /dev/null
+++ b/03-02_17.png
Binary files differ
diff --git a/03-02_18.png b/03-02_18.png
new file mode 100644
index 0000000..0bb0309
--- /dev/null
+++ b/03-02_18.png
Binary files differ
diff --git a/03-02_19.png b/03-02_19.png
new file mode 100644
index 0000000..87cba30
--- /dev/null
+++ b/03-02_19.png
Binary files differ
diff --git a/03-02_20.png b/03-02_20.png
new file mode 100644
index 0000000..4b88261
--- /dev/null
+++ b/03-02_20.png
Binary files differ
diff --git a/03-02_21.png b/03-02_21.png
new file mode 100644
index 0000000..a76ac1f
--- /dev/null
+++ b/03-02_21.png
Binary files differ
diff --git a/03-09.md b/03-09.md
new file mode 100644
index 0000000..1ed6217
--- /dev/null
+++ b/03-09.md
@@ -0,0 +1,550 @@
+[\<- 03/02](03-02.md)
+
+# Balanced Trees
+
+## Heaps
+
+### Heap Storage Rules
+
+- **A binary tree where the entries of the nodes can be compared with the less-than operator of a strict weak ordering**
+- In addition:
+ - Heap is **a complete binary tree**, so that every level except the deepest must contain as many nodes as possible; and at the deepest level all the nodes are as far left as possible
+ - A **max-heap** is a **complete binary tree** in which the value in each internal node is greater than or equal to the values in the children of that node
+ - A **min-heap** is defined similarly
+
+### Heap Storage Rules
+
+![diagram](03-09_3.png)
+
+- A heap can be implemented with the binary tree nodes
+- As heap is a complete binary tree, **it can be easily implemented as an array**
+ - A fixed size array if we know the maximum size
+ - A dynamic array to grow and shrink the size
+
+### The Priority Queue with Heaps
+
+- In a **priority queue**:
+ - Entries are placed in the queue and later taken out
+ - Each entry in a priority queue can be compared with the other entries using a less-than operator
+ - The highest priority entries always leave first
+
+- In the heap implementations of a priority queue:
+ - Each node of the heap contains one entry
+ - Each entry can be compared to each of the other entries by the less-than operator
+
+### Adding an Entry to a Heap
+
+- Pseudocode for **adding an entry**
+ 1. **Place the new entry in the heap in the first available location**. This keeps the structure as a complete binary tree, but it might no longer be a heap since the new entry's parent might be less than the new entry
+ 2. **while (the new entry's parent is less than the new entry)** swap the new entry with its parent
+
+![diagram](03-09_4.png)
+
+- **Re-heapification Upward**:
+ - The "new entry rising" stop when the new entry has a parent with a higher or equal priority, or when the new entry reaches the root
+
+### Removing an Entry from a Heap
+
+- **Always remove the entry with the highest priority**: The entry that stands "on top of the heap"
+- Pseudocode for Removing an Entry
+ 1. Copy **the entry at the root** of the heap to the variable that is used to return a value
+ 2. Copy the **last entry in the deepest level to the root**, and then take this last node out of the tree; This entry is called the "out-of-place" entry
+ 3. while (the out-of-place entry is less than one of its children) swap the out-of-place entry with its highest child
+ 4. Return the answer that was saved in step 1
+
+### Adding an Entry to a Heap
+
+![diagram](03-09_5.png)
+![diagram](03-09_6.png)
+
+---
+
+# The STL Priority Queue and the Heap Algorithms
+
+## Heaps
+
+### The STL Priority Queue
+
+- The STL includes a priority queue class
+
+```
+template <class T, class Container = std::vector<T>, class Compare = std::less<typename Container::value_type>>
+class priority_queue;
+```
+
+- `T`
+ - Type of the elements
+
+- `Container`
+ - Type of the internal *underlying container* object where the elements are stored
+
+- `Compare`
+ - A binary predicate that takes two elements (of type `T`) as arguments and returns a `bool`
+
+- The container:
+ - May be any of the standard container class templates or some other specifically designed container class
+ - Shall be accessible through random access iterators and support the following operations: `empty()`, `size()`, `front()`, `push_back()`, `pop_back()`
+- The standard container classes `vector` and `deque` fulfill these requirements
+
+- Some Member functions:
+ - `pop()`: Removes the **highest priority** item of the priority queue
+ - `push(const Item& entry)`: Adds an item to the priority queue
+ - `top()`: Returns the **highest priority** item of the queue (without removing it)
+
+- **Note**: The `top()` prototype is: `const value_type& top() const;`
+ - It cannot be used to change the top item
+ - The `top()` member function effectively calls member `front` of the underlying container object
+
+```
+#include <iostream> //std::cout
+#include <queue> //std::priority_queue
+
+int main(){
+ std::priority_queue<int> mypq;
+
+ mypq.push(30);
+ mypq.push(100);
+ mypq.push(25);
+ mypq.push(40);
+
+ std::cout << "Popping out elements...";
+ while(!mypq.empty()){
+ std::cout << ' ' << mypq.top();
+ mypq.pop();
+ }
+ std::cout << '\n';
+
+ return 0;
+}
+
+---
+Output:
+Popping out elements... 100 40 30 25
+```
+
+---
+
+# AVL Tree
+
+## The Problem of Unbalanced Trees
+
+- Assume we add 1,2,3,4 and 5 to a **binary search tree**
+
+![diagram](03-09_7.png)
+
+- We are no better off than the linked-list implementation
+
+- BST's worst-case performance is closest to linear search algorithms, that is O(n)
+- As we cannot predict data pattern and their frequencies, a need arises to balance out the existing BST
+- An AVL tree is a **self-balancing** binary search tree
+ - The first invented self-balancing tree
+- **The heights of the two child subtrees of any node differ by at most one**
+- If at any time they differ by more than one, rebalancing is done to restore this property
+- Lookup, insertion, and deletion all take O(log(n)) time in both the average and worst cases
+- Insertions and deletions may require the tree to be rebalanced **by one or more tree rotations**
+
+## Balance Factor
+
+- The **Balance Factor** of node `n` is defined as
+
+```
+BalanceFactor(n) = Height(LeftSubtree(n)) - Height(RightSubtree(n))
+```
+
+- A binary tree is called **AVL tree** if the following invariant holds for every node `n` in the tree:
+ - -1 <= BalanceFactor(n) <= 1
+
+![diagram](03-09_8.png)
+
+## Rotation
+
+- An AVL tree may perform the following four kinds of rotations to balance itself:
+ - Left rotation (single rotation)
+ - Right rotation (single rotation)
+ - Left-Right rotation (double rotation)
+ - Right-Left rotation (double rotation)
+
+### Left Rotation
+
+- If a tree becomes unbalanced, when a node is inserted into the **right subtree of the right subtree**
+- Left rotation: Swaps the parent node with its right child
+
+![diagram](03-09_9.png)
+
+```
+template <class Item>
+binary_tree_node<Item>* left_rotation(binary_tree_node<Item>*& parent){
+ binary_tree_node<Item>* temp;
+ temp = parent->right();
+ parent->set_right(temp->left());
+ temp->set_left(parent);
+ return temp;
+}
+```
+
+### Right Rotation
+
+- If a tree becomes unbalanced, when a node is inserted into the **left subtree of the left subtree**
+- Right rotation: Swaps the parent node with its left child
+
+![diagram](03-09_10.png)
+
+```
+template <class Item>
+binary_tree_node<Item>* right_rotation(binary_tree_node<Item>*& parent){
+ binary_tree_node<Item>* temp;
+ temp = parent->left();
+ parent->set_left(temp->right());
+ temp->set_right(parent);
+ return temp;
+}
+```
+
+### Left-Right Rotation
+
+- A node has been inserted into the right ubstree of the left subtree
+- Note: B < C < A -> C becomes the new parent
+
+![diagram](03-09_11.png)
+
+### Right-Left Rotation
+
+- A node has been inserted into the left ubstree of the right subtree
+- Note: A < C < B -> C becomes the new parent
+
+![diagram](03-09_12.png)
+
+## Trees, Logs, and Time Analysis
+
+- Both heap and AVL control the depth
+- The worst-case time performance for the following operations are all O(d), where d is the depth of the tree:
+ - Adding an entry in a binary search tree or a heap
+ - Deleting an entry from a binary search tree or a heap
+ - Searching for a specified entry in a binary search tree
+
+### Time Analysis for Binary Search Tree
+
+- A **BST** with `n` nodes has at most depth `n-1`
+- Adding an entry, deleting an entry, or searching for an entry in a binary search tree with n entries is: O(d)
+ - where d is the depth of the tree
+
+### Time Analysis for Heaps
+
+- Number of entries at level d is 2^d
+- For a **heap** with d levels we need at least the following number of nodes: 2^d
+- What is the maximum depth of a heap with `n` nodes?
+ - A heap with depth d needs at least 2^d nodes, therefore: 2^d <= n, d <= log2(n)
+- Adding or deleting an entry in a heap with n entries is O(d), where d is the depth of the tree
+- The operations are O(log2(n))
+
+### Logarithm Rules
+
+![diagram](03-09_13.png)
+
+## Summary
+
+- A **heap** is a complete binary tree that follows the rule that the entry at any node is never less than any of its children
+ - Provides an efficient implementation of **priority queues**
+- The STL includes a priority queue class as well as algorithms for building and manipulating heaps
+- The tree algorithms that we have seen for binary search trees, heaps, and B-trees **all have worst-case time performance of O(d)**, where **d is the depth of the tree**
+- The depth of a heap is never more than O(log(n)), where n is the number of nodes
+
+---
+
+# Appendix 1: The STL Multiset Class and Its Iterator
+
+## The Multiset Template Class
+
+- A **multiset** is an STL class similar to our bag, it permits a collection of items to be stored, **where each item may occur multiple times** in the multiset
+- The value of an element also identifies (the value is itself the **key**) - the keys are used to order the items
+- The elements in a multiset are always sorted following a specific strict weak ordering criterion indicated by its internal comparison object
+- Sets and Multisets are typically implemented as **binary search trees**
+- Another STL class, the **set** class, has the same interface as the multiset class, except that **it stores elements without repetition**, additional insertions of an element that is already in a set will have no effect
+- A program that uses multisets or sets must include the header file `<set>`
+
+---
+
+# Inheritance
+
+- Inheritance is the 4th principle of OOP
+- In this presentation, we discuss abstract and derived classes and principles of inheritance
+
+- One of the 4 major principles that make a language Object Oriented
+ - Encapsulation, Data Abstraction, Polymorphism, **Inheritance**
+- To create new classes that acquire some or many of their properties from an existing class
+- The original class is called the **base class** and the new (slightly different?) class is the **derived class**
+
+## Derived Classes
+
+- Once we have a class, we can then declare new classes that **contain all of the member of the original class - plus any extras that you want to throw in**
+- The members that the derived class receives from its base class are called **inherited members**
+
+- Assume you write a clock class to keep track of a time value such as 9:48PM
+- Now suppose you're writing a program with various kinds of clocks: 12-hour clocks, 24-hour clocks, alarm clocks, cuckoo clocks, and so on
+ - For example, a `cuckoo_clock` might have an extra function, `is_cuckooing`, that returns true it its cuckoo bird is currently making noise
+- One possible solution uses no new ideas: Modify the original clock definition by adding an extra member function
+- **Even though all of these have similar or identical constructors and member functions, we'll still end up repreating the member function implementations for each different kind of clock**
+
+- In the definition of the derived class, the name of the derived class is followed by a **single colon**, the keyword **public**, and then the **name of the base class**
+
+```
+class cuckoo_clock : public clock{
+ ...
+}
+```
+
+- All of the public members of an ordinary clock are immediately available as public members of a `cuckoo_clock`
+
+### Example
+
+- A Derived Class Definition:
+
+```
+class cuckoo_clock : public clock{
+ public:
+ bool is_cuckooing() const;
+};
+```
+
+- A Member Function Implementation:
+
+```
+bool cuckoo_clock::is_cuckooing() const{
+ return (get_minute() == 0);
+}
+```
+
+- Once the `cuckoo_clock` definition is available, a program may declare `cuckoo_clock` objects using all the public clock member functions and also using the new `is_cuckooing` function
+
+## Public vs Private vs Protected
+
+- We can use keyword **private** instead of **public**, resulting in a **private base class**
+- With a private base class, all of the public members of an ordinary clock are immediately **available as private members** of a `cuckoo_clock`
+- A **protected** member is like a private member, but it is also accessible by the children of the class
+
+![diagram](03-09_1.png)
+
+### Example
+
+```
+class clock {
+ public:
+ //...
+ // CONSTANT FUNCTIONS
+ int get_hour() const;
+ int get_minute() const;
+ bool is_morning() const;
+
+ private:
+ int my_hour;
+ int my_minute;
+ int my_morning;
+};
+
+class clock24 : private clock{
+ public:
+ int get_hour() const;
+};
+
+int main(){
+ clock24 myClock1;
+ cout << myClock1.get_hour() << endl;
+ cout << myClock1.get_minute() << endl;
+}
+```
+
+## Constructors for Derived Classes
+
+- Same as any other class
+ - Define it, or
+ - Use default constructor and copy constructor
+- This default constructor will carry out two steps
+ 1. **Activate the default constructor for the base class** (to initialize any member variables that the base class uses)
+ 2. **Activate default constructors for any new member variables that the derived class has**, but the base class does not have
+
+### Example: Constructor Order
+
+```
+class clock {
+ public:
+ // CONSTRUCTOR
+ clock(){
+ my_hour = 12;
+ my_minute = 0;
+ my_morning = true;
+ std::cout << "clock constructor!" << std::endl;
+ };
+
+ private:
+ int my_hour;
+ int my_minute;
+ int my_morning;
+};
+
+class clock_design{
+ public:
+ clock_design(){
+ color="brown";
+ weight = 12;
+ std::cout << "clock_design constructor!" << std::endl;
+ }
+
+ private:
+ std::string color;
+ int weight;
+};
+
+class clock24 : private clock{
+ public:
+ clock24(){
+ std::cout << "clock24 constructor!" << std::endl;
+ };
+
+ //...
+
+ private:
+ clock_design design_spec;
+};
+```
+
+### Copy Constructor
+
+- If a derived class does not define a copy constructor of its own, then C++ will automatically provide a copy constructor
+- This copy constructor is similar to the automatic default constructor in that it carries out two steps:
+ 1. **Activate the copy constructor for the base class (to copy any member variables that the base class uses)**
+ 2. **Activate copy constructors for any new member variables that the derived class has** but the base class does not have
+- The copy constructors that are actiavted in Steps 1 and 2 may themselves by automatic copy constructors, or they may be specially written to accomplish correct copying of dynamic data structures
+
+### Example: Assignment Operator
+
+```
+clock ordinary;
+cuckoo_clock fancy1, fancy2;
+fancy.advance(60);
+ordinary = fancy1;
+fancy2 = ordinary;
+```
+
+- So: what happens here?
+ - The assignment `ordinary = fancy1` is **permitted** because a cuckoo clock (such as `fancy1`) can be used at any point where an ordinary `clock` is expected
+ - An assignment in the other direction, `fancy2 = ordinary`, is **forbidden** because **an object of the base class (the ordinary clock) cannot be used as if it were an object of the derived class** (the cuckoo clock)
+
+### Automatic Assignment Operator Limitation
+
+- **Allowed**:
+ - When a base class is public, an object of a derived class may be used as if it were an object of the base class
+
+- **Forbidden**:
+ - But an object of the base class cannot usually be used as if it were an object of the derived class
+
+### Automatic Destructor
+
+- If a class does not have a declared destructor, then C++ provides an automatic destructor that carries out two steps:
+ 1. **The destructors are called for any member variables that the derived class has**, but the base class does not have
+ 2. **The destructor is called for the base class**
+- Notice that an automatic destructor works differently than an automatic constructor: **An automatic destructor first activates the destructors for member variables and then activates the destructor for the base class**
+- But an automatic constructor first activates the constructor for the base class, and then activates the constructors for the member variables
+
+## Overriding Inherited Members
+
+- A derived class must sometimes perform some actions differently from the way the base class does
+- Example:
+ - The original clock provides the current hour via `get_hour` using a 12-hour clock
+ - Suppose we want to implement a derived class that provides its hour on a 24-hour basis, ranging from 0 to 23
+- The new clock can be defined as a derived class called `clock24`
+- The `clock24` class inherits everything from the ordinary clock, but it provides a new `get_hour` member function
+- This is called **overriding** an inherited member function
+
+### Example 1
+
+```
+class clock24 : public clock{
+ public:
+ int get_hour() const; //Overriden from the clock class
+};
+
+int clock24::get_hour() const{
+ int ordinary_hour;
+ ordinary_hour = clock::get_hour();
+
+ if(is_morning()){
+ if(ordinary_hour == 12) return 0;
+ else return ordinary_hour;
+ }
+ else ...
+}
+```
+
+- When we write `clock::get_hour()`, we are activating the original clock's `get-hour` function
+
+---
+
+# Inheritance Tree
+
+## Example
+
+![diagram](03-09_2.png)
+
+## Adding Private Members
+
+- The animal class will have two new private member variables, which are not part of the organism class, as show in this partial definition:
+
+```
+class animal : public organism{
+ public:
+ //We discuss the animal's public members later
+ private:
+ double need_each_week;
+ double eaten_this_week;
+};
+```
+
+- When a derived class has some new member variables, **it will usually need a new constructor** to initialize those member variables
+
+### Initializing Private Members
+
+```
+class animal : public organism{
+ public:
+ animal(double init_size = 1; double init_rate = 0; double init_need = 0);
+}
+```
+
+- The work of the animal's constructor is easy enough to describe: The first two arguments must somehow initialize the size and growth rate of the `animal`; the last argument initializes `need_each_week`; the value of `eaten_this_week` is initialized to zero
+- But how do we manage to use `init_size` and `init_rate` to initialize the size and growth rate of the animal?
+- Most likely the size and growth rate are stored as private member variables of the `organism` class, but the animal has no direct access to the `organism`'s private member variables
+
+### Member Initialization List
+
+- This list is an extra line in the constructor of a derived class
+- The purpose is to provide initialization, including a call to the constructor of the base class
+
+```
+animal::animal(double init_size, double init_rate, double init_seed) : organism(init_size, init_rate), need_each_week(init_need), eaten_this_week(0){
+ //Because of the initialization list, this constructor has no work
+}
+```
+
+### Derived Class Initialization
+
+- The member initialization list appears in the implementation of a constructor, after the closing parenthesis of the parameter list
+ - The list begins with a colon, followed by a list of items separated by commas
+ - For a derived class, **the list can contain the name of the base class, followed by an argument list (in parentheses) for the base class constructor**
+ - The list can also contain **any member variable** followed by its initial value in parentheses
+ - When the derived class constructor is called, the member variables are initialized with the specified values and the constructor for the base class will be actiavted before anything else is done
+ - If a base class constructor is not activated in the member initialization list, then the default constructor for the base class will automatically be activated before any of the rest of the derived class constructor is executed
+
+### Example
+
+```
+class herbivore : public animal{
+ // CONSTRUCTOR
+ herbivore(double init_size = 1, double init_rate = 0, double init_need = 0);
+ // MODIFICATION MEMBER FUNCTIONS
+ void nibble(plant& meal);
+};
+
+herbivore::herbivore(double init_size, double init_rate, double init_need) : animal(init_size, init_rate, init_need){
+ //No work is done here, except calling the animal constructor
+}
+```
diff --git a/03-09_1.png b/03-09_1.png
new file mode 100644
index 0000000..de1cc01
--- /dev/null
+++ b/03-09_1.png
Binary files differ
diff --git a/03-09_10.png b/03-09_10.png
new file mode 100644
index 0000000..5935a1f
--- /dev/null
+++ b/03-09_10.png
Binary files differ
diff --git a/03-09_11.png b/03-09_11.png
new file mode 100644
index 0000000..8564337
--- /dev/null
+++ b/03-09_11.png
Binary files differ
diff --git a/03-09_12.png b/03-09_12.png
new file mode 100644
index 0000000..820073e
--- /dev/null
+++ b/03-09_12.png
Binary files differ
diff --git a/03-09_13.png b/03-09_13.png
new file mode 100644
index 0000000..0c3bdd1
--- /dev/null
+++ b/03-09_13.png
Binary files differ
diff --git a/03-09_2.png b/03-09_2.png
new file mode 100644
index 0000000..c35b721
--- /dev/null
+++ b/03-09_2.png
Binary files differ
diff --git a/03-09_3.png b/03-09_3.png
new file mode 100644
index 0000000..63f661a
--- /dev/null
+++ b/03-09_3.png
Binary files differ
diff --git a/03-09_4.png b/03-09_4.png
new file mode 100644
index 0000000..c5f0139
--- /dev/null
+++ b/03-09_4.png
Binary files differ
diff --git a/03-09_5.png b/03-09_5.png
new file mode 100644
index 0000000..d766167
--- /dev/null
+++ b/03-09_5.png
Binary files differ
diff --git a/03-09_6.png b/03-09_6.png
new file mode 100644
index 0000000..91cbb34
--- /dev/null
+++ b/03-09_6.png
Binary files differ
diff --git a/03-09_7.png b/03-09_7.png
new file mode 100644
index 0000000..840b9e8
--- /dev/null
+++ b/03-09_7.png
Binary files differ
diff --git a/03-09_8.png b/03-09_8.png
new file mode 100644
index 0000000..08de1a3
--- /dev/null
+++ b/03-09_8.png
Binary files differ
diff --git a/03-09_9.png b/03-09_9.png
new file mode 100644
index 0000000..6b6eb5b
--- /dev/null
+++ b/03-09_9.png
Binary files differ