“На экране моего ноутбука появляется баг. Пусть будет! Нам нужны все читатели, которых мы можем найти.& #8221;- свободно адаптированный отДжек Корнфилд
Интервалы почти вездесущи в разработке программного обеспечения. Тем не менее, они очень легко кодируются в классы, определенные пользователем, парой чисел, поэтому они используются тольконеявнобольшую часть времени. Смысл интервала прост. Они представляют собой все элементы между нижней и верхней границей и, таким образом, множество. Но в отличие от множества, интервалы обычно не могут быть добавлены к одному новому интервалу. Если вы хотите добавить интервалы к набору интервалов, который все еще представляет собойнабор, вы приходите к идееинтервала_множеств, предоставленной этой библиотекой.
Интервальные контейнерыICLбыли первоначально разработаны вCortex Software GmbHдля решения задач, связанных с вычислениями даты и временного интервала в контексте информационной системы больницы. Интервалы времени с соответствующими значениями, такими какколичество счета-фактурыилинабор методов лечения, должны были манипулировать в статистике, программах выставления счетов и программах планирования терапии. Таким образом,ICLпоявился из тех случаев промышленного использования. Он извлекает общий код, который помогает решить общие проблемы из области проблем даты и времени и может быть полезен в других областях.
Одним из наиболее выгодных аспектов интервальных контейнеров является их очень компактное представление наборов и карт. Работа с наборами и картамиэлементовможет быть очень неэффективной, если в данной проблемной области элементы обычно встречаются в смежных кусках. Помимо компактного представления ассоциативных контейнеров, которые могут значительно снизить стоимость пространства и времени, ICL поставляется с универсальным механизмом агрегации, который позволяет сочетать ассоциированные значения значимыми способами, когда интервалы пересекаются при вставке.
Для краткого введения и обзора вы можете посмотретьпрезентационный материал поICLизBoostCon 2009.
.Интервальная контейнерная библиотека (ICL)предоставляет<intervals
>и два вида интервальных контейнеров:<interval_sets
>и<interval_maps
>.
- <
interval_set
>— этонабор, который реализуется как набор интервалов. - <
interval_map
>— этокарта, которая реализована как карта пар интервальных значений.
<Interval_sets
>и<interval_maps
>выделяют два различных аспекта в их интерфейсах: (1) Функциональность набора или карты, которая является болееабстрактным аспектом. И (2) функциональность контейнера интервалов, который является более конкретным иаспект реализации. На практике оба аспекта полезны и поэтому поддерживаются.
Первый аспект, который будет называтьсяфундаментальнымаспектом, является более важным. Это означает, что мы можем использовать<interval_set
>или<interval_map
>как набор или картуэлементов. Он выполняет те же функции.
interval_set<int> mySet;
mySet.insert(42);
bool has_answer = contains(mySet, 42);
Второй аспект, который будет называться, позволяет использовать тот факт, что элементы<interval_sets
>сгруппированы винтервалов, которые мы можем повторять.
interval<seconds>::type news(make_seconds("20:00:00"), make_seconds("20:15:00"));
interval<seconds>::type talk_show(make_seconds("22:45:30"), make_seconds("23:30:50"));
interval_set<seconds> myTvProgram;
myTvProgram.add(news).add(talk_show);
for(interval_set<seconds>::iterator telecast = myTvProgram.begin();
telecast != myTvProgram.end(); ++telecast)
TV.switch_on(*telecast);
Работа с<interval_sets
>и<interval_maps
>может быть полезной всякий раз, когда элементы множества появляются в смежных кусках:<intervals
>. Это, очевидно, имеет место во многих проблемных областях, особенно в областях, которые имеют дело с вычислениями, связанными с датой и временем.
В отличие от<std::sets
>и<maps
>,<interval_sets
>и<interval_maps
>реализуют понятия<Addable
>и<Subtractable
>. Так<interval_sets
>определяют<operator+=
>, который естественным образом реализуется какзаданное соединениеи<operator-=
>, который, следовательно, реализуется какзаданное различие. ВИкл<interval_maps
>также можно добавлять и вычитать. Очень плодотворной оказалась концепция распространения сложения или вычитания до<interval_map's
>ассоциированных значений в тех случаях, когда вставка интервальной пары значений в<interval_map
>приводила к столкновению вставленной интервальной пары значений с интервальными парами значений, которые уже находятся в<interval_map
>. Эта операция распространения называетсяагрегат на перекрытие.
Это первый мотивирующий пример очень маленькой партии, демонстрирующейагрегат на перекрытиипринцип<interval_maps
>:
В качестве примера Мария вступает в партию первой. Она присутствует во время временного интервала<[20:00,22:00)
>. Гарри приходит позже. Он находится в пределах<[21:00,23:00)
>.
typedef std::set<string> guests;
interval_map<time, guests> party;
party += make_pair(interval<time>::right_open(time("20:00"), time("22:00")), guests("Mary"));
party += make_pair(interval<time>::right_open(time("21:00"), time("23:00")), guests("Harry"));
[20:00, 21:00)->{"Mary"}
[21:00, 22:00)->{"Harry","Mary"}
[22:00, 23:00)->{"Harry"}
При перекрытии интерваловсоответствующие наборы именнакоплены.точки перекрытия. Накопление содержимого при перекрытии интервалов осуществляется через<operator+=
>, который должен быть реализован для соответствующих значений<interval_map
>. В примере соответствующие значения<guest
sets
>.<guest
set
>,<operator+=
>,<operator+=
>, [скрыто], [скрыто].
Как видно из примера,<interval_map
>имеет какдекомпозиционное поведение(по временному измерению), так инакопительное поведение(по связанным значениям).
Добавляемость и агрегат на перекрытии являются полезными функциями<interval_maps
>, реализованными с помощью функций<add
>и<operator+=
>. Но вы также можете использовать их страдиционнойсемантикой вставки, которая ведет себя как<std::map::insert
>обобщенная для интервальной вставки.
В дополнение к интервальным контейнерам мы можем работать с контейнерами элементов, которыеповеденчески равныинтервальным контейнерам: В основном они имеют одинаковую функциональность.<std::set
>STL представляет собой такую эквивалентную реализацию множества. Из-за возможностей агрегации интервальных карт icl<std::map
>принципиально не полностью эквивалентен<interval_map
>. Поэтому в icl есть дополнительный шаблон класса<icl::map
>для карт элементов.
- <
std::set
>является поведенческим равным<interval_sets
>нафундаментальномаспекте. - <
icl::map
>является поведенческим равным<interval_maps
>нафундаментальномаспекте. В частности,<icl::map
>реализуетагрегат на перекрытии, который называетсяагрегат на столкновениидля контейнера элемента.
Следующие таблицы дают обзор основных шаблонов классов, предоставляемыхicl.
Table 1.1. Interval class templates
Статически ограниченные интервалы всегда имеют один и тот же тип интервальных границ, например, прямые открытые границы<[a..b)
>для<right_open_interval
>. Динамически ограниченные интервалы могут иметь разные границы. См. главу оинтервалахдля подробностей.
Table 1.2. Container class templates
<Std::set
>помещен в паретез, потому что это не шаблон классаICL. Он может быть использован в качестве контейнера элементов, хотя это поведение равно интервалам ICL на их фундаментальном аспекте. Колонкаотносится к различным способам объединения интервальных контейнеров с добавленными интервалами. Этисочетающие стилиописаны в следующем разделе.
Когда мы добавляем интервалы или пары значений интервала в интервальные контейнеры, интервалы могут быть добавлены различными способами: Интервалы могут быть объединены, разделены или разделены. Различные интервалы сочетания стилей показаны на примере в таблицах ниже.
Table 1.3. Interval container's ways to combine intervals
Table 1.4. Interval combining styles by example
| присоединитьсяприсоединиться
[ORIG_END] --> |
разделять |
разделять |
---|
Набор | <interval_set >А | <separate_interval_set >В | <split_interval_set >С |
| <{[1 3) }
+ [2 4)
+ [45)
={[1 5)} > |
{[1 3)} }
+ [2 4)
+ [4 5)
= {[1 4)[4 5)}
|
{[1 3) }
+ [2 4)
+ [4 5)
= {[1 2)[2 3)[3 4)[4 5)}
|
Карта |
interval_map
D
| | <split_interval_map >E |
|
{[1 3)->1 }
+ [2 4)->1
+ [4 5)->1
= {[1 2)[2 3)[3 5) }
| ->1 ->2 ->1 |
| |
{[1 3)->1 }
+ [2 4)->1
+ [4 5)->1
= {[1 2)[2 3)[3 4)[4 5) }
| ->1 ->2 ->1 ->1 |
|
Обратите внимание, что<interval_sets
>A,BиCпредставляют один и тот же набор элементов<{1,2,3,4}
>и<interval_maps
>DиEпредставляют одну и ту же карту элементов<{1->1, 2->2, 3->1, 4->1}
>. Пример программыИнтервальный контейнердля дополнительной демонстрации.
<Interval_set
>и<interval_map
>всегда находятся в.минимальное представление. Это полезно во многих случаях, когда точки вставки или пересечения интервалов не актуальны. Так что в большинстве случаев<interval_set
>и<interval_map
>будут первым выбором для интервального контейнера.
<Split_interval_set
>и<split_interval_map
>, напротив, имеютвставную память. Они накапливают интервальные границы как от сложений, так и от пересечений. Это особенно полезно, если мы хотим обогатить интервальный контейнер определенными временными сетками, например, месяцами или календарными неделями или обоими. См., например,временные сетки на месяцы и недели.
<Separate_interval_set
>Реализует разделительный стиль. Этот стиль сохраняет границы, которые никогда не проходят через перекрывающийся интервал. Таким образом, если все интервалы, которые вставляются в<separate_interval_set
>генерируются, образуют определенную сетку, которая никогда не проходит, скажем, месячные границы, то эти границы сохраняются в<separate_interval_set
>.