Структуры данных и алгоритмы. Практика. Деревья

January 20, 2007

Примеры. Итератор по дереву.
  1. #include <cstdio>
  2. #include <vector>
  3. #include <map>
  4. #include <string>
  5. #include <iostream>
  6.  
  7. using namespace std;
  8.  
  9. struct invalid_iterator_operation{};
  10. struct invalid_node_state {};
  11.  
  12. struct BinNode {
  13. 	int data;
  14. 	BinNode * left, * right, *parent;
  15.  
  16. 	BinNode (int d):
  17. 	data (d), left (NULL) , right (NULL) , parent (NULL){}
  18. 	operator int (){
  19. 		return data;
  20. 	}
  21. };
  22.  
  23. struct tree_iterator {
  24. 	BinNode * cur;
  25.  
  26. 	map <BinNode *, int> stages;
  27. 	tree_iterator (BinNode * _cur):
  28. 	cur (_cur){stages[cur]= 0;}
  29. 	tree_iterator (): cur (NULL) {}
  30.  
  31.  
  32. 	tree_iterator & operator ++ (){
  33. 		if (cur == NULL) throw invalid_iterator_operation();
  34.  
  35. 		if (stages[cur] == 2){
  36. 			cur = cur->parent;
  37. 			try{
  38. 				return ++(*this);
  39. 			}
  40. 			catch (invalid_iterator_operation){return *this;}
  41. 		}
  42. 		if (stages [cur] == 1){
  43. 			if (cur->right)
  44. 			{
  45. 				stages [cur]++;
  46. 				int tmp = stages [cur];
  47. 				cur = cur->right;
  48. 				stages [cur] = 0;
  49. 				return *this;
  50. 			}
  51. 			else{
  52. 				stages[cur]++;
  53. 				int tmp = stages [cur];
  54. 				return ++(*this);
  55. 			}
  56. 		}
  57. 		if (stages[cur] == 0){
  58. 			BinNode *saved = cur;
  59. 			stages [cur]++;
  60. 			int tmp = stages [cur];
  61. 			try{
  62. 				cur = cur->left;
  63. 				stages [cur] = -1;
  64. 				return ++(*this);
  65. 			}catch (invalid_iterator_operation){
  66. 				cur = saved;
  67. 				stages [cur]++;
  68. 				int tmp = stages [cur];
  69. 				cur = cur->right;
  70. 				stages [cur] = -1;
  71. 				try{
  72. 					return ++(*this);
  73. 				}
  74. 				catch (invalid_iterator_operation){
  75. 					cur = saved;
  76. 					stages [cur]++;
  77. 					int tmp = stages [cur];
  78. 					cur = cur->parent;
  79. 					tmp = stages [cur];
  80. 					return ++(*this);
  81. 				}//catch ()
  82. 			}//catch ()
  83. 		}//if (stages [cur] == 0)
  84. 		if (stages [cur] == -1){
  85. 			stages[cur]++;
  86. 			return *this;
  87. 		}
  88.  
  89. 		cerr << "State Error: Unknow Node State " << stages [cur] << " : " << *cur<<endl;
  90. 		throw invalid_node_state();
  91.  
  92. 	};
  93.  
  94. 	tree_iterator & operator ++(int){
  95. 		return operator ++ ();
  96. 	}
  97. 	bool operator != (const tree_iterator & ai){
  98. 		return cur != ai.cur;
  99. 	}
  100.  
  101. 	BinNode * operator * (){
  102. 		return cur;
  103. 	}
  104.  
  105. };
  106. BinNode * add (BinNode * w, int x, BinNode *parent){
  107. 	if (w == NULL){
  108. 		BinNode * n = new BinNode (x);
  109. 		n->parent = parent;
  110. 		return n;
  111. 	}
  112. 	if ( x < w->data)
  113. 		w->left = add (w->left , x , w);
  114. 	else
  115. 		w->right = add (w->right , x , w);
  116. 	return w;
  117. }
  118.  
  119. void print_LR (BinNode *w , int level){
  120. 	if (w == NULL) return;
  121. 	for (int i = 0; i < level;i++) cout << "\t";
  122. 	cout << w->data << endl;
  123. 	print_LR (w->left, level+1);
  124. 	print_LR (w->right, level+1);
  125. }
  126. void main(void)
  127. {
  128. 	BinNode * root = NULL;
  129. 	for (int i = 0; i < 50; i++)
  130. 		root = add (root , rand () % 100 , NULL);
  131. 	print_LR (root , 0);
  132. 	tree_iterator I = tree_iterator (root);
  133. 	tree_iterator I_end;
  134. 	try{
  135. 		while ( I != I_end){
  136. 			cout << *(*I) << ", ";
  137. 			I++;
  138. 		}
  139. 	}
  140. 	catch (invalid_node_state){
  141. 		cerr << "invalid_node_state" << endl;
  142. 	}
  143. 	catch (invalid_iterator_operation){
  144. 		cerr << "invalid_iterator_operation" << endl;
  145. 	}
  146.  
  147. }

