/sf/trunk/src/examples/binary_tree.cc
# · C++ · 334 lines · 268 code · 18 blank · 48 comment · 68 complexity · 601c03ba34d52e036fe13e92d8c44a05 MD5 · raw file
- /* Binary_Tree
- Copyright (C) 1998 Jarno Seppänen and Sami Kananoja
- $Id: binary_tree.cc 149 2004-06-28 19:38:39Z tonigonenstein $
- This file is part of Sonic Flow.
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
- #include <iostream>
- #include "binary_tree.h"
- Binary_Tree::Binary_Tree () : root(0), num_nodes(0)
- {
- }
- Binary_Tree::~Binary_Tree ()
- {
- clear ();
- }
- bool
- Binary_Tree::parse (char* expr)
- //Function for parsing a binary tree from a text string.
- //Legal binary tree expression
- // - (A, B)
- //
- //Node content 'A' and 'B' may be any string
- //which doesn't contain a '(', a ')' nor a ',' OR
- //another expression '(C, D)' recursively. Paretheses
- //must be well found.
- //
- //For example the string '(((A, B), C), (D, E))' is
- //a legal binary tree expression where as 'A, B' and
- //'((A, B) C)' are not (missing parentheses and a missing
- //comma respectively).
- {
- int i;
- Node * current;
- initialize_tree ();
- i = 0;
- current = 0;
- try {
- while (expr[i] != '\0')
- {
- //Remove preceeding 'empty' characters
- while (expr[i] == ' ' ||
- expr[i] == '\t' ||
- expr[i] == '\n')
- {
- i++;
- }
- switch (expr[i])
- {
- case '\0':
- break;
- case BEGIN_SEPARATOR:
- if (current == 0)
- {
- initialize_tree ();
- add_left_child (root);
- current = root->left;
- }
- else
- {
- add_left_child (current);
- current = current->left;
- }
- i++;
- break;
- case END_SEPARATOR:
- if (current == 0)
- {
- throw Bin_Tree_Exception("Missing 'BEGIN_SEPARATOR'");
- }
- if (current->parent == 0)
- {
- throw Bin_Tree_Exception("Illegally placed 'END_SEPARATOR'");
- }
- else
- {
- current = current->parent;
- }
- i++;
- break;
- case NODE_SEPARATOR:
- if (current == 0)
- {
- throw Bin_Tree_Exception("Missing ´BEGIN_SEPARATOR'");
- }
- if (current->parent == 0)
- {
- throw Bin_Tree_Exception("Illegally placed 'NODE_SEPARATOR'");
- }
- add_right_child (current->parent);
- current->parent->content = new char[2];
- current->parent->content[0] = NODE_SEPARATOR;
- current->parent->content[1] = '\0';
- current = current->parent->right;
- i++;
- break;
- default:
- if (current == 0)
- {
- throw Bin_Tree_Exception("Missing 'BEGIN_SEPARATOR'");
- }
- if (!is_leaf (current))
- {
- throw Bin_Tree_Exception("Node not a leaf");
- }
- if (current->content != 0)
- {
- throw Bin_Tree_Exception("Node already has a value");
- }
- int j;
- j = 0;
- while (expr[i + j] != NODE_SEPARATOR &&
- expr[i + j] != END_SEPARATOR &&
- expr[i + j] != BEGIN_SEPARATOR)
- {
- if (expr[i + j] == '\0')
- {
- throw Bin_Tree_Exception("Possibly missing 'END_SEPARATOR'");
- }
- j++;
- }
- j--;
- //Remove succeeding 'empty' characters
- while (expr[i + j] == ' ' ||
- expr[i + j] == '\t' ||
- expr[i + j] == '\n')
- {
- j--;
- }
- j++;
- current->content = new char[j+1];
- for (int k = 0; k < j; k++)
- {
- current->content[k] = expr[i + k];
- }
- current->content[j] = '\0';
- i = i + j;
- }
- }
- if (current != root)
- {
- throw Bin_Tree_Exception ("Missing 'END_SEPARATOR'");
- }
- if (is_leaf(root))
- {
- throw Bin_Tree_Exception ("Empty tree");
- }
- }
- catch (Bin_Tree_Exception e)
- {
- std::cerr << "Parse error: " << e.description << std::endl;
- clear ();
- return false;
- }
- if (sanity_check (root) == false)
- {
- std::cerr << "Sanity error: possibly missing nodes!" << std::endl;
- clear ();
- return false;
- }
- return true;
- }
- void
- Binary_Tree::clear ()
- //Delete all the nodes of the binary tree.
- {
- if (root != 0)
- {
- remove_node (root);
- }
- root = 0;
- }
- void
- Binary_Tree::print ()
- //Print the whole binary tree.
- {
- if (root != 0)
- {
- print_tree (root);
- }
- else
- {
- std::cout << "()";
- }
- std::cout << std::endl;
- }
- void
- Binary_Tree::initialize_tree ()
- //Initialize binary tree, i.e. clear the tree and
- //create the root.
- {
- clear ();
- root = new Node;
- root->content = 0;
- root->parent = 0;
- root->left = 0;
- root->right = 0;
- num_nodes++;
- }
- bool
- Binary_Tree::is_leaf (Node* n)
- //A node is a leaf if it has no children.
- {
- if (n == 0 || n->left != 0 || n->right != 0)
- {
- return false;
- }
- return true; //If node has no childs
- }
- bool
- Binary_Tree::is_single (Node* n)
- //A node is "single" if and only if it has one child.
- {
- if (n == 0)
- return false;
- if ((n->right == 0 && n->left != 0) ||
- (n->right != 0 && n->left == 0))
- return true;
- return false;
- }
- bool
- Binary_Tree::sanity_check (Node* n)
- //Checks wheather there are any "single" nodes
- //in the binary tree.
- {
- if (n == 0)
- return true;
- if (is_leaf (n))
- return true;
- if (is_single (n))
- return false;
- return ( sanity_check (n->left) &&
- sanity_check (n->right) );
- }
- bool
- Binary_Tree::add_left_child (Node* n)
- {
- if (n->left != 0)
- {
- return false; //Left child already exists (shouldn't be
- //possible)
- }
- n->left = new Node;
- n->left->content = 0;
- n->left->parent = n;
- n->left->left = 0;
- n->left->right = 0;
- num_nodes++;
- return true;
- }
- bool
- Binary_Tree::add_right_child (Node* n)
- {
- if (n->right != 0)
- {
- return false; //Right child already exists (shouldn't be
- //possible)
- }
- n->right = new Node;
- n->right->content = 0;
- n->right->parent = n;
- n->right->left = 0;
- n->right->right = 0;
- num_nodes++;
- return true;
- }
- void
- Binary_Tree::remove_node (Node* n)
- //Remove a given node and all its children recursively.
- {
- if (n != 0) {
- remove_node (n->left);
- remove_node (n->right);
- delete n;
- n = 0;
- num_nodes--;
- }
- }
- void
- Binary_Tree::print_tree (Node* n)
- //Print the binary tree recursively.
- {
- if (is_leaf (n))
- {
- std::cout << n->content;
- }
- //If the node is not a leaf, it has both
- //children (sanity_check() ensures this).
- else
- {
- std::cout << "(";
- print_tree (n->left);
- std::cout << n->content << ' ';
- print_tree (n->right);
- std::cout << ")";
- }
- }
- Bin_Tree_Exception::Bin_Tree_Exception (char* desc)
- : description(desc)
- {
- }
- Bin_Tree_Exception::~Bin_Tree_Exception ()
- {
- }