Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции C++.doc
Скачиваний:
0
Добавлен:
06.02.2020
Размер:
1.44 Mб
Скачать

9.8 Класс list

Класс list представляет собой реализацию класса двусвязного списка в виде шаблона, т.е. list – это двусвязный список, способный хранить данные любого типа. Вообще список – это структура данных, отличающаяся от массива тем, что данные хранятся не в непрерывном участке памяти и что допускается добавление элементов во внутрь и в начало списка, т.е. не только в конец. Рассмотрим пример, в котором объявляется список переменных типа int.

#include <list>

using namespace std;

void main()

{

list<int> l;

}

Здесь объявление list<int> l; создает объект l, имеющий тип “список переменных типа int”.

Класс list имеет много общего с классом vector в плане поддерживаемых операций и имен функций-членов. С объектами-списками также можно работать различными способами. Один из вариантов – заполнение списка некоторыми значениями, добавляя их в конец списка. Такую операцию выполняет функция-член push_back().

#include <list>

#include <iostream.h>

using namespace std;

void main()

{

list<int> l;

l.push_back(1);

if(l.size() != 0) cout << "Last element: " << l.back() << endl;

l.push_back(2);

if(l.size() != 0) cout << "New last element: " << l.back() << endl;

}

Эта программа выводит:

Last element: 1

New last element: 2

В данном примере объявляется объект l – список переменных типа int. Затем в конец списка помещается значение 1 (на самом деле оно становится первым значением), после чего выводится на экран. Функция-член size() возвращает число элементов списка и используется здесь для проверки успешности добавления в список нового элемента. Функция-член back() возвращает ссылку на последний элемент списка (в данном случае это все та же 1).

После этого в конец списка добавляется элемент 2 и ситуация повторяется.

Структура данных список не требует перевыделений памяти, поэтому при работе с list можно смело использовать функцию-член push_back(), если это необходимо. По той же причине в классе list отсутствуют функции reserve() и capacity(), которые имелись в классе vector.

При работе со списком необходимо каким-то образом получать доступ к элементам, хранящимся в списке. Однако, в отличие от vector, в классе list нет оператора индексации. Это объясняется тем, что элементы списка хранятся не в непрерывном участке памяти. Для доступа к отдельным элементам класс list использует итераторы. Рассмотрим пример:

#include <vector>

#include <iostream.h>

using namespace std;

void main()

{

list<int> l;

list<int>::iterator i;

l.push_back(10);

l.push_back(20);

l.push_back(30);

cout << "The list is now:";

for(i = l.begin(); i != l.end(); i++)

cout << " " << *i;

}

Вывод программы:

The list is now: 10 400 30

В данной программе i – итератор. Обратите внимание, что он объявлен с указанием соответствующего класса. Дело в том, что итераторы зависят от типа данных, на которые они указывают. Итератор можно понимать как особый вид указателя на элемент списка. После того, как список заполнен тремя числами, его содержимое в цикле выводится на экран. Функция-член begin() возвращает итератор, указывающий на первый элемент списка. В цикле итератор i инициализируется именно этим значением. Цикл продолжается, пока итератор i не примет значение, возвращаемое функцией-членом end(), которая возвращает итератор, указывающий на элемент, следующий за последним в списке. Для навигации по элементам списка к итератору i применяется оператор ++. С помощью операции *, примененной к итератору i, обеспечивается доступ непосредственно к значению элемента списка. С помощью итераторов также можно присваивать значения элементам списка.

Как было сказано, в список можно добавлять и удалять элементы на любой позиции. Для этого используются функции-члены insert() и erase() соответственно. Рассмотрим пример на добавление элементов:

#include <iostream.h>

#include <list>

using namespace std;

void main()

{

list<int> l;

list<int>::iterator i;

l.push_back(10);

l.push_back(20);

l.push_back(30);

cout << "l =";

for(i = l.begin(); i != l.end(); i++)

cout << " " << *i;

cout << endl;

i = l.begin();

i++;

l.insert(i, 999);

cout << "l =";

for(i = l.begin(); i != l.end(); i++)

cout << " " << *i;

cout << endl;

}

Вывод программы:

l = 10 20 30

l = 10 999 20 30

Для указания позиции, куда будет добавлен элемент, используется итератор. Выражение i = l.begin(); присваивает i адрес первого элемента списка. Выражение i++; приводит к тому, что i теперь указывает на второй элемент списка. Поэтому при вызове функции insert() значение 999 добавляется на вторую позицию. Важно понимать, что при этом список увеличивается, т.е. элемент, ранее стоявщий вторым, теперь является третьим, третий – четвертым и т.д.

Пример с удалением элементов из списка:

#include <iostream.h>

#include <list>

using namespace std;

void main()

{

list<int> l;

list<int>::iterator i;

l.push_back(10);

l.push_back(20);

l.push_back(30);

l.push_back(40);

l.push_back(50);

cout << "The initial list is:";

for(i = l.begin(); i != l.end(); i++)

cout << " " << *i;

cout << endl;

l.erase(l.begin());

cout << "After erasing the first element, the list becomes:";

for(i = l.begin(); i != l.end(); i++)

cout << " " << *i;

cout << endl;

i = l.begin();

i++;

l.erase(i);

cout << "After erasing the new second element the list becomes: ";

for(i = l.begin(); i != l.end(); i++)

cout << " " << *i;

cout << endl;

}

Вывод программы:

The initial list is: 10 20 30 40 50

After erasing the first element, the list becomes: 20 30 40 50

After erasing the new second element the list becomes: 20 40 50

Для указания удаляемых из списка элементов также используются итераторы. После заполнения списка в приведенной выше программе и вывода его содержимого на экран команда l.erase(l.begin()); вызывает удаление первого элемента списка. Затем, после вывода содержимого списка на экран, пара команд i = l.begin(); i++; приводят к тому, что i указывает на второй элемент полученного списка. Команда l.erase(i); вызывает удаление этого второго элемента списка.

Другие полезные функции-члены класса list:

  • clear() – очищает список, т.е. удаляет все хранящиеся в нем элементы;

  • empty() – возвращает истину, если в списке нет элементов, т.е. если он пустой;

  • front() – возвращает ссылку на первый элемент списка;

  • push_front() – добавляет элемент в начало списка;

  • pop_front() – удаляет первый элемент списка;

  • pop_back() – удаляет последний элемент списка.