Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Data Structures and Algorithms in C++ 2e (На ру...docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
2.37 Mб
Скачать

112 Глава 3. Множества, связанные списки и рекурсия

вовлечение данных, которые хранятся в рядах и колонках.

Множества в C ++ одномерны; мы используем единственный индекс, чтобы получить доступ к каждой клетке множества. Тем не менее, есть способ, которым мы можем определить двумерные множества в C ++ - мы можем создать двумерное множество как множество множеств. Таким образом, мы можем определить двумерное множество, чтобы быть множеством с каждой из его камер, являющихся другим множеством. Такое двумерное множество иногда также называют матрицей. В C ++, мы объявляем двумерное множество следующим образом:

международный M[8][10]; //матрица с 8 рядами и 10 колонками

Это заявление создает двумерное «множество множеств», M, который является 8 10,

наличие 8 рядов и 10 колонок. Таким образом, M - множество длины 8 таким образом что каждый

элемент M - множество длины 10 из целых чисел. (См. рисунок 3.6.)

Рисунок 3.6: двумерное множество целого числа, у которого есть 8 рядов и 10 колонок. Ценность M[3][5] равняется 100, и ценность M[6][2] 632.

Данные переменные целого числа i и j, мы могли произвести элемент ряда i и седла - umn j (или эквивалентно, j th элемент множества ith) следующим образом:

суд <<M [я] [j]; //элемент продукции последовательно я колонка j

Это часто - хорошая идея использовать символические константы, чтобы определить размеры, чтобы сделать Ваши намерения более ясными кому-то читающему Вашу программу.

интервал константы N ДНИ = 7; интервал константы N ЧАСЫ = 24; международный график [N ДНИ] [N ЧАСЫ];

Динамическое распределение матриц

Если размеры двумерного множества не известны заранее, это - NEC -

essary, чтобы ассигновать множество динамично. Это может быть сделано, применив метод, который мы обсудили ранее для распределения множеств в Разделе 1.1.3, но вместо этого, мы должны применить его к каждому отдельному ряду матрицы.

3.1. Используя множества 113

Например, предположите, что мы хотим ассигновать матрицу целого числа с n рядами и

m колонки. Каждый ряд матрицы - множество целых чисел длины m. Вспомните, что динамическое множество представлено как указатель на его первый элемент, таким образом, каждый ряд, как объявляли бы, имел бы тип int*. Как мы собираем в группу отдельные ряды, чтобы сформировать матрицу? Матрица - множество указателей ряда. Так как каждый указатель ряда имеет интервал типа*, матрица имеет интервал типа **, то есть, указатель на указатель целых чисел.

Чтобы произвести нашу матрицу, мы сначала объявляем, что M имеет этот тип и ассигнует n указатели ряда с командой «M = новый интервал* [n]». ith ряд матрицы ассигнован с заявлением «M [я] = новый интервал [m]». В Кодовом Фрагменте 3.9, мы показываем, как сделать этот данный две переменные целого числа n и m.

интервал ** M = новый интервал* [n]; //ассигнуют множество указателей ряда для (интервал i = 0; я <n; я ++)

M [я] = новый интервал [m]; //ассигнуют i-th ряд

Кодовый Фрагмент 3.9: Распределение хранения для матрицы как множество множеств.

После того, как ассигнованный, мы можем получить доступ к его элементам так же, как прежде, например, как «M [я] [j]». Как показано в Кодовом Фрагменте 3.10, освобождая матрицу включает пере - versing эти шаги. Во-первых, мы освобождаем каждый из рядов, один за другим. Мы тогда освобождаем множество указателей ряда. Так как мы удаляем множество, мы используем команду, «удаляют []».

для (интервал i = 0; я <n; я ++)

удалите [] M [я]; //удаляют i-th ряд, удаляют [] M; //удаляют множество указателей ряда

Кодовый Фрагмент 3.10: Освобождение хранения для матрицы как множество множеств.

Используя векторы STL, чтобы осуществить матрицы

Как мы видим от предыдущей секции, динамическое распределение матриц скорее

тяжелый. Векторный класс STL (вспоминают Раздел 1.5.5) обеспечивает намного более изящный способ обработать матрицы. Мы приспосабливаем тот же самый подход как выше imple-чеканка матрицы как вектор векторов. Каждый ряд нашей матрицы объявлен как «вектор <интервал>». Таким образом вся матрица, как объявляют, является вектором рядов, то есть, «вектор <вектор <интервал>>». Давайте объявим, что M имеет этот тип.

Разрешение n обозначает желаемое число рядов в матрице, требование конструктора M (n) ассигнует хранение для рядов. Однако это не ассигнует желаемое число колонок. Причина состоит в том, что конструктора по умолчанию называют для каждого ряда, и неплатеж должен построить пустое множество.

Чтобы фиксировать это, мы используем хорошую особенность векторного конструктора класса. Есть дополнительный второй аргумент, который указывает на стоимость, чтобы использовать, инициализируя

114

Глава 3. Множества, Связанные Списки и Рекурсия каждый элемент вектора. В нашем случае каждый элемент M - вектор m целых чисел, то есть, «вектор <интервал> (m)». Таким образом, данный переменные целого числа n и m, следующий кодовый фрагмент производит n m матрица как вектор векторов.

вектор <вектор <интервал>> M (n, вектор <интервал> (m)); суд <<M [я] [j] <<endl;

Пространство между вектором <интервал> и следующим»>» был добавлен, чтобы предотвратить двусмысленность с C ++ входной оператор»>>». Поскольку векторный класс STL, au-tomatically заботится об удалении его участников, мы не должны писать петлю, чтобы явно удалить ряды, когда нам было нужно с динамическими множествами.

У двумерных множеств есть много заявлений. Затем, мы исследуем простое применение двумерных множеств для осуществления позиционной игры.

Tic-Tac-Toe

Как большинство школьников знает, Tic-Tac-Toe - игра, игравшая на три тремя правление. Два игрока, X и O, чередуются в размещении их соответствующих отметок в ячейках этого правления, начинающего с игрока X. Если или игрок преуспевает в том, чтобы получить три из его или ее отметок подряд, колонки или диагонали, то тот игрок побеждает.

Это - по общему признанию не сложная позиционная игра, и это даже не так много забавы играть, так как хороший игрок О может всегда вызывать связь. Изящество экономии Tic-Tac-Toe состоит в том, что это - хороший, простой пример, показывающий, как двумерные множества могут использоваться для позиционных игр. Программное обеспечение для более сложных позиционных игр, таких как шашки, шахматы, или популярные игры моделирования, все основано на том же самом подходе, который мы иллюстрируем здесь для использования двумерного множества для Tic-Tac-Toe. (См. Упражнение P-7.11.)

Основная идея состоит в том, чтобы использовать двумерное множество, правление, чтобы поддержать игровую доску. Клетки в этом множестве хранят ценности, которые указывают, пуста ли та клетка или хранит X или O. Таким образом, правление три тремя матрица. Например, его средний ряд состоит из правления клеток [1] [0], правление [1] [1] и правление [1] [2]. В нашем случае мы принимаем решение заставить клетки во множестве правления быть целыми числами, с 0 указаниями на пустую клетку, 1

указание на X и-1 указание O. Это кодирование позволяет нам иметь простое

способ проверить, является ли данная конфигурация правления победой для X или O, а именно, если

ценности ряда, колонки или диагонали составляют в целом-3 или 3, соответственно.

Мы даем полный C ++ программа для поддержания управления Tic-Tac-Toe два

игроки в Кодовых Фрагментах 3.11 и 3.12. Мы показываем получающуюся продукцию в Фиге - ure 3.8. Обратите внимание на то, что этот кодекс - только для поддержания правления Tic-Tac-Toe и regis - утомительные шаги; это не выполняет стратегии или позволяет кому-то играть Tic-Tac-Toe против компьютера. Детали такой программы выходят за рамки этой главы, но это могло бы, тем не менее, сделать хороший проект (см. Упражнение P-7.11).