Задания к практической работе



Сегодняшняя работа посвящена работе с деревьями.

1. Необходимо создать класс GenTree который будет представлять собой генеалогическое дерево. Дерево должно быть бинарным: у каждого узла (человека, который описывается данным узлом) должны быть два родителя. В состав класса необходимо включить следующее множество методов:
 • add (GenNode * child, string fio, bool sex) – 
 метод для добавления информации об одном из родителей для человека на которого ссылается указатель child.
 • add (string parent_path, string fio , bool sex) – 
 добавление информации об одном из родителей: путь(местоположение) добавляемого узла задается в виде xpath – строки
 (<em>“vasya\tatiana\igor\anna”</em>) в случае не возможности найти место, куда следует добавить узел должно генерироваться
 исключение <em>bad_xpath_expression</em>.
 • delete (string deleted_xpath) – метод должен служить для удаления всех узлов которые находятся ниже чем тот,
 на который указывает xpath – выражение.
 • bool get_sex (string name_xpath) – данная функция должна возвращать признак пола у человека,
 на которого ссылается xpath-выражение.
 • print_all_tree () – данная функция должна распечатывать все генеалогическое дерево, при этом необходимо,
 чтобы данные были представлены в удобном виде, например, так:
  1. vasya:
  2. father: petya
  3. 		father:	anton
  4. 			father: serge
  5. 		mother: vika
  6. 		mother: alla
  7. 			father: boris
  8. 		mother: anna
  9. mother: irina
  10. ….
 - а всех узлов лежащих ниже чем тот, на который ссылается xpath-выражение.
 (например, “alla”) и должна пройтись по всему дереву найти все ссылки на данную фамилию 
 (ведь в общем случае, имена повторяются) и вывести все xpath-пути ведущие к найденным фамилиям 
 (для вышеприведенного дерева, это будет “<em>vasya\petya\alla</em>”).
 обо всех людях которые есть в нашем дереве которые имеют пол sex – возвращается map,
 в качестве ключа будут храниться xpath выражения которые ведут к найденному человеку, 
 а в качестве значения по ключу будет количество дочерних элементов в дереве 
 (т.е. таких людей которые были предками для найденного).
  • print_below (string xpath) – вывод на экран в форме подобной той что приведена выше не всего дерева
  • print_xpath_by_fio (string fio) - данная функция получает на вход только фио одного человека
  • map collect (bool sex) – данная функция должна формировать карту в которой должны храниться данные

2. Создать дерево в котором будут храниться перекрестные ссылки на слова некоторого файла: необходимо прочитать текстовой файл, все слова которые содержатся в нем необходимо поместить в двоичное дерево поиска (нечто подобное было приведено в методическом пособии), но кроме этого необходимо создать список ссылок. Для каждого слова необходимо вести учет того в каких именно строках оно встречается. Программа должна анализировать файл, имя которого задается как первый параметр командной строки, как второй параметр командной строки задается слово которое должно быть найдено. В качестве результата работы выводится сначала само построенное дерево (обязательно, как и в предыдущем задании необходимо при выводе каждого узла делать некоторое количество отступов прапорциональное уроню узла), а также вывести список всех предложений где встречается данное слово.