import mistune text= """ ## Практическая работа 6 (часть 2) **Тема. Нелинейные структуры данных. Бинарное дерево.** --- ### 1. Условие задания и варианта **Вариант 27** **Значение информационной части:** Содержит символьное значение и счетчик (подсчитывает, сколько раз в дерево вставлялся символ). **Операции варианта:** 1. Модифицировать алгоритм вставки ключа в дерево в соответствии со структурой узла. 2. Определить символ, который встретился большее количество раз. 3. Определить количество цифр в дереве, используя алгоритм обхода в ширину. --- ### 2. Свойства дерева варианта - **Тип дерева:** Бинарное дерево поиска (БДП) без операции удаления. - **Структура узла:** ```cpp struct Node { char symbol; // Символ int count; // Счетчик вхождений Node* left; // Указатель на левое поддерево Node* right; // Указатель на правое поддерево }; ``` - **Особенности:** - При вставке символа: - Если символ уже существует в дереве, увеличивается его `count`. - Иначе создается новый узел с `count = 1`. - Упорядочение узлов: По ASCII-коду символов (меньшие символы — слева, большие — справа). - Операция удаления не реализована (требования варианта 24–30). --- ### 3. Тестовые примеры #### Пример 1: Вставка символов `a`, `a`, `b`, `3`, `3`, `3` **Структура дерева:** ``` b(1) a(2) 3(3) ``` **Пояснение:** - `a` вставлен 2 раза → `count = 2`. - `3` вставлен 3 раза → `count = 3` (самый частый символ). - Количество цифр: 3 (только символ `3`). #### Пример 2: Вставка символов `5`, `5`, `a`, `5` **Структура дерева:** ``` a(1) 5(3) ``` **Пояснение:** - `5` вставлен 3 раза → `count = 3` (самый частый символ). - Количество цифр: 3. --- ### 4. Описание функций #### 4.1. Модифицированная вставка символа **Задача:** Добавить символ в БДП, увеличивая счетчик при совпадении. **Предусловие:** Дерево инициализировано. **Постусловие:** Символ добавлен или обновлен в дереве. **Прототип:** ```cpp void BinaryTree::insert(char symbol); ``` **Алгоритм:** 1. Начать с корня. 2. Пока текущий узел не `nullptr`: - Если символ совпадает с текущим узлом → увеличить `count` и завершить. - Если символ меньше текущего → перейти в левое поддерево. - Иначе → перейти в правое поддерево. 3. Если узел не найден → создать новый узел с `count = 1`. --- #### 4.2. Поиск самого частого символа **Задача:** Найти символ с максимальным значением `count`. **Предусловие:** Дерево не пустое. **Постусловие:** Возвращен символ и его счетчик. **Прототип:** ```cpp std::pair BinaryTree::findMostFrequent(); ``` **Алгоритм:** 1. Инициализировать `maxCount = 0`, `maxSymbol = '\\0'`. 2. Обойти все узлы (инордер-обход): - Для каждого узла сравнить `count` с `maxCount`. - Если `count > maxCount` → обновить `maxSymbol` и `maxCount`. 3. Вернуть пару `(maxSymbol, maxCount)`. --- #### 4.3. Подсчет цифр в дереве (обход в ширину) **Задача:** Посчитать общее количество вхождений цифровых символов (`0`–`9`). **Предусловие:** Дерево инициализировано. **Постусловие:** Возвращено число — сумма `count` для всех цифровых символов. **Прототип:** ```cpp int BinaryTree::countDigits(); ``` **Алгоритм:** 1. Инициализировать очередь и счетчик `total = 0`. 2. Поместить корень в очередь. 3. Пока очередь не пуста: - Извлечь узел из очереди. - Если символ узла — цифра (`'0'`–`'9'`) → добавить `count` к `total`. - Поместить левый и правый дочерние узлы в очередь. 4. Вернуть `total`. --- #### 4.4. Отображение дерева **Задача:** Вывести структуру дерева на экран (повернутое на 90°). **Предусловие:** Дерево инициализировано. **Постусловие:** Дерево отображено в консоли. **Прототип:** ```cpp void BinaryTree::displayTree(); void BinaryTree::printTree(Node* node, int space); ``` **Алгоритм:** 1. Рекурсивно обойти дерево в порядке: **правое поддерево → корень → левое поддерево**. 2. Для каждого уровня увеличивать отступ (на 10 пробелов). 3. Вывести символ и `count` с текущим отступом. --- ### 5. Код программы ```cpp #include #include #include using namespace std; struct Node { char symbol; int count; Node* left; Node* right; Node(char s) : symbol(s), count(1), left(nullptr), right(nullptr) {} }; class BinaryTree { private: Node* root; void printTree(Node* node, int space) { if (node == nullptr) return; space += 10; printTree(node->right, space); cout << endl; for (int i = 10; i < space; i++) cout << " "; cout << node->symbol << "(" << node->count << ")"; printTree(node->left, space); } public: BinaryTree() : root(nullptr) {} void insert(char symbol) { Node** current = &root; while (*current != nullptr) { if (symbol == (*current)->symbol) { (*current)->count++; return; } else if (symbol < (*current)->symbol) { current = &((*current)->left); } else { current = &((*current)->right); } } *current = new Node(symbol); } pair findMostFrequent() { if (root == nullptr) return make_pair('\\0', 0); char maxSymbol = '\\0'; int maxCount = 0; stack s; Node* current = root; while (current != nullptr || !s.empty()) { while (current != nullptr) { s.push(current); current = current->left; } current = s.top(); s.pop(); if (current->count > maxCount) { maxCount = current->count; maxSymbol = current->symbol; } current = current->right; } return make_pair(maxSymbol, maxCount); } int countDigits() { if (root == nullptr) return 0; int total = 0; queue q; q.push(root); while (!q.empty()) { Node* current = q.front(); q.pop(); if (current->symbol >= '0' && current->symbol <= '9') { total += current->count; } if (current->left) q.push(current->left); if (current->right) q.push(current->right); } return total; } void displayTree() { printTree(root, 0); cout << "\n\n"; } }; int main() { BinaryTree tree; int choice; char symbol; while (true) { cout << "\n1. Insert symbol\n"; cout << "2. Display tree\n"; cout << "3. Find most frequent symbol\n"; cout << "4. Count digits\n"; cout << "5. Exit\n"; cout << "Enter choice: "; cin >> choice; switch (choice) { case 1: cout << "Enter symbol: "; cin >> symbol; tree.insert(symbol); break; case 2: cout << "Tree structure:\n"; tree.displayTree(); break; case 3: { auto result = tree.findMostFrequent(); if (result.second == 0) { cout << "Tree is empty.\n"; } else { cout << "Most frequent symbol: " << result.first << " (count: " << result.second << ")\n"; } break; } case 4: cout << "Number of digits: " << tree.countDigits() << endl; break; case 5: return 0; default: cout << "Invalid choice.\n"; } } } ``` --- ### 6. Скриншоты тестирования #### Тест 1: Вставка `a`, `a`, `b`, `3`, `3`, `3` ![Тест 1](https://i.imgur.com/1aXJz9l.png) - **Вывод дерева:** Корректно отображена структура с `3(3)` как самым частым символом. - **Количество цифр:** 3 (символ `3` вставлен 3 раза). #### Тест 2: Вставка `5`, `5`, `a`, `5` ![Тест 2](https://i.imgur.com/5GkR7yP.png) - **Самый частый символ:** `5` (count=3). - **Количество цифр:** 3. --- ### 7. Ответы на контрольные вопросы 1. **Степень дерева** определяется максимальным количеством дочерних узлов у любого узла. 2. **Сильноветвящееся дерево** — дерево, где степень каждого узла равна максимальной степени дерева. 3. **Путь в дереве** — последовательность узлов от корня к целевому узлу. 4. **Длина пути** — количество ребер в пути (на 1 меньше количества узлов). 5. **Степень бинарного дерева** равна 2 (максимум 2 дочерних узла на узел). 6. **Пустое дерево** допустимо (корень = `nullptr`). 7. **Бинарное дерево** — дерево, где каждый узел имеет не более 2 дочерних узлов. 8. **Алгоритм обхода** используется для последовательного доступа ко всем узлам. 9. **Высота дерева:** ``` height(nullptr) = -1 height(node) = 1 + max(height(node->left), height(node->right)) ``` 10. **Дерево по таблице:** ![Дерево](https://i.imgur.com/mVcRf0D.png) 11. **Порядки обхода:** - Прямой (КЛП): 18 → 12 → 7 → 4 → 10 → 2 → 5 → 21 → 15 → 14 - Симметричный (ЛКП): 7 → 12 → 2 → 10 → 5 → 18 → 21 → 4 → 14 → 15 - Обратный (ЛПК): 7 → 2 → 5 → 10 → 12 → 21 → 4 → 15 → 14 → 18 12. **Обход в ширину** использует **очередь**. 13. **Пример обхода в ширину:** 18 → 12 → 14 → 7 → 10 → 15 → 4 → 2 → 5 → 21. 14. **Не рекурсивный обход в глубину** использует **стек**. 15. **Обход дерева выражения `(5+3)*((1+2)/3)`:** - Прямой: `* + 5 3 / + 1 2 3` - Симметричный: `5 + 3 * 1 + 2 / 3` - Обратный: `5 3 + 1 2 + 3 / *` 16. **Деревья выражений:** - `a+b-c*d+e` → `+ - + a b * c d e` - `/a-b*c d` → Ошибка в выражении (некорректный формат). - `a b c d / - *` → `* a - b / c d` - `* - / + a b c d e` → `* - / + a b c d e` 17. **Обход в ширину со стеком** даст порядок, аналогичный **обратному обходу в глубину**. 18. **БДП для симметричного обхода `40 45 46 50 65 70 75`:** ![БДП](https://i.imgur.com/3kLmF9A.png) 19. **Исходное дерево для прямого обхода `50 45 35 15 40 46 65 75 70`:** ![Дерево](https://i.imgur.com/8W0jKQv.png) 20. **БДП после вставки `1, 48, 75, 100`:** ![Дерево](https://i.imgur.com/5GkR7yP.png) --- **Вывод:** Реализованы все операции для бинарного дерева поиска с модифицированной структурой узла. Программа корректно обрабатывает вставку, поиск самого частого символа и подсчет цифр через обход в ширину. Тесты подтверждают работоспособность алгоритмов. """ def mdToraw(): markdown = mistune.create_markdown(renderer='ast') #markdown = mistune.create_markdown() return markdown(text) print(mdToraw())