/** * @brief Структура Stack реализует динамический список-стек. * * Для того, чтобы в стеке можно было хранить любые данные, в качестве типа переменной #inf используется void*. */ struct Stack { struct Stack *next; ///< Указатель на следующий элемент void *inf; ///< Информация, хранящаясяя в данном элементе }; /** * @brief Тип FlightInformation предназначен для хранения информации о полёте. */ struct FlightInformation { int id; ///< Номер рейса size_t cityId; ///< Номер целевого города в кодификаторе int distance; ///< Расстояние от Донецка до целевого города int adultTicketCost; ///< Стоимость взрослого билета int childTicketCost; ///< Стоимость детского билета char departureTime[6]; ///< Время отправления char arrivalTime[6]; ///< Время прибытия }; /** * @brief Находит длину стека за O(N). * @param beg Указатель на начало стека. * @return Длина стека. */ size_t StackLength(const struct Stack *beg) { size_t size = 0; struct Stack *run = beg; while (run != NULL) { ++size; run = run->next; } return size; } enum FieldType { FieldType_Id = 1, FieldType_CityId, FieldType_Distance, FieldType_AdultTicketCost, FieldType_ChildTicketCost, FieldType_DepartureTime, FieldType_ArrivalTime }; /** * @brief Сравнивает заданное поле структур #left и #right. * @param fieldType Тип поля, которое нужно сравнить. * @return True, если заданное поле #left <= заданного поля #right, иначе False. */ Bool lessOrEqualThan(const struct FlightInformation *left, const struct FlightInformation *right, enum FieldType fieldType) { int compResult = 0; switch (fieldType) { case FieldType_Id: return left->id <= right->id; case FieldType_CityId: return left->cityId <= right->cityId; case FieldType_Distance: return left->distance <= right->distance; case FieldType_AdultTicketCost: return left->adultTicketCost <= right->adultTicketCost; case FieldType_ChildTicketCost: return left->childTicketCost <= right->childTicketCost; case FieldType_DepartureTime: compResult = strcmp(left->departureTime, right->departureTime); return compResult <= 0; case FieldType_ArrivalTime: compResult = strcmp(left->arrivalTime, right->arrivalTime); return compResult <= 0; } return False; } /** * @brief Сортирует стек рейсов "школьной" сортировкой по заданному полю. * @param archiveStack Сортируемый стек. * @param fieldType Тип поля, по которому нужно сортировать. */ void sortArchiveBySchoolSort(struct Stack *archiveStack, enum FieldType fieldType) { struct Stack *left, *right; // Стек уже отсортирован, если в нём 1 или 0 элементов if (StackLength(archiveStack) < 2) return; left = archiveStack; right = archiveStack->next; for (left = archiveStack; left->next != NULL; left = left->next) { for (right = left->next; right != NULL; right = right->next) { if (lessOrEqualThan((struct FlightInformation *)right->inf, (struct FlightInformation *)left->inf, fieldType)) { void *inf = left->inf; left->inf = right->inf; right->inf = inf; } } } } /** * @brief Сортирует стек рейсов сортировкой вставкой по заданному полю. * @param archiveStack Сортируемый стек. * @param fieldType Тип поля, по которому нужно сортировать. */ void sortArchiveBySelectionSort(struct Stack *archiveStack, enum FieldType fieldType) { struct Stack *left, *right; // Стек уже отсортирован, если в нём 1 или 0 элементов if (StackLength(archiveStack) < 2) return; left = archiveStack; right = archiveStack->next; for (left = archiveStack; left->next != NULL; left = left->next) { struct Stack *min = left; for (right = left->next; right != NULL; right = right->next) { if (lessOrEqualThan((struct FlightInformation *)right->inf, (struct FlightInformation *)min->inf, fieldType)) { min = right; } } if (min != left) { void *inf = left->inf; left->inf = min->inf; min->inf = inf; } } }