
- •Міністерство освіти і науки, молоді та спорту україни Національний університет “Львівська політехніка” Кафедра програмного забезпечення
- •Інструкція
- •1. Правила оформлення та оцінювання роботи
- •Представлення множин числами (бітові маски)
- •3. Пошук наближених коренів системи нелінійних рівнянь
- •4. Деякі відомості з лінійної алгебри
- •5. Пошук перестановок послідовності символів
- •6. Програма з графічним інтерфейсом
- •Варіанти контрольної роботи
5. Пошук перестановок послідовності символів
Частина задач контрольної роботи передбачає побудову можливих перестановок введеної послідовності символів, які відповідають певній умові. Для вирішення цього завдання слід реалізувати алгоритм знаходження лексикографічно наступної перестановки, поданий у методичних вказівках до виконання практичних занять з “Комбінаторного аналізу” (с. 8 – 9). Для прикладу розглянемо наступний код:
/* Рядок з клавіатури зчитується у змінну str, ще дві змінні – strtemp1 і strtemp2 є допоміжними */
char str[80], strtemp1[80], strtemp2[80];
cin.getline(str,80,'\n');
int N = strlen(str); // довжина рядка
/* посортуємо літери рядка у порядку зростання, щоб одержати найменшу з можливих перестановок */
sort(str,N,0);
/* sort – це функція для сортування елементів масиву у порядку зростання; першим аргументом є ім'я массиву, другим – його довжина, а третім – індекс, з якого слід почати сортування (тобто, всі елементи з меншими індексами лишаються несортованими). Цю функцію можна одержати з функції сортування, описаної в інструкції до виконання лабораторної роботи № 9 з дисципліни «Основи програмування». Елементи масиву рядків символів мають тип char */
char aj; /* У змінну aj будемо запам’ятовувати символ, що підлягає заміні */
int good_permutation; int existsPermutation = 1; /* змінні, які будемо застосовувати в якості умов продовження або припинення циклів */
int permutations_number = 1; // поточна кількість перестановок
cout<<endl<<"String original "<<str<<endl;
while(existsPermutation){ /* хоча б одна ітерація циклу виконається */
for(int i = N-1; i > 0; i--) { /* Починаючи з останніх символів поточної перестановки шукаємо два такі символи аj, aj+1, що символ ліворуч менший за символ праворуч. При цьому спочатку вважаємо, що лексикографічно наступної перестановки не існує (змінній existsPermutation = 0) */
existsPermutation = 0;
good_permutation = 1; /* ця змінна використовується як ознака: якщо вона рівна 0, для двох символів аj, aj+1 не виконується умова, що всі символи з індексом понад j+1 не повинні перевищувати aj+1 */
if(str[i-1]<str[i]) // якщо знайшлися аj, aj+1
{
for(int j=i;j<N;j++)
{
/* якщо умова
не виконується,
записуємо цей факт у змінну-ознаку */
if(str[j]>str[i]) {good_permutation = 0; break;}
}
if(good_permutation) /* у цьому випадку лексикографічна перестановка існує, тому змінній existsPermutation присвоюємо 1 */
{
aj = str[i-1]; // саме цей символ підлягає заміні
existsPermutation = 1;
char *pos1 = &str[i-1]; /* створюємо новий рядок, що починається з символу aj */
sort(pos1,N-i+1,0); /* сортуємо рядок pos1, що містить (N-i+1) символів */
char *pos = strchr(pos1,aj); /* знаходимо перше входження символа aj у рядок pos1 і записуємо вказівник на нього в pos */
strncpy(strtemp1,pos1,pos-pos1+1); /* копіюємо з pos перші (pos-pos1+1) символів у рядок strtemp1 і завершуємо цей рядок нуль-символом; це будуть посортовані в порядку зростання символи рядка pos1, останнім з яких є символ aj */
strtemp1[pos-pos1+1] = '\0';
strcpy(strtemp2,pos + 2); /* у рядок strtemp2 всі посортовані в порядку зростання символи, більші за символ, наступний за aj */
str[i-1] = *(pos + 1); /* наступний за aj символ записуємо на колишнє місце символа aj */
str[i] = '\0'; /* завершуємо рядок str і «склеюємо» рядки str, strtemp1 і strtemp2. Це і буде наступна перестановка, яку виводимо на екран */
strcat(str,strtemp1);
strcat(str,strtemp2);
cout<<"next permutation:\t"<<str<<endl;
permutations_number++; /* збільшуємо лічильник знайдених перестановок */
break;
}
/* якщо за все виконання циклу for жодного разу не відбулося присвоєння 1 змінній existsPermutation, значить, лексикографічно наступної перестановки не існує, змінна existsPermutation лишиться нульовою і виконання циклу while припиниться */
}
}
} /* Виводимо кількість знайдених перестановок */
cout<<"It was found "<<permutations_number<<" permutations";
_getch();
Приклад виконання коду подано на рис. 5.
Початок: Завершення пошуку перестановок:
Рис. 5 Приклад роботи програми побудови перестановок введених символів
У С++ вже реалізовані алгоритми сортування та побудови лексикографічно наступної перестановки. Їх використання реалізує наступний код:
#include <algorithm>
#include <string>
#include <iostream>
#include <conio.h>
using namespace std;
int main(){
std::string s = "qwert";
std::sort(s.begin(), s.end());
do {
std::cout << s << '\n';
} while(std::next_permutation(s.begin(), s.end()));
_getch(); return 0;
}
Цим кодом зручно перевіряти правильність виконання самостійно розроблених кодів, що виконують цю ж задачу. Для можливості виклику sort і next_permutation слід під’єднати файл algorithm.