/sf/trunk/src/examples/binary_tree.cc

# · C++ · 334 lines · 268 code · 18 blank · 48 comment · 68 complexity · 601c03ba34d52e036fe13e92d8c44a05 MD5 · raw file

  1. /* Binary_Tree
  2. Copyright (C) 1998 Jarno Seppänen and Sami Kananoja
  3. $Id: binary_tree.cc 149 2004-06-28 19:38:39Z tonigonenstein $
  4. This file is part of Sonic Flow.
  5. This program is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License
  7. as published by the Free Software Foundation; either version 2
  8. of the License, or (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  16. #include <iostream>
  17. #include "binary_tree.h"
  18. Binary_Tree::Binary_Tree () : root(0), num_nodes(0)
  19. {
  20. }
  21. Binary_Tree::~Binary_Tree ()
  22. {
  23. clear ();
  24. }
  25. bool
  26. Binary_Tree::parse (char* expr)
  27. //Function for parsing a binary tree from a text string.
  28. //Legal binary tree expression
  29. // - (A, B)
  30. //
  31. //Node content 'A' and 'B' may be any string
  32. //which doesn't contain a '(', a ')' nor a ',' OR
  33. //another expression '(C, D)' recursively. Paretheses
  34. //must be well found.
  35. //
  36. //For example the string '(((A, B), C), (D, E))' is
  37. //a legal binary tree expression where as 'A, B' and
  38. //'((A, B) C)' are not (missing parentheses and a missing
  39. //comma respectively).
  40. {
  41. int i;
  42. Node * current;
  43. initialize_tree ();
  44. i = 0;
  45. current = 0;
  46. try {
  47. while (expr[i] != '\0')
  48. {
  49. //Remove preceeding 'empty' characters
  50. while (expr[i] == ' ' ||
  51. expr[i] == '\t' ||
  52. expr[i] == '\n')
  53. {
  54. i++;
  55. }
  56. switch (expr[i])
  57. {
  58. case '\0':
  59. break;
  60. case BEGIN_SEPARATOR:
  61. if (current == 0)
  62. {
  63. initialize_tree ();
  64. add_left_child (root);
  65. current = root->left;
  66. }
  67. else
  68. {
  69. add_left_child (current);
  70. current = current->left;
  71. }
  72. i++;
  73. break;
  74. case END_SEPARATOR:
  75. if (current == 0)
  76. {
  77. throw Bin_Tree_Exception("Missing 'BEGIN_SEPARATOR'");
  78. }
  79. if (current->parent == 0)
  80. {
  81. throw Bin_Tree_Exception("Illegally placed 'END_SEPARATOR'");
  82. }
  83. else
  84. {
  85. current = current->parent;
  86. }
  87. i++;
  88. break;
  89. case NODE_SEPARATOR:
  90. if (current == 0)
  91. {
  92. throw Bin_Tree_Exception("Missing ´BEGIN_SEPARATOR'");
  93. }
  94. if (current->parent == 0)
  95. {
  96. throw Bin_Tree_Exception("Illegally placed 'NODE_SEPARATOR'");
  97. }
  98. add_right_child (current->parent);
  99. current->parent->content = new char[2];
  100. current->parent->content[0] = NODE_SEPARATOR;
  101. current->parent->content[1] = '\0';
  102. current = current->parent->right;
  103. i++;
  104. break;
  105. default:
  106. if (current == 0)
  107. {
  108. throw Bin_Tree_Exception("Missing 'BEGIN_SEPARATOR'");
  109. }
  110. if (!is_leaf (current))
  111. {
  112. throw Bin_Tree_Exception("Node not a leaf");
  113. }
  114. if (current->content != 0)
  115. {
  116. throw Bin_Tree_Exception("Node already has a value");
  117. }
  118. int j;
  119. j = 0;
  120. while (expr[i + j] != NODE_SEPARATOR &&
  121. expr[i + j] != END_SEPARATOR &&
  122. expr[i + j] != BEGIN_SEPARATOR)
  123. {
  124. if (expr[i + j] == '\0')
  125. {
  126. throw Bin_Tree_Exception("Possibly missing 'END_SEPARATOR'");
  127. }
  128. j++;
  129. }
  130. j--;
  131. //Remove succeeding 'empty' characters
  132. while (expr[i + j] == ' ' ||
  133. expr[i + j] == '\t' ||
  134. expr[i + j] == '\n')
  135. {
  136. j--;
  137. }
  138. j++;
  139. current->content = new char[j+1];
  140. for (int k = 0; k < j; k++)
  141. {
  142. current->content[k] = expr[i + k];
  143. }
  144. current->content[j] = '\0';
  145. i = i + j;
  146. }
  147. }
  148. if (current != root)
  149. {
  150. throw Bin_Tree_Exception ("Missing 'END_SEPARATOR'");
  151. }
  152. if (is_leaf(root))
  153. {
  154. throw Bin_Tree_Exception ("Empty tree");
  155. }
  156. }
  157. catch (Bin_Tree_Exception e)
  158. {
  159. std::cerr << "Parse error: " << e.description << std::endl;
  160. clear ();
  161. return false;
  162. }
  163. if (sanity_check (root) == false)
  164. {
  165. std::cerr << "Sanity error: possibly missing nodes!" << std::endl;
  166. clear ();
  167. return false;
  168. }
  169. return true;
  170. }
  171. void
  172. Binary_Tree::clear ()
  173. //Delete all the nodes of the binary tree.
  174. {
  175. if (root != 0)
  176. {
  177. remove_node (root);
  178. }
  179. root = 0;
  180. }
  181. void
  182. Binary_Tree::print ()
  183. //Print the whole binary tree.
  184. {
  185. if (root != 0)
  186. {
  187. print_tree (root);
  188. }
  189. else
  190. {
  191. std::cout << "()";
  192. }
  193. std::cout << std::endl;
  194. }
  195. void
  196. Binary_Tree::initialize_tree ()
  197. //Initialize binary tree, i.e. clear the tree and
  198. //create the root.
  199. {
  200. clear ();
  201. root = new Node;
  202. root->content = 0;
  203. root->parent = 0;
  204. root->left = 0;
  205. root->right = 0;
  206. num_nodes++;
  207. }
  208. bool
  209. Binary_Tree::is_leaf (Node* n)
  210. //A node is a leaf if it has no children.
  211. {
  212. if (n == 0 || n->left != 0 || n->right != 0)
  213. {
  214. return false;
  215. }
  216. return true; //If node has no childs
  217. }
  218. bool
  219. Binary_Tree::is_single (Node* n)
  220. //A node is "single" if and only if it has one child.
  221. {
  222. if (n == 0)
  223. return false;
  224. if ((n->right == 0 && n->left != 0) ||
  225. (n->right != 0 && n->left == 0))
  226. return true;
  227. return false;
  228. }
  229. bool
  230. Binary_Tree::sanity_check (Node* n)
  231. //Checks wheather there are any "single" nodes
  232. //in the binary tree.
  233. {
  234. if (n == 0)
  235. return true;
  236. if (is_leaf (n))
  237. return true;
  238. if (is_single (n))
  239. return false;
  240. return ( sanity_check (n->left) &&
  241. sanity_check (n->right) );
  242. }
  243. bool
  244. Binary_Tree::add_left_child (Node* n)
  245. {
  246. if (n->left != 0)
  247. {
  248. return false; //Left child already exists (shouldn't be
  249. //possible)
  250. }
  251. n->left = new Node;
  252. n->left->content = 0;
  253. n->left->parent = n;
  254. n->left->left = 0;
  255. n->left->right = 0;
  256. num_nodes++;
  257. return true;
  258. }
  259. bool
  260. Binary_Tree::add_right_child (Node* n)
  261. {
  262. if (n->right != 0)
  263. {
  264. return false; //Right child already exists (shouldn't be
  265. //possible)
  266. }
  267. n->right = new Node;
  268. n->right->content = 0;
  269. n->right->parent = n;
  270. n->right->left = 0;
  271. n->right->right = 0;
  272. num_nodes++;
  273. return true;
  274. }
  275. void
  276. Binary_Tree::remove_node (Node* n)
  277. //Remove a given node and all its children recursively.
  278. {
  279. if (n != 0) {
  280. remove_node (n->left);
  281. remove_node (n->right);
  282. delete n;
  283. n = 0;
  284. num_nodes--;
  285. }
  286. }
  287. void
  288. Binary_Tree::print_tree (Node* n)
  289. //Print the binary tree recursively.
  290. {
  291. if (is_leaf (n))
  292. {
  293. std::cout << n->content;
  294. }
  295. //If the node is not a leaf, it has both
  296. //children (sanity_check() ensures this).
  297. else
  298. {
  299. std::cout << "(";
  300. print_tree (n->left);
  301. std::cout << n->content << ' ';
  302. print_tree (n->right);
  303. std::cout << ")";
  304. }
  305. }
  306. Bin_Tree_Exception::Bin_Tree_Exception (char* desc)
  307. : description(desc)
  308. {
  309. }
  310. Bin_Tree_Exception::~Bin_Tree_Exception ()
  311. {
  312. }