- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп
Шрифт:
Интервал:
Закладка:
21.8. Сортировка и поиск
Часто мы хотим упорядочить данные. Мы можем добиться этого, используя структуры, поддерживающие порядок, такие как map и set, или выполняя сортировку. Наиболее распространенной и полезной операцией сортировки в библиотеке STL является функция sort(), которую мы уже несколько раз использовали. По умолчанию функция sort() в качестве критерия сортировки использует оператор <, но мы можем задавать свои собственные критерии.
template<class Ran> void sort(Ran first, Ran last);
template<class Ran,class Cmp> void sort(Ran first,Ran last,Cmp cmp);
В качестве примера сортировки, основанной на критерии, определенном пользователем, покажем, как упорядочить строки без учета регистра.
struct No_case { // lowercase(x) < lowercase(y)
bool operator()(const string& x, const string& y) const
{
for (int i = 0; i<x.length(); ++i) {
if (i == y.length()) return false; // y<x
char xx = tolower(x[i]);
char yy = tolower(y[i]);
if (xx<yy) return true; // x<y
if (yy<xx) return false; // y<x
}
if (x.length()==y.length()) return false; // x==y
return true; // x<y (в строке x меньше символов)
}
};
void sort_and_print(vector<string>& vc)
{
sort(vc.begin(),vc.end(),No_case());
for (vector<string>::const_iterator p = vc.begin();
p!=vc.end(); ++p)
cout << *p << 'n';
}
Как только последовательность отсортирована, нам больше не обязательно перебирать все элементы с самого начала контейнера с помощью функции find(); вместо этого можно использовать бинарный поиск, учитывающий порядок следования элементов. По существу, бинарный поиск сводится к следующему.
Предположим, что мы ищем значение x; посмотрим на средний элемент.
• Если значение этого элемента равно x, мы нашли его!
• Если значение этого элемента меньше x, то любой элемент со значением х находится справа, поэтому мы просматриваем правую половину (применяя бинарный поиск к правой половине).
• Если значение этого элемента больше x, то любой элемент со значением х находится слева, поэтому мы просматриваем левую половину (применяя бинарный поиск к левой половине).
• Если мы достигли последнего элемента (перемещаясь влево или вправо) и не нашли значение x, то в контейнере нет такого элемента.
Для длинных последовательностей бинарный поиск выполняется намного быстрее, чем алгоритм find() (представляющий собой линейный поиск). Алгоритмы бинарного поиска в стандартной библиотеке называются binary_search() и equal_range(). Что мы понимаем под словом “длинные”? Это зависит от обстоятельств, но десяти элементов обычно уже достаточно, чтобы продемонстрировать преимущество алгоритма binary_search() над алгоритмом find(). На последовательности, состоящей из тысячи элементов, алгоритм binary_search() работает примерно в 200 раз быстрее, чем алгоритм find(), потому что он имеет сложность O(log2N) (см. раздел 21.6.4).
Алгоритм binary_search имеет два варианта.
template<class Ran, class T>
bool binary_search(Ran first,Ran last,const T& val);
template<class Ran,class T,class Cmp>
bool binary_search(Ran first,Ran last,const T& val,Cmp cmp);
Эти алгоритмы требуют, чтобы их входные последовательности были упорядочены. Если это условие не выполняется, то могут возникнуть такие интересные вещи, как бесконечные циклы. Алгоритм binary_search() просто сообщает, содержит ли контейнер заданное значение.
void f(vector<string>& vs) // vs упорядочено
{
if (binary_search(vs.begin(),vs.end(),"starfruit")) {
// в контейнере есть строка "starfruit"
}
// ...
}
Итак, алгоритм binary_search() — идеальное средство, если нас интересует, есть заданное значение в контейнере или нет. Если нам нужно найти этот элемент, мы можем использовать функции lower_bound(), upper_bound() или equal_range() (разделы 23.4 и Б.5.4). Как правило, это необходимо, когда элементы контейнера представляют собой объекты, содержащие больше информации, чем просто ключ, когда в контейнере содержатся несколько элементов с одинаковыми ключами или когда нас интересует, какой именно элемент удовлетворяет критерию поиска.
Задание
После выполнения каждой операции выведите содержание вектора на экран.
1. Определите структуру struct Item { string name; int iid; double value; /* ... */ };, создайте контейнер vector<Item> vi и заполните его десятью строками из файла.
2. Отсортируйте контейнер vi по полю name.
3. Отсортируйте контейнер vi по полю iid.
4. Отсортируйте контейнер vi по полю value; выведите его содержание на печать в порядке убывания значений (т.е. самое большое значение должно быть выведено первым).
5. Вставьте в контейнер элементы Item("horse shoe",99,12.34) и Item("Canon S400",9988,499.95).
6. Удалите два элемента Item из контейнера vi, задав поля name.
7. Удалите два элемента Item из контейнера vi, задав поля iid.
8. Повторите упражнение с контейнером типа list<Item>, а не vector<Item>.
Теперь поработайте с контейнером map.
1. Определите контейнер map<string,int> с именем msi.
2. Вставьте в него десять пар (имя, значение), например msi["lecture"]=21.
3. Выведите пары (имя, значение) в поток cout в удобном для вас виде.
4. Удалите пары (имя, значение) из контейнера msi.
5. Напишите функцию, считывающую пары из потока cin и помещающую их в контейнер msi.
6. Прочитайте десять пар из потока ввода и поместите их в контейнер msi.
7. Запишите элементы контейнера msi в поток cout.
8. Выведите сумму (целых) значений из контейнера msi.
9. Определите контейнер map<int,string> с именем mis.
10. Введите значения из контейнера msi в контейнер mis; иначе говоря, если в контейнере msi есть элемент ("lecture",21), то контейнер mis также должен содержать элемент (21,"lecture").
11. Выведите элементы контейнера mis в поток cout.
Несколько заданий, касающихся контейнера vector.
1. Прочитайте несколько чисел с плавающей точкой (не меньше 16 значений) из файла в контейнер vector<double> с именем vd.
2. Выведите элементы контейнера vd в поток cout.
3. Создайте вектор vi типа vector<int> с таким же количеством элементов, как в контейнере vd; скопируйте элементы из контейнера vd в контейнер vi.
4. Выведите в поток cout пары (

