![]() |
![]() |
![]() |
Последовательности типа list
Контейнеры типа list представляют собой двусвязные списки, то есть упорядоченные последовательности, допускающие проходы как вперед, так и назад. Операции вставки и удаления одинаково эффективны в любое место списка. Однако операции поиска и выбора элементов линейны относительно размера контейнера. Выбор по индексу вовсе невозможен. Важным свойством списка является то, что операции вставки не портят итераторы, связанные с ним, а удаление делает недействительным только тот итератор, который указывал на удаленный элемент.
В шаблоне класса
list определены методы merge, reverse, unique, remove и remove_if, которые оптимизированы
для списков. Не путайте их с одноименными шаблонами функций, которые определены
в алгоритмах. В примере, который приведен ниже, обратите внимание на операции
слияния как списков, так и контейнеров различной природы. При исследовании списков
не забудьте вставить директиву #include <list>, а также приведенный выше
набор объектов класса Man:
void main 0
{
list<Man>
men;
men.push_front(zorah);
men.push_back(mela);
men.push_back(joy);
pr(men,"Man
List");
//========
Поиск объекта
list<Man>::iterator
p = find (men.begin(),men.end(),mela);
//========
Вставка перед элементом
p = men.insert (p,joe);
// одного объекта men.insert(p,2,joe);
//
двух объектов pr(men,"After inserting 3 joes");
//========
Удаление всех вхождений joe
men.remove(j
oe);
men.sort(less<Man>()
) ;
pr(men,"After
removing all joes and sort");
//========
Создаем второй список
list<Man>
li(3,simon);
//========
Сливаем его с первым
.
men.merge (li, less<Man>'() );
pr(men,"After
merging with simons list");
//====
После слияния второй список полностью исчез
cout
« "\n\tAfter merging simons li.size: "
« li.size() « endl;
men.remove(s
imon);
//========
Создаем очередь
deque<Man>
d(men.size());
//========
Копируем в нее список
copy(men.begin(), men.end(), d.begin());
pr(d,"Deque
copied from list");
//========
Создаем вектор
vector<Man>
v (men. size () + d.sizeO);
//====
Соединяем список и очередь и помещаем в вектор merge(men.begin(),men.end(),d.begin(),d.end(),
v.begin() ) ;
pr(v,"Vector after merging list and deque");
pr(d,"Deque after merging with list");
cout «"\n\n";
}
После слияния
(merge) двух списков (men и li) размер второго списка стал нулевым, так как
он полностью влился в первый. При слиянии методом list: emerge элементы не копируются,
а вливаются в список-мишень операции. При слиянии с помощью алгоритма merge
контейнеры операнды остаются невредимыми, так как они копируются в контейнер-мишень.
Если операнды операции слияния упорядочены, то при слиянии методом list::merge
упорядоченность не нарушается, чего не наблюдается при слиянии шаблоном функции
merge. Приведем для ясности результат работы рассматриваемой программы:
Man
List # Sequence:
1.
Zoran Todorovitch, Age: 27
2.
Melissa Robinson, Age: 9
3.
Joy Amore, Age: 18
After
inserting 3 joes # Sequence:
1.
Zoran Todorovitch, Age: 27
2.
Joe Doe, Age: 30
3.
Joe Doe, Age: 30
4.
Joe Doe, Age: 30
5.
Melissa Robinson, Age: 9 6. Joy Amore, Age: 18
After
removing all joes and sort # Sequence:
1.
Melissa Robinson, Age: 9
2.
Joy Amore, Age: 18
3.
Zoran Todorovitch, Age: 27
After
merging with simons list # Sequence: 1. Melissa Robinson, Age: 9
2.
Simon Paul, Age: 15
3.
Simon Paul, Age: 15
4.
Simon Paul, Age: 15
5.
Joy Amore, Age: 18
6.
Zoran Todorovitch, Age: 27
After
merging Simons li.size: 0 Removing simons
Deque
copied from list # Sequence:
1.
Melissa Robinson, Age: 9
2.
Joy Amore, Age: 18
3.
Zoran Todorovitch, Age: 27
Vector
after merging list and deque f Sequence:
1.
Melissa Robinson, Age: 9
2.
Joy Amore, Age: 18
3.
Melissa Robinson, Age: 9
4.
Joy Amore, Age: 18
5.
Zoran Todorovitch, Age: 27
6.
Zoran Todorovitch, Age: 27
Deque
after merging with list # Sequence:
1.
Melissa Robinson, Age: 9
2.
Joy Amore, Age: 18
3. Zoran Todorovitch, Age: 27
Генерирование последовательности
С помощью алгоритма
generate удобно создавать последовательности, имеющие строго определенную структуру.
Например, если объявлен список целых из шести элементов, то его можно заполнить
значениями, сгенерированными с помощью функции generate:
//=========
Создаем список целых
list<uint>
1st (6);
//=========
Генерируем степенную последовательность
generate (1st.begin (), Ist.end(), pows);
pr(1st,"List
of generated powers");
Здесь pows
— это внешняя функция, которая при каждом обращении возвращает возрастающую
степень двойки. Эффект достигается за счет того, что static-переменная г инициализируется
единицей во время компиляции, а затем помнит свое предыдущее значение:
uint pows()
{
static
uint r = 1;
return r <= 1;
}
Если надо добиться обратного эффекта, то есть убрать закономерность в последовательности чисел, то можно воспользоваться шаблоном функции random_shuffle, которая переставляет элементы последовательности в одно из п! состояний. Например:
vector
<int> v;
for
(int i = 0; i <= 6; i++ ) v.push_back(i+1);
random_shuffle(v.begin() , v.end()) ;
pr(v,"Vector of shuffled numbers");
![]() |
![]() |
![]() |