#include #include using namespace std; //Класс «узел дерева» class Node { char d; //тег узла Node* lft; // левый сын Node* rgt; // правый сын int count = 0; public: Node() : lft(nullptr), rgt(nullptr) { } // конструктор узла Node(const Node&) = delete; Node& operator = (const Node&) = delete; ~Node() { delete lft; // деструктор узла (уничтожает все поддерево delete rgt; } // в порядке, обратном его созданию) friend class Tree; // дружественный класс «дерево» }; // Класс «дерево в целом» class Tree { Node* root; // указатель на корень дерева char num, maxnum; // счетчик тегов и максимальный тег int maxrow, offset; // максимальная глубина, смещение корня char** SCREEN; // буфер для выдачи на экран void clrscr() // очистка буфера { for (int i = 0; i < maxrow; i++) memset(SCREEN[i], '.', 80); } Node* MakeNode(int depth) // создание поддерева { Node* v = nullptr; int random; random = rand() % 5 + 1;// cout << random << endl; int Y = (depth < random) && (num <= 'я'); //Вариант: cout << "Node (" << num << ',' << depth << ")1/0: "; cin >> Y; if (Y) { // создание узла, если Y = 1 v = new Node; v->lft = MakeNode(depth + 1); v->d = num++; // вариант — во внутреннем v->rgt = MakeNode(depth + 1); } return v; } void OutNodes(Node* v, int r, int c) // выдача поддерева // root, 1, 40 { if (r && c && (c < 80)) SCREEN[r - 1][c - 1] = v->d; // вывод метки if (r < maxrow) { if (v->lft) OutNodes(v->lft, r + 1, c -(offset >> r)); //левый сын if (v->rgt) OutNodes(v->rgt, r + 1, c + (offset >> r)); //правый сын } } //Tree(const Tree&) = delete; // конструктор копии //Tree(Tree&&) = delete; // копия с переносом (С++11) //Tree& operator = (const Tree&) const = delete; // присваивание //Tree& operator = (Tree&&) const = delete; // то же, с переносом // public: Tree(char nm, char mnm, int mxr) : num(nm), maxnum(mnm), maxrow(mxr), offset(40), root(nullptr), SCREEN(new char* [maxrow]) { for (int i = 0; i < maxrow; i++) SCREEN[i] = new char[80]; } ~Tree() { for (int i = 0; i < maxrow; i++) delete[]SCREEN[i]; delete[]SCREEN; delete root; } void MakeTree() // ввод — генерация дерева { root = MakeNode(0); } bool exist() { return root != nullptr; } // проверка «дерево не пусто» void OutTree() // выдача на экран { clrscr(); OutNodes(root, 1, offset); for (int i = 0; i < maxrow; i++) { SCREEN[i][79] = 0; cout << '\n' << SCREEN[i]; } cout << '\n'; } int DFS() // обход дерева «в глубину» { const int MaxS = 20; // максимальный размер стека int count = 0; STACK S(MaxS); //создание стека указателей на узлы S.push(root); // STACK <- root while (!S.empty()) // Пока стек не пуст… { Node* v = S.pop(); // поднять узел из стека cout << v->d << '_'; count++; // выдать тег, счет узлов if (v->rgt) S.push(v->rgt); // STACK <- (правый сын) if (v->lft) S.push(v->lft); // STACK <- (левый сын) } return count; } template class STACK { Item* S; int t; public: STACK(int maxt) { S = new Item[maxt]; t = 0; } int empty() const { return t == 0; } void push(Item item) { S[t++] = item; } Item pop() { return (t ? S[--t] : 0); } }; int result() { int rezult = 0; search_1(root, 1); search_2(root, 1); return counter(root, 1, &rezult); } void search_1(Node* v, int x) // проставляем количество сыновей в каждой вершине { while (x) { if (v->lft != nullptr) { v->count++; search_1(v->lft,1); if (v->rgt != nullptr) { v->count++; search_1(v->rgt, 1); x = 0; } x = 0; } if ((v->rgt == nullptr && v->lft == nullptr) || (v->count > 1)) { x = 0; break; } if (v->rgt != nullptr) { v->count++; search_1(v->rgt, 1); if (v->lft != nullptr) { v->count++; search_1(v->lft, 1); x = 0; } x = 0; } if (v->rgt == nullptr && v->lft == nullptr) x = 0; } } void search_2(Node* v, int x) // к количеству уже имеющихся сыновей у каждой вершины прибавляем количесвто сыновей у каждогого сына очередной вершины { while (x)// ////// { if (v->lft != nullptr) { v->count = v->count + v->lft->count; search_2(v->lft, 1); if (v->rgt != nullptr) { v->count = v->count + v->rgt->count; search_2(v->rgt, 1); x = 0; } x = 0; } if ((v->rgt == nullptr && v->lft == nullptr) || (v->count > 3)) { x = 0; break; } if (v->rgt != nullptr) { v->count = v->count + v->rgt->count; search_2(v->rgt, 1); if (v->lft != nullptr) { v->count = v->count + v->lft->count; search_2(v->lft, 1); x = 0; } x = 0; } if (v->rgt == nullptr && v->lft == nullptr) x = 0; } } int counter(Node* v, int x, int* rezult) {// в результат идут вершины в которых один или 0 сыновей* (*не сыновей а то что мы считали в прошлых двух функциях) while (x) { if (v->count < 2) { (*rezult)++; if (v->lft != nullptr) { counter(v->lft, 1, rezult); x = 0; } if (v->rgt != nullptr) { counter(v->rgt, 1, rezult); x = 0; } if (v->rgt == nullptr && v->lft == nullptr) x = 0; } else { if (v->lft != nullptr) { counter(v->lft, 1, rezult); x = 0; } if (v->rgt != nullptr) { counter(v->rgt, 1, rezult); x = 0; } if (v->rgt == nullptr && v->lft == nullptr) x = 0; } } return *rezult; } }; // int main () { int n = 0, rezult; setlocale(LC_ALL, "Russian"); srand(time(0)); Tree tr('а','я',5); tr.MakeTree(); if (tr.exist()) { tr.OutTree(); cout << '\n' << "Обход в глубину: "; n = tr.DFS(); cout << " Пройдено узлов = " << n << '\n'; rezult = tr.result(); cout << "Количество вершин, имеющих не более одного потомка: " << rezult << '\n'; } else cout << "Error." << '\n'; }