adding lab 10
This commit is contained in:
44
labs/10_trees_I/README.md
Normal file
44
labs/10_trees_I/README.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# Lab 10 — Trees, Binary Trees, & Binary Search Trees
|
||||
|
||||
## Checkpoint 1
|
||||
|
||||
*estimate: 20-30 minutes*
|
||||
|
||||
problem 1: Draw a binary tree with 4 levels with the integers 1-7 such that the sum of elements on every level of the tree is the same.
|
||||
|
||||
problem 2: Create a exactly balanced binary search tree with 7 color words (order the colors alphabetically).
|
||||
|
||||
problem 3: Draw a exactly-balanced binary search tree containing the letters of the word: uncopyrightable
|
||||
|
||||
What is the pre-order traversal of the tree above?
|
||||
|
||||
problem 4: Now draw a exactly-balanced binary tree of characters such that a post-order traversal spells the word: uncopyrightable
|
||||
|
||||
What is the breadth-first traversal of the tree above?
|
||||
|
||||
*To complete this checkpoint*: When you have finished all of the problems, discuss your answers with your lab TA or mentor.
|
||||
|
||||
## Checkpoint 2
|
||||
|
||||
*estimate: 20-35 minutes*
|
||||
|
||||
Now let’s explore the implementation of the ds_set class, along with the use of recursive functions to
|
||||
|
||||
manipulate binary search trees. Download and examine the files: [ds_set.h](ds_set.h) and [test_ds_set.cpp](test_ds_set.cpp).
|
||||
|
||||
The implementation of find provided in ds_set.h is recursive. Re-implement and test a
|
||||
non-recursive replacement for this function.
|
||||
|
||||
**To complete this checkpoint**: Show one of the TAs your new code. Be prepared to discuss the running
|
||||
time for the two different versions of find for various inputs.
|
||||
|
||||
## Checkpoint 3
|
||||
|
||||
*estimate: 20-35 minutes*
|
||||
|
||||
The implementation of the copy constructor and the assignment operator is not yet complete
|
||||
because each depends on a private member function called copy tree, the body of which has not yet been
|
||||
written. Write copy tree and then test to see if it works by “uncommenting” the appropriate code from the
|
||||
main function.
|
||||
|
||||
**To complete this checkpoint**: Show one of the TAs your new code. Be prepared to discuss the running
|
||||
155
labs/10_trees_I/ds_set.h
Normal file
155
labs/10_trees_I/ds_set.h
Normal file
@@ -0,0 +1,155 @@
|
||||
// Partial implementation of binary-tree based set class similar to std::set.
|
||||
// The iterator increment & decrement operations have been omitted.
|
||||
#ifndef ds_set_h_
|
||||
#define ds_set_h_
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// TREE NODE CLASS
|
||||
template <class T>
|
||||
class TreeNode {
|
||||
public:
|
||||
TreeNode() : left(NULL), right(NULL) {}
|
||||
TreeNode(const T& init) : value(init), left(NULL), right(NULL) {}
|
||||
T value;
|
||||
TreeNode* left;
|
||||
TreeNode* right;
|
||||
};
|
||||
|
||||
template <class T> class ds_set;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// TREE NODE ITERATOR CLASS
|
||||
template <class T>
|
||||
class tree_iterator {
|
||||
public:
|
||||
tree_iterator() : ptr_(NULL) {}
|
||||
tree_iterator(TreeNode<T>* p) : ptr_(p) {}
|
||||
tree_iterator(const tree_iterator& old) : ptr_(old.ptr_) {}
|
||||
~tree_iterator() {}
|
||||
tree_iterator& operator=(const tree_iterator& old) { ptr_ = old.ptr_; return *this; }
|
||||
// operator* gives constant access to the value at the pointer
|
||||
const T& operator*() const { return ptr_->value; }
|
||||
// comparions operators are straightforward
|
||||
bool operator== (const tree_iterator& rgt) { return ptr_ == rgt.ptr_; }
|
||||
bool operator!= (const tree_iterator& rgt) { return ptr_ != rgt.ptr_; }
|
||||
// increment & decrement will be discussed in Lecture 19 and Lab 11
|
||||
|
||||
private:
|
||||
// representation
|
||||
TreeNode<T>* ptr_;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// DS SET CLASS
|
||||
template <class T>
|
||||
class ds_set {
|
||||
public:
|
||||
ds_set() : root_(NULL), size_(0) {}
|
||||
ds_set(const ds_set<T>& old) : size_(old.size_) {
|
||||
root_ = this->copy_tree(old.root_); }
|
||||
~ds_set() { this->destroy_tree(root_); root_ = NULL; }
|
||||
ds_set& operator=(const ds_set<T>& old) {
|
||||
if (&old != this) {
|
||||
this->destroy_tree(root_);
|
||||
root_ = this->copy_tree(old.root_);
|
||||
size_ = old.size_;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
typedef tree_iterator<T> iterator;
|
||||
|
||||
int size() const { return size_; }
|
||||
bool operator==(const ds_set<T>& old) const { return (old.root_ == this->root_); }
|
||||
|
||||
// FIND, INSERT & ERASE
|
||||
iterator find(const T& key_value) { return find(key_value, root_); }
|
||||
std::pair< iterator, bool > insert(T const& key_value) { return insert(key_value, root_); }
|
||||
int erase(T const& key_value) { return erase(key_value, root_); }
|
||||
|
||||
// OUTPUT & PRINTING
|
||||
friend std::ostream& operator<< (std::ostream& ostr, const ds_set<T>& s) {
|
||||
s.print_in_order(ostr, s.root_);
|
||||
return ostr;
|
||||
}
|
||||
void print_as_sideways_tree(std::ostream& ostr) const {
|
||||
print_as_sideways_tree(ostr, root_, 0); }
|
||||
|
||||
// ITERATORS
|
||||
iterator begin() const {
|
||||
if (!root_) return iterator(NULL);
|
||||
TreeNode<T>* p = root_;
|
||||
while (p->left) p = p->left;
|
||||
return iterator(p);
|
||||
}
|
||||
iterator end() const { return iterator(NULL); }
|
||||
|
||||
private:
|
||||
// REPRESENTATION
|
||||
TreeNode<T>* root_;
|
||||
int size_;
|
||||
|
||||
// PRIVATE HELPER FUNCTIONS
|
||||
TreeNode<T>* copy_tree(TreeNode<T>* old_root) {
|
||||
// Implemented in Lab 10
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void destroy_tree(TreeNode<T>* p) { /* Implemented in Lecture 18 */ }
|
||||
|
||||
iterator find(const T& key_value, TreeNode<T>* p) {
|
||||
if (!p) return iterator(NULL);
|
||||
if (p->value > key_value)
|
||||
return find(key_value, p->left);
|
||||
else if (p->value < key_value)
|
||||
return find(key_value, p->right);
|
||||
else
|
||||
return iterator(p);
|
||||
}
|
||||
|
||||
std::pair<iterator,bool> insert(const T& key_value, TreeNode<T>*& p) {
|
||||
if (!p) {
|
||||
p = new TreeNode<T>(key_value);
|
||||
this->size_++;
|
||||
return std::pair<iterator,bool>(iterator(p), true);
|
||||
}
|
||||
else if (key_value < p->value)
|
||||
return insert(key_value, p->left);
|
||||
else if (key_value > p->value)
|
||||
return insert(key_value, p->right);
|
||||
else
|
||||
return std::pair<iterator,bool>(iterator(p), false);
|
||||
}
|
||||
|
||||
int erase(T const& key_value, TreeNode<T>* &p) { /* Implemented in Lecture 19 or 20 */ }
|
||||
|
||||
void print_in_order(std::ostream& ostr, const TreeNode<T>* p) const {
|
||||
if (p) {
|
||||
print_in_order(ostr, p->left);
|
||||
ostr << p->value << "\n";
|
||||
print_in_order(ostr, p->right);
|
||||
}
|
||||
}
|
||||
|
||||
void print_as_sideways_tree(std::ostream& ostr, const TreeNode<T>* p, int depth) const {
|
||||
if (p) {
|
||||
print_as_sideways_tree(ostr, p->right, depth+1);
|
||||
for (int i=0; i<depth; ++i) ostr << " ";
|
||||
ostr << p->value << "\n";
|
||||
print_as_sideways_tree(ostr, p->left, depth+1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
96
labs/10_trees_I/test_ds_set.cpp
Normal file
96
labs/10_trees_I/test_ds_set.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <cassert>
|
||||
|
||||
#include "ds_set.h"
|
||||
|
||||
int main() {
|
||||
|
||||
// build a set
|
||||
ds_set<std::string> set1;
|
||||
|
||||
std::pair< ds_set<std::string>::iterator, bool > insert_result;
|
||||
std::string to_insert = std::string("hello");
|
||||
insert_result = set1.insert(to_insert);
|
||||
assert(insert_result.second);
|
||||
|
||||
insert_result = set1.insert(std::string("good-bye"));
|
||||
assert(insert_result.second);
|
||||
|
||||
insert_result = set1.insert(std::string("friend"));
|
||||
assert(insert_result.second);
|
||||
|
||||
insert_result = set1.insert(std::string("abc"));
|
||||
assert(insert_result.second);
|
||||
|
||||
insert_result = set1.insert(std::string("puppy"));
|
||||
assert(insert_result.second);
|
||||
|
||||
insert_result = set1.insert(std::string("zebra"));
|
||||
assert(insert_result.second);
|
||||
|
||||
insert_result = set1.insert(std::string("daddy"));
|
||||
assert(insert_result.second);
|
||||
|
||||
insert_result = set1.insert(std::string("puppy"));
|
||||
assert(!insert_result.second && * insert_result.first == std::string("puppy"));
|
||||
|
||||
ds_set<std::string>::iterator p = set1.begin();
|
||||
assert(p != set1.end() && *p == std::string("abc"));
|
||||
|
||||
|
||||
// visualize the set
|
||||
std::cout << "The set size is " << set1.size()
|
||||
<< "\nHere are the elements: \n" << set1 << std::endl;
|
||||
|
||||
p = set1.find("foo");
|
||||
if (p == set1.end())
|
||||
std::cout << "\"foo\" is not in the set\n";
|
||||
else
|
||||
std::cout << "\"foo\" is in the set\n"
|
||||
<< "The iterator points to " << *p << std::endl;
|
||||
|
||||
p = set1.find("puppy");
|
||||
if (p == set1.end())
|
||||
std::cout << "\"puppy\" is not in the set\n";
|
||||
else
|
||||
std::cout << "\"puppy\" is in the set\n"
|
||||
<< "The iterator points to " << *p << std::endl;
|
||||
|
||||
p = set1.find("daddy");
|
||||
if (p == set1.end())
|
||||
std::cout << "\"daddy\" is not in the set\n";
|
||||
else
|
||||
std::cout << "\"daddy\" is in the set\n"
|
||||
<< "The iterator points to " << *p << std::endl;
|
||||
|
||||
std::cout << "\nHere is the tree, printed sideways.\n"
|
||||
<< "The indentation is proportional to the depth of the node\n"
|
||||
<< "so that the value stored at the root is the only value printed\n"
|
||||
<< "without indentation. Also, for each node, the right subtree\n"
|
||||
<< "can be found above where the node is printed and indented\n"
|
||||
<< "relative to it\n\n";
|
||||
set1.print_as_sideways_tree(std::cout);
|
||||
|
||||
|
||||
/*
|
||||
// Needed for checkpoint 2, part 2
|
||||
ds_set<std::string> set2(set1);
|
||||
std::cout << "set1.size() = " << set1.size() << ", set2.size() = " << set2.size() << std::endl;
|
||||
std::cout << "\nHere is set2 printed sideways:\n";
|
||||
set2.print_as_sideways_tree(std::cout);
|
||||
|
||||
// Now add more stuff to set2.
|
||||
insert_result = set2.insert(std::string("a"));
|
||||
assert(insert_result.second);
|
||||
insert_result = set2.insert(std::string("b"));
|
||||
assert(insert_result.second);
|
||||
std::cout << "\nAfter two inserts:\n"
|
||||
<< "set1.size() = " << set1.size() << ", set2.size() = " << set2.size() << "\n"
|
||||
<< "\nThe contents of set2:\n" << set2 << std::endl;
|
||||
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user