LAB 7: TREES PART 2

advertisement
LAB 7: TREES PART 2
Exercise 1 Revising the Animal Guessing Program
Problem statement:
Revise the animal guessing program from Figure 10.9 on page 492 of your text so
that the initial knowledge tree is obtained by reading information from a file.
Also, when the program ends, the knowledge tree at that point is written to the
same file. You must carefully specify the format of the data in this file.
Learning Objectives:
The learner will be able to:
1. Modify an existing program to read a file and set the initial tree structure.
2. Modify an existing program to write a tree structure to a file, using some
kind of traversal.
Exercise 2 Binary Search Trees
Problem statement:
Binary search trees have their best performance when they are balanced, which
means that at each node, n, the size of the left subtree of n is within one of the
size of the right subtree of n.
Write a function that takes a sorted link list of entries and produces a balanced
binary search tree. If useful, you may add extra parameters to the procedure, such
as the total number of entries in the list.
Learning Objectives:
The learner will be able to:
Write a function that takes a sorted link list of entries and produces a balanced
binary search tree.
Equipment:
Typical Computer Lab setup
Components/Materials:
Microsoft Visual C++
1
Lab Handout for IT327
Data Structures
Classroom Configuration:
N/A
Lab Procedures:
Complete the following tasks: Exercise 1
1. Modify the animal guessing program from Figure 10.9 on page 492 of your text so
that the knowledge tree is obtained by reading a file and setting the initial tree
structure.
2. Write the knowledge tree back to the file, using some kind of traversal.
Complete the following tasks: Exercise 2
1. Build the left subtree of the root.
2. Build the right subtree of the root.
3. Put the pieces together with the join function from Self-Test Exercise 26 on page
526 of your text.
4. Think recursively!
Validation/Evaluation
Answers to Lab Exercises
Solutions to Lab Exercises can be found at the Curriculum Knowledge Network
(CKN) section of the ITT Technical Institute Employee Portal, http://myportal.itttech.edu. The solutions are also listed below.
Exercise 1
// FILE: animal.cpp
// An animal-guessing program to illustrate the use of the binary tree toolkit.
#include <cstdlib> // Provides EXIT_SUCCESS
#include <iostream> // Provides cout
#include <string> // Provides string class
#include "bintree.h" // Provides the binary tree node functions
#include "useful.h" // Provides eat_line, inquire (from Appendix I)
using namespace std;
using namespace main_savitch_10;
// PROTOTYPES for functions used by this game program:
void ask_and_move(binary_tree_node<string>*& current_ptr);
// Precondition: current_ptr points to a non-leaf node in a binary taxonomy tree.
// Postcondition: The question at the current node has been asked. The current
// pointer has been shifted left (if the user answered yes) or right
2
Lab Handout for IT327
Data Structures
// (for a no answer).
binary_tree_node<string>* beginning_tree( );
// Postcondition: The function has created a small taxonomy tree. The return
// value is the root pointer of the new tree.
void instruct( );
// Postcondition: Instructions for playing the game have been printed to the
// screen.
void learn(binary_tree_node<string>*& leaf_ptr);
// Precondition: leaf_ptr is a pointer to a leaf in a taxonomy tree. The leaf
// contains a wrong guess that was just made.
// Postcondition: Information has been elicited from the user, and the tree has
// been improved.
void play(binary_tree_node<string>* current_ptr);
// Precondition: current_ptr points to the root of a binary taxonomy tree with
// at least two leaves.
// Postcondition: One round of the animal game has been played, and maybe the
// tree has been improved.
int main( )
{
binary_tree_node<string> *taxonomy_root_ptr;
instruct( );
taxonomy_root_ptr = beginning_tree( );
do
play(taxonomy_root_ptr);
while (inquire("Shall we play again?"));
cout << "Thank you for teaching me a thing or two." << endl;
return EXIT_SUCCESS;
}
void ask_and_move(binary_tree_node<string>*& current_ptr)
// Library facilities used: bintree.h, string, useful.h
{
cout << current_ptr->data( );
if (inquire(" Please answer:"))
current_ptr = current_ptr->left( );
else
current_ptr = current_ptr->right( );
}
3
Lab Handout for IT327
Data Structures
binary_tree_node<string>* beginning_tree( )
// Library facilities used: bintree.h, string
{
binary_tree_node<string> *root_ptr;
binary_tree_node<string> *child_ptr;
const string root_question("Are you a mammal?");
const string left_question("Are you bigger than a cat?");
const string right_question("Do you live underwater?");
const string animal1("Kangaroo");
const string animal2("Mouse");
const string animal3("Trout");
const string animal4("Robin");
// Create the root node with the question “Are you a mammal?”
root_ptr = new binary_tree_node<string>(root_question);
// Create and attach the left subtree.
child_ptr = new binary_tree_node<string>(left_question);
child_ptr->set_left( new binary_tree_node<string>(animal1) );
child_ptr->set_right( new binary_tree_node<string>(animal2) );
root_ptr->set_left(child_ptr);
// Create and attach the right subtree.
child_ptr = new binary_tree_node<string>(right_question);
child_ptr->set_left( new binary_tree_node<string>(animal3) );
child_ptr->set_right( new binary_tree_node<string>(animal4) );
root_ptr->set_right(child_ptr);
return root_ptr;
}
void instruct( )
// Library facilities used: iostream
{
cout << "Let's play!" << endl;
cout << "You pretend to be an animal, and I try to guess what you are.\n";
}
void learn(binary_tree_node<string>*& leaf_ptr)
// Library facilities used: bintree.h, iostream, string, useful.h
{
string guess_animal; // The animal that was just guessed
string correct_animal; // The animal that the user was thinking of
string new_question; // A question to distinguish the two animals
4
Lab Handout for IT327
Data Structures
// Set strings for the guessed animal, correct animal and a new question.
guess_animal = leaf_ptr->data( );
cout << "I give up. What are you? " << endl;
getline(cin, correct_animal);
cout << "Please type a yes/no question that will distinguish a" << endl;
cout << correct_animal << " from a " << guess_animal << "." << endl;
cout << "Your question: " << endl;
getline(cin, new_question);
// Put the new question in the current node, and add two new children.
leaf_ptr->set_data(new_question);
cout << "As a " << correct_animal << ", " << new_question << endl;
if (inquire("Please answer"))
{
leaf_ptr->set_left( new binary_tree_node<string> (correct_animal) );
leaf_ptr->set_right( new binary_tree_node<string> (guess_animal) );
}
else
{
leaf_ptr->set_left( new binary_tree_node<string> (guess_animal) );
leaf_ptr->set_right( new binary_tree_node<string> (correct_animal) );
}
}
void play(binary_tree_node<string>* current_ptr)
// Library facilities used: bintree.h, iostream, string, useful.h
{
cout << "Think of an animal, then press the return key.";
eat_line( );
while (!current_ptr->is_leaf( ))
ask_and_move(current_ptr);
cout << ("My guess is " + current_ptr->data( ) + ". ");
if (!inquire("Am I right?"))
learn(current_ptr);
else
cout << "I knew it all along!" << endl;
}
Exercise 2
// FILE: bintree.h (part of the namespace main_savitch_10)
// From Chapter 10 of Data Structures and Other Objects (Third Edition)
//
5
Lab Handout for IT327
Data Structures
______________________________________________________________________
//
// This file has been modified to work with Microsoft Visual C++ 6.0,
// as described in www.cs.colorado.edu/~main/vc6.html
//
______________________________________________________________________
//
// PROVIDES: A template class for a node in a binary tree and functions for
// manipulating binary trees. The template parameter is the type of data in
// each node.
//
// TYPEDEF for the binary_tree_node<Item> template class:
// Each node of the tree contains a piece of data and pointers to its
// children. The type of the data (binary_tree_node<Item>::value_type) is
// the Item type from the template parameter. The type may be any of the C++
// built-in types (int, char, etc.), or a class with a default constructor,
// and an assignment operator.
//
// CONSTRUCTOR for the binary_tree_node<Item> class:
// binary_tree_node(
//
const item& init_data = Item( ),
//
binary_tree_node<Item>* init_left = NULL,
//
binary_tree_node<Item>* init_right = NULL
// )
// Postcondition: The new node has its data equal to init_data,
// and it's child pointers equal to init_left and init_right.
//
// MEMBER FUNCTIONS for the binary_tree_node<Item> class:
// -----------------------------------------------------------------------// NOTE: I have changed the return values from the non-const versions of
// the left() and right() functions so that they return a reference to
// the pointer in the node. This is indicated by the & symbol here:
// binary_tree_node*& left( )
// The use of a "reference" in the return value has two advantages that
// simplify the material of Chapter 10:
// 1. It now allows a direct assignment such as: p->left() = NULL.
// This is not a huge advantage since the same thing can be accomplished
// by using the set_left function.
// 2. The expression p->left() can be passed as the argument
// to a function such as: tree_clear(p->left());
// The parameter of tree_clear is a reference parameter, so that
// any changes that tree_clear makes to p->left() will now affect
// the actual left pointer in the node *p. In this example, the
// tree_clear function does set its parameter to NULL, so that
// the total effect of tree_clear(p->left()) is to clear the left
// subtree of p and to set p's left pointer to NULL.
6
Lab Handout for IT327
Data Structures
// In the case of tree_clear, this is not a huge advantage because we
// could have just set p's left pointer to NULL ourselves. But, in
// Section 10.5, there are two functions, bst_remove and bst_remove_max,
// which are easier to write if we can use p->left() and p->right() as
// the parameters of recursive calls. See the partial implementation
// of bag6.template for details:
// http://www.cs.colorado.edu/~main/projects/chap10a.html
// -----------------------------------------------------------------------// const item& data( ) const
<----- const version
// and
// Item& data( )
<----- non-const version
// Postcondition: The return value is a reference to the data from
// this binary_tree_node.
//
// const binary_tree_node* left( ) const <----- const version
// and
// binary_tree_node*& left( )
<----- non-const version
// and
// const binary_tree_node* right( ) const <----- const version
// and
// binary_tree_node*& right( )
<----- non-const version
// Postcondition: The return value is a pointer to the left or right child
// (which will be NULL if there is no child).
//
// void set_data(const Item& new_data)
// Postcondition: The binary_tree_node now contains the specified new data.
//
// void set_left(binary_tree_node* new_link)
// and
// void set_right(binary_tree_node* new_link)
// Postcondition: The binary_tree_node now contains the specified new link
// to a child.
//
// bool is_leaf( )
// Postcondition: The return value is true if the node is a leaf;
// otherwise the return value is false.
//
// NON-MEMBER FUNCTIONS to maniplulate binary tree nodes:
// tempate <class Process, class BTNode>
// void inorder(Process f, BTNode* node_ptr)
// Precondition: node_ptr is a pointer to a node in a binary tree (or
// node_ptr may be NULL to indicate the empty tree).
// Postcondition: If node_ptr is non-NULL, then the function f has been
// applied to the contents of *node_ptr and all of its descendants, using
// an in-order traversal.
// Note: BTNode may be a binary_tree_node or a const binary tree node.
7
Lab Handout for IT327
Data Structures
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
Process is the type of a function f that may be called with a single
Item argument (using the Item type from the node).
tempate <class Process, class BTNode>
void postorder(Process f, BTNode* node_ptr)
Same as the in-order function, except with a post-order traversal.
tempate <class Process, class BTNode>
void preorder(Process f, BTNode* node_ptr)
Same as the in-order function, except with a pre-order traversal.
template <class Item, class SizeType>
void print(const binary_tree_node<Item>* node_ptr, SizeType depth)
Precondition: node_ptr is a pointer to a node in a binary tree (or
node_ptr may be NULL to indicate the empty tree). If the pointer is
not NULL, then depth is the depth of the node pointed to by node_ptr.
Postcondition: If node_ptr is non-NULL, then the contents of *node_ptr
and all its descendants have been written to cout with the << operator,
using a backward in-order traversal. Each node is indented four times
its depth.
template <class Item>
void tree_clear(binary_tree_node<Item>*& root_ptr)
Precondition: root_ptr is the root pointer of a binary tree (which may
be NULL for the empty tree).
Postcondition: All nodes at the root or below have been returned to the
heap, and root_ptr has been set to NULL.
template <class Item>
binary_tree_node<Item>* tree_copy(const binary_tree_node<Item>* root_ptr)
Precondition: root_ptr is the root pointer of a binary tree (which may
be NULL for the empty tree).
Postcondition: A copy of the binary tree has been made, and the return
value is a pointer to the root of this copy.
template <class Item>
size_t tree_size(const binary_tree_node<Item>* node_ptr)
Precondition: node_ptr is a pointer to a node in a binary tree (or
node_ptr may be NULL to indicate the empty tree).
Postcondition: The return value is the number of nodes in the tree.
#ifndef BINTREE_H
#define BINTREE_H
#include <cstdlib> // Provides NULL and size_t
namespace main_savitch_10
8
Lab Handout for IT327
Data Structures
{
template <class Item>
class binary_tree_node
{
public:
// TYPEDEF
typedef Item value_type;
// CONSTRUCTOR
binary_tree_node(
const Item& init_data = Item( ),
binary_tree_node* init_left = NULL,
binary_tree_node* init_right = NULL
)
{
data_field = init_data;
left_field = init_left;
right_field = init_right;
}
// MODIFICATION MEMBER FUNCTIONS
Item& data( ) { return data_field; }
binary_tree_node*& left( ) { return left_field; }
binary_tree_node*& right( ) { return right_field; }
void set_data(const Item& new_data) { data_field = new_data; }
void set_left(binary_tree_node* new_left) { left_field = new_left; }
void set_right(binary_tree_node* new_right) { right_field = new_right; }
// CONST MEMBER FUNCTIONS
const Item& data( ) const { return data_field; }
const binary_tree_node* left( ) const { return left_field; }
const binary_tree_node* right( ) const { return right_field; }
bool is_leaf( ) const
{ return (left_field == NULL) && (right_field == NULL); }
private:
Item data_field;
binary_tree_node *left_field;
binary_tree_node *right_field;
};
// NON-MEMBER FUNCTIONS for the binary_tree_node<Item>:
template <class Process, class BTNode>
void inorder(Process f, BTNode* node_ptr);
template <class Process, class BTNode>
void preorder(Process f, BTNode* node_ptr);
template <class Process, class BTNode>
9
Lab Handout for IT327
Data Structures
void postorder(Process f, BTNode* node_ptr);
template <class Item, class SizeType>
void print(binary_tree_node<Item>* node_ptr, SizeType depth);
template <class Item>
void tree_clear(binary_tree_node<Item>*& root_ptr);
template <class Item>
binary_tree_node<Item>* tree_copy(const binary_tree_node<Item>* root_ptr);
template <class Item>
size_t tree_size(const binary_tree_node<Item>* node_ptr);
}
#include "bintree.template"
#endif
// FILE: bintree.template
// From Chapter 10 of Data Structures and Other Objects (Third Edition)
//
______________________________________________________________________
//
// This file has been modified to work with Microsoft Visual C++ 6.0,
// as described in www.cs.colorado.edu/~main/vc6.html
//
______________________________________________________________________
//
// IMPLEMENTS: The binary_tree node class (see bintree.h for documentation).
#include <cassert> // Provides assert
#include <cstdlib> // Provides NULL, size_t
#include <iomanip> // Provides std::setw
#include <iostream> // Provides std::cout
namespace main_savitch_10
{
template <class Process, class BTNode>
void inorder(Process f, BTNode* node_ptr)
// Library facilities used: cstdlib
{
if (node_ptr != NULL)
{
inorder(f, node_ptr->left( ));
f( node_ptr->data( ) );
inorder(f, node_ptr->right( ));
}
10
Lab Handout for IT327
Data Structures
}
template <class Process, class BTNode>
void postorder(Process f, BTNode* node_ptr)
// Library facilities used: cstdlib
{
if (node_ptr != NULL)
{
postorder(f, node_ptr->left( ));
postorder(f, node_ptr->right( ));
f(node_ptr->data( ));
}
}
template <class Process, class BTNode>
void preorder(Process f, BTNode* node_ptr)
// Library facilities used: cstdlib
{
if (node_ptr != NULL)
{
f( node_ptr->data( ) );
preorder(f, node_ptr->left( ));
preorder(f, node_ptr->right( ));
}
}
template <class Item, class SizeType>
void print(binary_tree_node<Item>* node_ptr, SizeType depth)
// Library facilities used: iomanip, iostream, stdlib
{
if (node_ptr != NULL)
{
print(node_ptr->right( ), depth+1);
std::cout << std::setw(4*depth) << ""; // Indent 4*depth spaces.
std::cout << node_ptr->data( ) << std::endl;
print(node_ptr->left( ), depth+1);
}
}
template <class Item>
void tree_clear(binary_tree_node<Item>*& root_ptr)
// Library facilities used: cstdlib
{
if (root_ptr != NULL)
{
tree_clear( root_ptr->left( ) );
11
Lab Handout for IT327
Data Structures
tree_clear( root_ptr->right( ) );
delete root_ptr;
root_ptr = NULL;
}
}
template <class Item>
binary_tree_node<Item>* tree_copy(const binary_tree_node<Item>* root_ptr)
// Library facilities used: cstdlib
{
binary_tree_node<Item> *l_ptr;
binary_tree_node<Item> *r_ptr;
if (root_ptr == NULL)
return NULL;
else
{
l_ptr = tree_copy( root_ptr->left( ) );
r_ptr = tree_copy( root_ptr->right( ) );
return
new binary_tree_node<Item>( root_ptr->data( ), l_ptr, r_ptr);
}
}
template <class Item>
size_t tree_size(const binary_tree_node<Item>* node_ptr)
// Library facilities used: cstdlib
{
if (node_ptr == NULL)
return 0;
else
return
1 + tree_size(node_ptr->left( )) + tree_size(node_ptr->right( ));
}
}
12
Lab Handout for IT327
Data Structures
Download