Как реализовать переменное количество вложенных циклов в C++
Иногда возникает в программировании задача, когда надо реализовать переменное количество вложенных циклов, число которых неизвестно, неизвестно также количество повторений каждого цикла. Как быть? В статье предлагается способ с использованием одного лишь цикла, который имитирует множество вложенных циклов.
Идея
Количество итераций во множестве вложенных циклов равно произведению прогонов каждого вложенного цикла. Поэтому можно заменить все одним циклом с числом повторений равным этому произведению. Но в циклах важную роль играют индексы, которые меняются от итерации к итерации. Поэтому для имитации вложенности всех циклов надо для каждой итерации нашего одного цикла ставить в соответствие вектор индексов вложенных циклов. Вот этим и займемся.
У меня эта задача возникла при тестировании алгоритмов оптимизации, где множество параметров и их количество у алгоритмов может отличаться, а переписывать каждый раз код из-за разных внешних вложенных циклов не хотелось.
Подготовительные функции
Для реализации идеи вам потребуется две функции, которые приведены ниже:
template <typename T> T productOfElementsOfVector(T *vector, int n)
{
/*
Функция вычисляет произведение элементов вектора.
Входные параметры:
vector - указатель на исходный массив;
n - размер массива.
Возвращаемое значение:
Произведение элементов массива.
*/
T result = 1;
for (int i = 0; i < n; i++)
result *= vector[i];
return result;
}
void mixedMultiLogicVectorOfFullSearch(int *vector, int number, int *howMuchInElements, int n)
{
/*
Функция генерирует определенный вектор k-значной логики, где каждый элемент может
принимать разное максимальное значение, в полном переборе вариантов.
Генерируется number вектор в этом полном переборе.
Входные параметры:
vector - выходной вектор, в который записывается результат;
number - номер в массиве в полном переборе, начиная с нуля (от 0 и до произведения всех элементов массива howMuchInElements - 1);
howMuchInElements - сколько значений может принимать элемент в векторе. То есть элемент может быть 0 и howMuchInElements[i] - 1;
n - количество элементов в массиве.
Возвращаемое значение:
Отсутствует.
*/
int *countInBlock = new int[n];
int countOfAllVariants = productOfElementsOfVector(howMuchInElements, n);
countInBlock[0] = countOfAllVariants / howMuchInElements[0];
for (int i = 1; i < n; i++)
countInBlock[i] = countInBlock[i-1] / howMuchInElements[i];
for (int i = 0; i < n; i++)
vector[i] = (number / countInBlock[i]) % howMuchInElements[i];
delete [] countInBlock;
}
Сама реализация
Всё использование показано в примере:
int N = 4;//сколько параметров будет у алгоритма
int *R = new int[N];//вектор числа повторений у циклов
R[0] = 3;//Число повторений у 1 цикла
R[1] = 3;//Число повторений у 2 цикла
R[2] = 3;//Число повторений у 3 цикла
R[3] = 2;//Число повторений у 4 цикла
int M = productOfElementsOfVector(R,N);//сколько итераций вообще будет
int *P = new int[N];//вектор текущих значений индексов имитируемых вложенных циклов
//основной цикл
for (int i = 0; i < M; i++) {
mixedMultiLogicVectorOfFullSearch(P, i, R, N);//теперь в P лежат нужные индексы
//используем результат
}
delete[] R;
delete[] P;
Если мы это запустим, то вектор P будет принимать значения:
P = 0 0 0 0
P = 0 0 0 1
P = 0 0 1 0
P = 0 0 1 1
P = 0 0 2 0
P = 0 0 2 1
P = 0 1 0 0
P = 0 1 0 1
P = 0 1 1 0
P = 0 1 1 1
P = 0 1 2 0
P = 0 1 2 1
P = 0 2 0 0
P = 0 2 0 1
P = 0 2 1 0
P = 0 2 1 1
P = 0 2 2 0
P = 0 2 2 1
P = 1 0 0 0
P = 1 0 0 1
P = 1 0 1 0
P = 1 0 1 1
P = 1 0 2 0
P = 1 0 2 1
P = 1 1 0 0
P = 1 1 0 1
P = 1 1 1 0
P = 1 1 1 1
P = 1 1 2 0
P = 1 1 2 1
P = 1 2 0 0
P = 1 2 0 1
P = 1 2 1 0
P = 1 2 1 1
P = 1 2 2 0
P = 1 2 2 1
P = 2 0 0 0
P = 2 0 0 1
P = 2 0 1 0
P = 2 0 1 1
P = 2 0 2 0
P = 2 0 2 1
P = 2 1 0 0
P = 2 1 0 1
P = 2 1 1 0
P = 2 1 1 1
P = 2 1 2 0
P = 2 1 2 1
P = 2 2 0 0
P = 2 2 0 1
P = 2 2 1 0
P = 2 2 1 1
P = 2 2 2 0
P = 2 2 2 1
То есть значения будут именно такими, какими были бы индексы во вложенных циклах. И все идет в том же порядке.
Тэги:
- C++
- Алгоритм
Категории:
- blog
- it
- programming
Иногда возникает в программировании задача, когда надо реализовать переменное количество вложенных циклов, число которых неизвестно, неизвестно также количество повторений каждого цикла. Как быть? В статье предлагается способ с использованием одного лишь цикла, который имитирует множество вложенных циклов.
Иногда возникает в программировании задача, когда надо реализовать переменное количество вложенных циклов, число которых неизвестно, неизвестно также количество повторений каждого цикла. Как быть? В статье предлагается способ с использованием одного лишь цикла, который имитирует множество вложенных циклов.