#c #arrays #performance #structure
#c #массивы #Производительность #структура
Вопрос:
Я изучаю C самостоятельно, и я хотел бы поработать над небольшим проектом, чтобы улучшить свои навыки в C .
Я внедряю программу, позволяющую записывать ряд различных экспериментальных задач, каждая из которых имеет заранее определенный лимит времени, представленный целыми числами в единицах времени.
-
Различные виды задач могут запускаться одновременно или последовательно.
-
Один вид задач может выполняться только по одной за раз.
-
Задачи выполняются обычно продолжительностью не более 24 часов.
-
По какой-то причине компьютер, на котором запущена программа, должен перезагружаться во время выполнения задач в течение одного дня. (поэтому приходится записывать данные на диск)
-
Одна задача может запускаться и останавливаться несколько раз, поэтому time_elapsed накапливается.
Например:
задачи, time_limit (единица времени), time_elapsed (единица времени).
t0, 500, 0
t1, 1000, 700
t2, 700, 700
Как вы видите, проект — это просто таймер. Но я не уверен, как сохранить три параметра в моей программе; У меня есть
- строка: имена задач;
- целое число: ограничение по времени и
- целое число: прошедшее время.
В принципе, существует три варианта проекта, в которых запрашиваются различные способы (ваши предложения) хранения вышеуказанных данных:
-
общее количество задач составляет 10-100; цикл запуска-остановки и интервал запроса могут составлять минуты, и не требуется память;
-
общее количество задач равно 10 ^ 100; цикл запуска-остановки и интервал запроса могут составлять миллисекунды и не требуют памяти;
-
общее количество задач равно 100 !; цикл запуска-остановки и интервал запроса могут составлять миллисекунды и иметь как можно меньший объем памяти.
У меня есть несколько решений:
нуль, у меня просто есть все три переменные в трех примитивных массивах [], файлы чтения / записи при каждом обновлении с помощью индексации на основе положения массива.
во-первых, использование векторов вместо массивов в приведенном выше случае.
во-вторых, с помощью unordered_map задайте task-name в качестве ключа и задайте time_limit, time_elapsed в pair<int, int>
качестве значения. при каждом обновлении записи вводите имя задачи (строку), чтобы обновить соответствующее целочисленное значение в паре (C STL).
в-третьих, использование кортежа <string, int, int>
для хранения <task_name, time_limit, time_elapsed>
соответственно.
в-четвертых, используя массивы C struct, чтобы иметь что-то вроде
struct {
string task name;
int time_limit
int time_elapsed;};
Или любые другие типы структур данных.
Редактировать:
Для запроса структуры данных текущее состояние в любое время должно быть передано некоторым другим объектам класса программы для запуска соответствующих событий (что опущено в этом сообщении), таким образом, считывается список каждого незавершенного (time_elapsed меньше time_limit) task_name задач, прошедшее время и оставшееся времяв качестве входных данных для других объектов класса.
Если так думать, это поможет мне многому научиться.
Я хотел бы услышать комментарии / предложения о том, как выбрать эффективные структуры данных на основе различных требований, перечисленных выше.
Спасибо
Комментарии:
1. Структура данных выбирается не только для хранения данных, но и для поддержки запросов. В вашем вопросе описано, какие данные вы хотите сохранить. Но в нем не указано, какие запросы вы хотите запускать поверх данных. Поэтому я не могу сказать вам, какая структура является наиболее эффективной.
2. О, вы забыли упомянуть о деревьях B и динамических хэш-таблицах…
3. «как выбрать эффективную структуру данных». как вы определяете эффективность? Похоже, что производительность приложения не является проблемой — время сбора данных составляет минуты. Отпечаток памяти? Стиль кодирования / стоимость обслуживания исходного кода?
4. @DonghuiZhang, большое спасибо за ваш комментарий, я обновил вопрос в разделе РЕДАКТИРОВАНИЯ, включив формат запроса — отображение списка задач и его прошедшего / оставшегося времени.
5. @AdrianColomitchi Я внес некоторые изменения в сообщение на основе вашего комментария; вкратце, учитывается объем памяти, и коллекции могут быть разделены на 10 минут, например. Большое спасибо, что спросили.
Ответ №1:
Итак, проблема в том, что у вас есть коллекция троек {task_name, time_limit, time_elapsed} . Вам часто нужно найти тройку, учитывая ее task_name, чтобы обновить time_elapsed . Вам нужно вставить новые тройки. И когда срок действия задачи истекает (time_elapsed >= time_limt), вы должны удалить ее из коллекции (и, возможно, добавить в другую коллекцию), чтобы иметь возможность печатать задачи, срок действия которых не истек.
Вы могли бы сделать что-то вроде этого:
#include <set>
#include <string>
struct Task {
std::string task_name;
size_t time_limit;
size_t time_elapsed;
};
struct TaskLess {
bool operator()(const Taskamp; task1, const Taskamp; task2) {
return task1.task_name < task2.task_name;
}
};
std::set<Task, TaskLess> tasks;
Чтобы найти / обновить / вставить / удалить задачу, заданную ее task_name, выполняется логарифмический поиск. Для печати задач с истекшим сроком действия необходимо выполнить итерацию по набору.
Вы также могли бы рассмотреть дальнейшие оптимизации: (а) использовать std::unordered_map вместо set ; (б) использовать целое число в качестве ключа задачи вместо строки.
Комментарии:
1. Большое спасибо за ваш ответ! кстати, я снова обновил свой пост, чтобы задать другие требования к времени и пространству. Я бы очень хотел услышать ваш ответ.
Ответ №2:
[«Попадание в движущуюся цель» править]
Приведенный ниже ответ предлагается для сценария 1 — образцы в тысячах или около того.
Примеры в 10 ^ 100 или 100!диапазоны — если у вас нет компьютера размером с мультивселенную, лучше забудьте об этом (количество атомов в нашей наблюдаемой вселенной составляет что-то около 10 ^ 80 — 10 ^ 81). Кроме того, я не думаю, что у вас было бы время накопить такое большое количество выборок, учитывая, что возраст нашей вселенной составляет 13,8 миллиарда лет (что дает величину порядка 10 ^ 20 миллисекунд отсчета с момента Большого взрыва).
По состоянию на 2015 год общий размер данных CERN составляет всего 25 петабайт — это меньше 10 ^ 16.
Исходя из сценария использования (время сбора с интервалом в несколько минут, запрос для незавершенных задач), я бы выбрал ваше четвертое решение, сохраняя эти структуры в a std:vector
— количество записей для хранения / обработки не может быть таким большим, поэтому нет необходимости в специальных контейнерах или базе данных (запущено 20 экспериментовмесяц с периодом сбора 10 минут приведет к получению чуть более 3600 записей).
Сторона запроса, стиль C 11, искусственно раздутый код (т. Е. Не Самая компактная форма), чтобы сделать очевидным, что происходит:
std::vector<MyStruct> allSamples;
// assuming a code that fills allSamples up
// this is a lambda function, used as a predicate
auto unfinishedTest=[](const MyStructamp; s) {
return s.time_elapsed < s.time_limit;
}
auto unfinishedIterator=std::find_if(
allSamples.begin(), allSamples.end(), // range of lookup
unfinishedTest // filtering predicate
);
// now you have an iterator which only gives you unfinished tests
while(unfinishedIterator != allSamples.end()) {
const MySampleamp; unfinishedJobAtHand = *unfinishedIterator;
// do what you please
}
Ссылки:
Комментарии:
1. Большое спасибо за ваш ответ, особенно за ссылки! кстати, я снова обновил свой пост, чтобы задать другие требования к времени и пространству. Я бы очень хотел услышать ваш ответ.
2. @kaka0512 — «запрашивать разные требования к времени и пространству» ого! Не делайте этого, пожалуйста. Это делает недействительными уже предоставленные ответы — «попадание в движущуюся цель» и все такое. Лучше откройте новый вопрос, ссылающийся на старый.
3. @kaka0512 — обновил мой ответ и исключил ваши второй и третий варианты использования. Я имею в виду… вы действительно хотите рассмотреть эти случаи?