Кашина_СП_ЛБ11
.docxМинистерство науки и высшего образования Российской Федерации Федеральное государственное бюджетное образовательное учреждение высшего образования
«Владимирский государственный университет
имени Александра Григорьевича и Николая Григорьевича Столетовых» (ВлГУ)
Колледж инновационных технологий и предпринимательства
КАФЕДРА ФИЗИКИ И ПРИКЛАДНОЙ МАТЕМАТИКИ
Лабораторная работа № 11
по дисциплине «Системное программирование»
на тему: «Динамические структуры данных. Бинарные деревья.
Выполнил
студент группы ИПсп-123
Кашина Д. А.
Принял
Красильщикова В. В.
Владимир, 2026
Цель работы: получение практических навыков создания нелинейных динамических структур данных.
Задание:
person.h
#ifndef PERSON_H
#define PERSON_H
#include <string>
using namespace std;
struct Person {
string lastName;
string firstName;
int age;
char gender; // 'M' or 'F'
Person(const string& last = "", const string& first = "",
int a = 0, char g = 'M')
: lastName(last), firstName(first), age(a), gender(g) {
}
};
#endif
persontree.h
#ifndef PERSONTREE_H
#define PERSONTREE_H
#include "person.h"
#include <vector>
#include <stdexcept>
using namespace std;
class PersonTree {
private:
struct Node {
Person data;
Node* left;
Node* right;
Node(const Person& p) : data(p), left(nullptr), right(nullptr) {}
};
Node* root;
// Вспомогательные методы
Node* add(Node* node, const Person& person);
Node* remove(Node* node, const Person& person);
Node* findMin(Node* node);
void clear(Node* node);
void toArray(Node* node, vector<Person>& arr);
// Сравнение по ключу (возраст + фамилия)
bool compareByKey(const Person& a, const Person& b);
bool equalsByKey(const Person& a, const Person& b);
// Поиск по одному полю
bool existsByAge(Node* node, int age);
bool existsByLastName(Node* node, const string& lastName);
bool existsByFullKey(Node* node, const Person& person);
public:
PersonTree();
~PersonTree();
// a. Добавление элемента
void add(const Person& person);
// b. Удаление элемента по ключу
void remove(const Person& person);
// c. Проверка наличия
bool existsByFullKey(const Person& person); // по полному ключу
bool existsByAge(int age); // только по возрасту
bool existsByLastName(const string& lastName); // только по фамилии
// d. Получение всех элементов в виде массива
vector<Person> getAll();
// Проверка на пустоту
bool isEmpty() const { return root == nullptr; }
};
// Классы исключений
class DuplicatePersonException : public runtime_error {
public:
DuplicatePersonException(const string& msg) : runtime_error(msg) {}
};
class PersonNotFoundException : public runtime_error {
public:
PersonNotFoundException(const string& msg) : runtime_error(msg) {}
};
#endif
persontree.cpp
#include "persontree.h"
PersonTree::PersonTree() {
root = nullptr;
}
PersonTree::~PersonTree() {
clear(root);
}
void PersonTree::clear(Node* node) {
if (node == nullptr) return;
clear(node->left);
clear(node->right);
delete node;
}
// Сравнение по ключу: возраст + фамилия
bool PersonTree::compareByKey(const Person& a, const Person& b) {
if (a.age != b.age)
return a.age < b.age;
return a.lastName < b.lastName;
}
// Проверка равенства по ключу
bool PersonTree::equalsByKey(const Person& a, const Person& b) {
return a.age == b.age && a.lastName == b.lastName;
}
PersonTree::Node* PersonTree::add(Node* node, const Person& person) {
if (node == nullptr)
return new Node(person);
if (equalsByKey(person, node->data))
throw DuplicatePersonException("Студент с таким возрастом и фамилией уже существует!");
if (compareByKey(person, node->data))
node->left = add(node->left, person);
else
node->right = add(node->right, person);
return node;
}
void PersonTree::add(const Person& person) {
root = add(root, person);
}
PersonTree::Node* PersonTree::findMin(Node* node) {
while (node->left != nullptr)
node = node->left;
return node;
}
PersonTree::Node* PersonTree::remove(Node* node, const Person& person) {
if (node == nullptr)
throw PersonNotFoundException("Студент с указанным возрастом и фамилией не найден!");
if (compareByKey(person, node->data))
node->left = remove(node->left, person);
else if (compareByKey(node->data, person))
node->right = remove(node->right, person);
else {
// Нашли узел для удаления
if (node->left == nullptr && node->right == nullptr) {
delete node;
return nullptr;
}
if (node->left == nullptr) {
Node* temp = node->right;
delete node;
return temp;
}
if (node->right == nullptr) {
Node* temp = node->left;
delete node;
return temp;
}
Node* minNode = findMin(node->right);
node->data = minNode->data;
node->right = remove(node->right, minNode->data);
}
return node;
}
void PersonTree::remove(const Person& person) {
root = remove(root, person);
}
// Поиск по полному ключу (возраст + фамилия)
bool PersonTree::existsByFullKey(Node* node, const Person& person) {
if (node == nullptr) return false;
if (equalsByKey(person, node->data))
return true;
if (compareByKey(person, node->data))
return existsByFullKey(node->left, person);
else
return existsByFullKey(node->right, person);
}
bool PersonTree::existsByFullKey(const Person& person) {
return existsByFullKey(root, person);
}
// Поиск только по возрасту
bool PersonTree::existsByAge(Node* node, int age) {
if (node == nullptr) return false;
if (node->data.age == age)
return true;
return existsByAge(node->left, age) || existsByAge(node->right, age);
}
bool PersonTree::existsByAge(int age) {
return existsByAge(root, age);
}
// Поиск только по фамилии
bool PersonTree::existsByLastName(Node* node, const string& lastName) {
if (node == nullptr) return false;
if (node->data.lastName == lastName)
return true;
return existsByLastName(node->left, lastName) || existsByLastName(node->right, lastName);
}
bool PersonTree::existsByLastName(const string& lastName) {
return existsByLastName(root, lastName);
}
void PersonTree::toArray(Node* node, vector<Person>& arr) {
if (node == nullptr) return;
toArray(node->left, arr);
arr.push_back(node->data);
toArray(node->right, arr);
}
vector<Person> PersonTree::getAll() {
vector<Person> arr;
toArray(root, arr);
return arr;
}
main.cpp
#include <iostream>
#include <iomanip>
#include <windows.h>
#include "persontree.h"
using namespace std;
Person inputPerson() {
Person p;
cout << "Введите фамилию: ";
cin >> p.lastName;
cout << "Введите имя: ";
cin >> p.firstName;
cout << "Введите возраст: ";
cin >> p.age;
cout << "Введите пол (M/F): ";
cin >> p.gender;
return p;
}
void printPerson(const Person& p) {
cout << "| " << left << setw(12) << p.lastName
<< " | " << setw(10) << p.firstName
<< " | " << setw(6) << p.age
<< " | " << setw(8) << (p.gender == 'M' ? "Муж" : "Жен")
<< " |\n";
cout << "+--------------+------------+--------+----------+\n";
}
void printTableHeader() {
cout << "+--------------+------------+--------+----------+\n";
cout << "| " << left << setw(12) << "Фамилия"
<< " | " << setw(10) << "Имя"
<< " | " << setw(6) << "Возраст"
<< " | " << setw(8) << "Пол"
<< " |\n";
cout << "+--------------+------------+--------+----------+\n";
}
void printAllPersons(PersonTree& tree) {
vector<Person> arr = tree.getAll();
if (arr.empty()) {
cout << "\nВ базе данных нет людей.\n";
}
else {
cout << "\nСписок всех людей (упорядочено по возрасту+фамилии):\n";
printTableHeader();
for (int i = 0; i < arr.size(); i++) {
printPerson(arr[i]);
}
cout << "Всего людей: " << arr.size() << endl;
}
}
void showMenu() {
cout << "\n=====================================\n";
cout << " ГЛАВНОЕ МЕНЮ \n";
cout << "=====================================\n";
cout << " 1. Добавить человека\n";
cout << " 2. Удалить человека (по возрасту+фамилии)\n";
cout << " 3. Найти человека по возрасту+фамилии\n";
cout << " 4. Найти человека по возрасту\n";
cout << " 5. Найти человека по фамилии\n";
cout << " 6. Показать всех людей\n";
cout << " 0. Выход\n";
cout << "=====================================\n";
cout << "Ваш выбор: ";
}
int main() {
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
PersonTree tree;
int choice;
// Добавим тестовые данные
try {
tree.add(Person("Иванов", "Иван", 25, 'M'));
tree.add(Person("Петрова", "Мария", 30, 'F'));
tree.add(Person("Сидоров", "Алексей", 25, 'M'));
tree.add(Person("Кузнецова", "Елена", 35, 'F'));
tree.add(Person("Смирнов", "Дмитрий", 40, 'M'));
cout << "\n[Добавлены тестовые данные]\n";
}
catch (const exception& e) {
cout << "\nОшибка при добавлении тестовых данных: " << e.what() << endl;
}
do {
showMenu();
cin >> choice;
try {
switch (choice) {
case 1: { // Добавление
cout << "\n--- Добавление человека ---\n";
Person p = inputPerson();
tree.add(p);
cout << "\nЧеловек успешно добавлен!\n";
break;
}
case 2: { // Удаление по ключу
cout << "\n--- Удаление человека ---\n";
cout << "Введите данные для удаления (возраст+фамилия - ключ):\n";
Person p;
cout << "Введите фамилию: ";
cin >> p.lastName;
cout << "Введите возраст: ";
cin >> p.age;
tree.remove(p);
cout << "\nЧеловек успешно удален!\n";
break;
}
case 3: { // Поиск по полному ключу
cout << "\n--- Поиск по возрасту+фамилии ---\n";
Person p;
cout << "Введите фамилию: ";
cin >> p.lastName;
cout << "Введите возраст: ";
cin >> p.age;
if (tree.existsByFullKey(p)) {
cout << "\nЧеловек с фамилией '" << p.lastName
<< "' и возрастом " << p.age << " - НАЙДЕН!\n";
}
else {
cout << "\nЧеловек с фамилией '" << p.lastName
<< "' и возрастом " << p.age << " - НЕ НАЙДЕН!\n";
}
break;
}
case 4: { // Поиск по возрасту
cout << "\n--- Поиск по возрасту ---\n";
int age;
cout << "Введите возраст: ";
cin >> age;
if (tree.existsByAge(age)) {
cout << "\nЕсть человек с возрастом " << age << " лет!\n";
}
else {
cout << "\nНет человека с возрастом " << age << " лет!\n";
}
break;
}
case 5: { // Поиск по фамилии
cout << "\n--- Поиск по фамилии ---\n";
string lastName;
cout << "Введите фамилию: ";
cin >> lastName;
if (tree.existsByLastName(lastName)) {
cout << "\nЕсть человек с фамилией '" << lastName << "'!\n";
}
else {
cout << "\nНет человека с фамилией '" << lastName << "'!\n";
}
break;
}
case 6: { // Показать всех
printAllPersons(tree);
break;
}
case 0: {
cout << "\nВыход из программы...\n";
break;
}
default: {
cout << "\nНеверный выбор! Пожалуйста, попробуйте снова.\n";
break;
}
}
}
catch (DuplicatePersonException& e) {
cout << "\nОшибка: " << e.what() << endl;
}
catch (PersonNotFoundException& e) {
cout << "\nОшибка: " << e.what() << endl;
}
catch (exception& e) {
cout << "\nНепредвиденная ошибка: " << e.what() << endl;
}
} while (choice != 0);
return 0;
}
Результат работы программы
Диаграмма:
Вывод: в ходе выполнения лабораторной работы были получены навыки создания нелинейных динамических структур данных.
