First Commit
This commit is contained in:
@@ -0,0 +1,340 @@
|
||||
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<char, int> 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 <iostream>
|
||||
#include <stack>
|
||||
#include <queue>
|
||||
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<char, int> findMostFrequent() {
|
||||
if (root == nullptr) return make_pair('\\0', 0);
|
||||
char maxSymbol = '\\0';
|
||||
int maxCount = 0;
|
||||
stack<Node*> 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<Node*> 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`
|
||||

|
||||
- **Вывод дерева:** Корректно отображена структура с `3(3)` как самым частым символом.
|
||||
- **Количество цифр:** 3 (символ `3` вставлен 3 раза).
|
||||
|
||||
#### Тест 2: Вставка `5`, `5`, `a`, `5`
|
||||

|
||||
- **Самый частый символ:** `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. **Дерево по таблице:**
|
||||

|
||||
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`:**
|
||||

|
||||
19. **Исходное дерево для прямого обхода `50 45 35 15 40 46 65 75 70`:**
|
||||

|
||||
20. **БДП после вставки `1, 48, 75, 100`:**
|
||||

|
||||
|
||||
---
|
||||
|
||||
**Вывод:** Реализованы все операции для бинарного дерева поиска с модифицированной структурой узла. Программа корректно обрабатывает вставку, поиск самого частого символа и подсчет цифр через обход в ширину. Тесты подтверждают работоспособность алгоритмов.
|
||||
"""
|
||||
|
||||
|
||||
def mdToraw():
|
||||
markdown = mistune.create_markdown(renderer='ast')
|
||||
#markdown = mistune.create_markdown()
|
||||
return markdown(text)
|
||||
|
||||
print(mdToraw())
|
||||
Reference in New Issue
Block a user