adding lab 10

This commit is contained in:
Jidong Xiao
2023-10-30 20:47:59 -04:00
parent 5b8ab189a3
commit 76db306c94
3 changed files with 295 additions and 0 deletions

44
labs/10_trees_I/README.md Normal file
View 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 lets 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
View 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

View 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;
}