adding binary tree test case
This commit is contained in:
@@ -11,119 +11,109 @@ Review from Lecture 20
|
|||||||
|
|
||||||
## Today’s Lecture
|
## Today’s Lecture
|
||||||
|
|
||||||
- Red Black Trees
|
- Morris Traversal
|
||||||
- B+ Trees
|
|
||||||
|
|
||||||
## 21.1 Red-Black Trees
|
## 21.1 Morris Traversal
|
||||||
In addition to the binary search tree properties, the following
|
|
||||||
red-black tree properties are maintained throughout all
|
|
||||||
modifications to the data structure:
|
|
||||||
|
|
||||||
- Each node is either red or black.
|
Morris Traversal is a tree traversal algorithm that allows inorder (and also preorder) traversal of a binary tree without using recursion or a stack, achieving O(1) space complexity. It modifies the tree temporarily but restores it afterward.
|
||||||
- The root node is always black.
|
|
||||||
- The NULL child pointers are black.
|
|
||||||
- Both children of every red node are black.
|
|
||||||
- Thus, the parent of a red node must also be black.
|
|
||||||
- All paths from a particular node to a NULL child pointer contain the same
|
|
||||||
number of black nodes.
|
|
||||||
|
|
||||||

|
Instead of using extra memory (like recursion stack or an explicit stack), Morris Traversal utilizes threaded binary trees by:
|
||||||
|
|
||||||
What tree does our **ds_set** implementation produce if we insert the
|
- Finding the inorder predecessor of the current node.
|
||||||
numbers 1-14 **in order**?
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
The tree at the top is the result using a red-black tree. Notice how the tree is still quite balanced.
|
- Temporarily modifying the tree structure by creating threads (links) to the current node.
|
||||||
|
|
||||||
Visit these links for an animation of the sequential insertion and re-balancing:
|
- Using these links to traverse back instead of a recursive call.
|
||||||
|
|
||||||
http://babbage.clarku.edu/~achou/cs160fall03/examples/bst_animation/RedBlackTree-Example.html
|
## 21.2 Morris Traversal - In Order
|
||||||
|
|
||||||
https://www.cs.usfca.edu/~galles/visualization/RedBlack.html
|
- Start from the root.
|
||||||
|
|
||||||
http://www.youtube.com/watch?v=vDHFF4wjWYU&noredirect=1
|
- If the left subtree is NULL, print the node and move to the right.
|
||||||
|
|
||||||
What is the best/average/worst case height of a red-black tree with $n$ nodes?
|
- If the left subtree exists, find the inorder predecessor (rightmost node in the left subtree):
|
||||||
|
|
||||||
|
- If the predecessor’s right child is NULL, set it to the current node (threading) and move left.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
What is the best/average/worst case shortest-path from root to leaf node in a red-black tree with $n$ nodes?
|
- If the predecessor’s right child points to the current node (thread already exists), remove the thread, print the current node, and move right.
|
||||||
|
|
||||||
|
- Repeat until you traverse the entire tree.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Exercise 21.2
|
|
||||||
Fill in the tree on the right with the integers 1-7 to make a binary search tree. Also, color each node "red" or "black" so that the tree also fulfills the requirements of a Red-Black tree.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Which nodes are red?
|
|
||||||
|
|
||||||
**Note:** Red-Black Trees are just one algorithm for **self-balancing binary search tress**. We have many more, including the AVL trees that we discussed last week.
|
|
||||||
|
|
||||||
## 21.3 Trinary Tree
|
|
||||||
|
|
||||||
A **trinary tree** is similar to a binary tree except that each node has at most 3 children.
|
|
||||||
|
|
||||||
Write a **recursive** function named **EqualsChildrenSum** that takes one argument, a pointer to the root of a trinary tree, and returns true if the value at each non-leaf node is the sum of the values of all of its children and false otherwise. In
|
|
||||||
the examples below, the tree on the left will return true and the tree on the right will return false.
|
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
class Node {
|
vector<int> inorderTraversal(TreeNode* root) {
|
||||||
public:
|
vector<int> result;
|
||||||
int value;
|
TreeNode *current=root;
|
||||||
Node* left;
|
TreeNode *rightmost;
|
||||||
Node* middle;
|
while(current!=NULL){
|
||||||
Node* right;
|
if(current->left!=NULL){
|
||||||
};
|
rightmost=current->left;
|
||||||
|
while(rightmost->right!=NULL && rightmost->right!=current){
|
||||||
|
rightmost=rightmost->right;
|
||||||
|
}
|
||||||
|
if(rightmost->right==NULL){ /* first time */
|
||||||
|
rightmost->right=current;
|
||||||
|
current=current->left;
|
||||||
|
}else{ /* second time */
|
||||||
|
result.push_back(current->val);
|
||||||
|
rightmost->right=NULL;
|
||||||
|
current=current->right;
|
||||||
|
}
|
||||||
|
}else{ /* nodes which do not have left child */
|
||||||
|
result.push_back(current->val);
|
||||||
|
current=current->right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
```
|
```
|
||||||

|
|
||||||
|
|
||||||
## 21.4 B+ Trees
|
You can test the above function using this program: [inorder_main.cpp](inorder_main.cpp).
|
||||||
|
|
||||||
Unlike binary search trees, nodes in B+ trees (and their predecessor, the B tree) have up to b children. Thus
|
For this test case,
|
||||||
B+ trees are very flat and very wide. This is good when it is very expensive to move from one node to another.
|
|
||||||
- B+ trees are supposed to be associative (i.e. they have key-value pairs), but we will just focus on the keys.
|
|
||||||
- Just like STL map and STL set, these keys and values can be any type, but keys must have an operator<
|
|
||||||
defined.
|
|
||||||
- In a B tree key-value pairs can show up anywhere in the tree, in a B+ tree all the key-value pairs are in the
|
|
||||||
leaves and the non-leaf nodes contain duplicates of some keys.
|
|
||||||
- In either type of tree, all leaves are the same distance from the root.
|
|
||||||
- The keys are always sorted in a B/B+ tree node, and there are up to b − 1 of them. They act like b − 1 binary
|
|
||||||
search tree nodes mashed together.
|
|
||||||
- In fact, with the exception of the root, nodes will always have between roughly b/2 and b − 1 keys (in our
|
|
||||||
implementation).
|
|
||||||
- If a B+ tree node has k keys key0, key1, key2, . . . , keyk−1, it will have k + 1 children. The keys in the leftmost
|
|
||||||
child must be < key0, the next child must have keys such that they are ≥key0 and < key1, and so on up to
|
|
||||||
the rightmost child which has only keys ≥keyk−1.
|
|
||||||
|
|
||||||
A B+ tree visualization can be seen at: https://www.cs.usfca.edu/~galles/visualization/BPlusTree.html
|

|
||||||
|
|
||||||

|
The testing program prints:
|
||||||
|
|
||||||
Considerations in a full implementation:
|
```console
|
||||||
- What happens when we want to add a key to a node that's already full?
|
$ g++ inorder_main.cpp
|
||||||
- How do we remove values from a node?
|
$ ./a.out
|
||||||
- How do we ensure the tree stays balanced?
|
Inorder Traversal using Morris Traversal:
|
||||||
- How to keep laves linked together? WHy would we want this?
|
4 2 6 5 7 1 3 9 8
|
||||||
- How to represent key-value pairs?
|
```
|
||||||
|
|
||||||
## 21.5 Exercise
|
## 21.3 Morris Traversal - Pre Order
|
||||||
|
|
||||||
Draw a B+ tree with b=3 with values inserted in the order 1,2,3,4,5,6. Now draw a B+ tree with b=3 and values inserted in the order 6,5,4,3,2,1. The two trees have a different number of levels.
|
```cpp
|
||||||
|
vector<int> preorderTraversal(TreeNode* root) {
|
||||||
|
vector<int> result;
|
||||||
|
int index=0;
|
||||||
|
TreeNode *current=root;
|
||||||
|
TreeNode *rightmost;
|
||||||
|
while(current != nullptr){
|
||||||
|
if(current->left != nullptr){
|
||||||
|
rightmost=current->left;
|
||||||
|
while(rightmost->right!=nullptr && rightmost->right!=current){
|
||||||
|
rightmost=rightmost->right;
|
||||||
|
}
|
||||||
|
if(rightmost->right==nullptr){ /* first time */
|
||||||
|
result.push_back(current->val);
|
||||||
|
rightmost->right=current;
|
||||||
|
current=current->left;
|
||||||
|
}else{ /* second time */
|
||||||
|
rightmost->right=nullptr;
|
||||||
|
current=current->right;
|
||||||
|
}
|
||||||
|
}else{ /* nodes which do not have left child */
|
||||||
|
result.push_back(current->val);
|
||||||
|
current=current->right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 21.4 Morris Traversal - Post Order
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
```
|
||||||
|
|||||||
BIN
lectures/21_trees_IV/binaryTree.png
Normal file
BIN
lectures/21_trees_IV/binaryTree.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
Reference in New Issue
Block a user