Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Кашина_СП_ЛБ11

.docx
Скачиваний:
0
Добавлен:
22.09.2026
Размер:
201 Кб
Скачать

Министерство науки и высшего образования Российской Федерации Федеральное государственное бюджетное образовательное учреждение высшего образования

«Владимирский государственный университет

имени Александра Григорьевича и Николая Григорьевича Столетовых» (ВлГУ)

Колледж инновационных технологий и предпринимательства

КАФЕДРА ФИЗИКИ И ПРИКЛАДНОЙ МАТЕМАТИКИ

Лабораторная работа № 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;

}

Результат работы программы

Диаграмма:

Вывод: в ходе выполнения лабораторной работы были получены навыки создания нелинейных динамических структур данных.

Соседние файлы в предмете Системное программирование