Лабораторная работа по Алгоритмам и структурам данных. Лабораторная работа №1. Отчет по лабораторной работе 1 по дисциплине Алгоритмы и структуры данных Тема Множества Студент гр. 9891 Преподаватель
![]()
|
1 2 МИНОБРНАУКИ РОССИИ Санкт-Петербургский государственный электротехнический университет «ЛЭТИ» им. В.И. Ульянова (Ленина) Кафедра вычислительной техники отчет по лабораторной работе №1 по дисциплине «Алгоритмы и структуры данных» Тема: Множества
Санкт-Петербург 2021 Цель работы: Сравнительное исследование четырёх основных способов хранения множеств в памяти ЭВМ. Необходимо разработать программу для обработки множеств четырьмя способами (Преставление в виде массива, списка, массива битов и машинного слова). И измерить время работы алгоритма для каждого из четырех способов представления. Содержание: Представление множества в виде массива 4 Представление множества в виде списка 4 Представление множества отображением на универсум 5 Представление множества в виде машинного слова 5 Алгоритм автоматической генерации 6 Примеры автоматической генерации 7 Вывод 7 Приложение А. Код программы 8 Представление множества в виде массива Словесное описание алгоритма Изначально путем ввода символов с клавиатуры задаются 4 множества (setA,…, setD) из которых в последствии будет формироваться множество setE. После того как были сформированы множества, начинается обработка множеств, то есть получение множества setE из введенных множеств по следующей формуле: ![]() При автоматической генерации множеств изменяется только ввод элементов, вместо ручного ввода используется генерация с помощью функции rand. Подробнее о автоматической генерации в пункте 5. Временной результат работы алгоритма О ![]() Представление множества в виде списка Словесное описание алгоритма Изначально путем ввода символов задаются 4 множества setA,…,setD в виде однонаправленного линейного списка (используется функция CreateSet). После того как были сформированы множества, начинается обработка множеств, то есть получение множества setE из введенных множеств по следующей формуле: ![]() При автоматической генерации множеств изменяется только ввод элементов, вместо ручного ввода используется генерация с помощью функции rand. Подробнее о автоматической генерации в пункте 5. Временной результат работы алгоритма О ![]() Представление множества отображением на юниверсум Словесное описание алгоритма Изначально создаем массивы битов для множеств A, B, C, D, E (setArrayBitA,…, setArrayBitE) и установим все значения в 0. Также для хранения введенных символов будут использоваться множества setA,…, setD. Также создадим множество setUniversum со значением от А до Я. Теперь после того как множества setA,…, setD заполнены символами, изменим биты в множествах setArrayBitA,…, setArrayBitE. Для этого будем сравнивать множества setA,…, setD с множеством setUniversum пока символ из множеств setA,…, setD не будет равен символу из множества setUniversum. Когда будет найден такой символ, то в множестве setArrayBitA,…, setArrayBitD инвертируем бит с номером, равным порядковому номеру найденного символа в множестве setUniversum. Повторяем эти действия пока все символы из множеств setA,…, setD не будут отражены в массивы битов. После этого будем обрабатывать множество в соответствии с заданной формулой: ![]() При автоматической генерации множеств изменяется только ввод элементов, вместо ручного ввода используется генерация с помощью функции rand. Подробнее о автоматической генерации в пункте 5. Временной результат работы алгоритма О ![]() Представление множества в виде машинного слова Словесное описание алгоритма Для представления множеств в виде машинных слов создадим 4 переменных типа long mwordA,…,mwordD и присвоим им значение 0 (int нам не подходит, так как у нас множество заглавных русских букв требует 33 бита). Создаем множества setA,…,setD типа char, куда будут сохраняться вводимые множества, также создадим множество setUniversum (А,…, Я). После того как мы ввели все множества, преобразуем их в машинные слова. Для этого будем действовать следующим образом. Создадим временную переменную tempword. Далее будем сравнивать множество setA,…,setD с множеством setUniversum, пока не встретим одинаковые символы. Когда появляются равные символы, мы присваиваем биту с номером равным порядковому номеру символа в множестве setUniversum значение 1 в переменной tempword. После этого с помощью побитового ИЛИ присваиваем значение переменной tempword переменной mwordA,…, mwordD. Продолжаем эти действия пока все множества не будут переведены в машинные слова. После этого приступаем к обработке множеств по заданной формуле: ![]() При автоматической генерации множеств изменяется только ввод элементов, вместо ручного ввода используется генерация с помощью функции rand. Подробнее о автоматической генерации в пункте 5. Временной результат работы алгоритма О ![]() Алгоритм автоматической генерации Для автоматической генерации во всех случаях используется фунция rand и вспомогательное множество setUniversum(А,…, Я). С помощью функции rand выбирается произвольное число от 0 до 32 и ему сопоставляется буква из множества setUniversum, которая и присваивается в одно из множеств вместо ручного ввода. А) Автоматическая генерация. Массив. ![]() Б) Автоматическая генерация. Список. ![]() В) Автоматическая генерация. Универсум. ![]() Г) Автоматическая генерация. Машинное слово. ![]() Вывод Исходя из результатов работы программы мы видим, что самая быстрая скорость работы у машинного слова, а самая медленная у списка. Это было ожидаемо, так как побитовые операции значительно быстрее выполняются, чем итерация по списку. Отсюда можно сделать вывод, что если для решения задачи требуется высокая скорость обработки данных, то лучше всего использовать представление в виде машинного слова, хотя оно обладает некоторыми ограничениями, такими как ограниченный размер хранения данных, который ограничивается размером простого типа (int, long и т.д.). Для решения этого ограничения надо будет использовать двойные машинные слова. В случае списка таких проблем нет, мы ограничены только памятью ЭВМ. Приложение А. Код программы #include #include #include #include #include #include using namespace std; void inputLetter(int amount, char* setLetter); void concatenationLetter(char* setSum, char* setLetter_1, char* setLetter_2, char* setLetter_3); void compareAndcopyLetter(char* setLetterA, char* setLetterTemp, char* setLetterE); void compareString(char* setInput, int num); int numA, numB, numC, numD, numE; char temp_1, temp_2; char setElst[256], setAlst[256], setBlst[256]; struct SetNode { char element;}; struct ListSet { SetNode Set; ListSet* next;}; void CreateSet(ListSet** begin); void ShowSet(ListSet* begin); int main(){ setlocale(LC_ALL, "rus"); SetConsoleCP(1251); // Ввод с консоли в кодировке 1251 SetConsoleOutputCP(1251); // Вывод на консоль в кодировке 1251. Нужно только будет изменить шрифт консоли на Lucida Console или Consolas char setUniversum[33] = { 'А','Б','В','Г','Д','Е','Ё','Ж','З','И','Й','К','Л','М','Н','О','П','Р','С','Т','У','Ф','Х','Ц','Ч','Ш','Щ','Ъ','Ы','Ь','Э','Ю','Я' }; int choice = 0; cout << "Меню:" << endl; cout << "1. Массив." << endl; cout << "2. Список" << endl; cout << "3. Массив битов/универсум" << endl; cout << "4. Машинное слово" << endl; cout << "5. Массив. Генерация множества." << endl; cout << "6. Список. Генерация множества." << endl; cout << "7. Массив битов/универсум. Генерация множества." << endl; cout << "8. Машинное слово. Генерация множества." << endl; cout << "Введите цифру, которая соответствует вашему выбору: "; cin >> choice; if (choice == 1) { cout << "Введите количество элементов множества A: "; cin >> numA; cin.ignore(); char* setA = new char[numA + 1]; inputLetter(numA, setA); cout << "Введите количество элементов множества B: "; cin >> numB; cin.ignore(); char* setB = new char[numB + 1]; inputLetter(numB, setB); cout << "Введите количество элементов множества C: "; cin >> numC; cin.ignore(); char* setC = new char[numC + 1]; inputLetter(numC, setC); cout << "Введите количество элементов множества D: "; cin >> numD; cin.ignore(); char* setD = new char[numD + 1]; inputLetter(numD, setD); auto start = chrono::steady_clock::now(); char* setTemp = new char[numB + numC + numD + 1]; concatenationLetter(setTemp, setB, setC, setD); char* setE = new char[numA + 2]; compareAndcopyLetter(setA, setTemp, setE); auto stop = chrono::steady_clock::now(); auto second = chrono::duration_cast<chrono::nanoseconds>(stop - start); cout << "\nМножество A: ";cout << setA << endl; cout << "Множество B: ";cout << setB << endl; cout << "Множество C: ";cout << setC << endl; cout << "Множество D: ";cout << setD << endl; cout << "Множество Е: ";cout << setE << endl; cout << "\nВремя работы: " << second.count() << " наносекунд" << endl; delete[] setA;} if (choice == 2) { ListSet* beginA = NULL; ListSet* endA = NULL; ListSet* beginB = NULL; ListSet* endB = NULL; ListSet* beginC = NULL; ListSet* endC = NULL; ListSet* beginD = NULL; ListSet* endD = NULL; ListSet* beginE = NULL; ListSet* endE = NULL; CreateSet(&beginA); CreateSet(&beginB); CreateSet(&beginC); CreateSet(&beginD); ListSet* tempA = new ListSet; tempA = beginA; ListSet* tempB = new ListSet; tempB = beginB; ListSet* tempC = new ListSet; tempC = beginC; ListSet* tempD = new ListSet; tempD = beginD; cout << "\nМножество А: "; while (beginA != NULL) { cout << beginA->Set.element; beginA = beginA->next;} cout << "\nМножество B: "; while (beginB != NULL) { cout << beginB->Set.element; beginB = beginB->next;} cout << "\nМножество C: "; while (beginC != NULL) { cout << beginC->Set.element; beginC = beginC->next;} cout << "\nМножество D: "; while (beginD != NULL) { cout << beginD->Set.element; beginD = beginD->next;} auto start = chrono::steady_clock::now(); while (beginA != NULL) { while (beginB != NULL) { if (beginB->Set.element == beginA->Set.element) { beginA->Set.element = '8';} beginB = beginB->next;} beginA = beginA->next; beginB = tempB;} beginA = tempA; while (beginA != NULL) { while (beginC != NULL) { if (beginC->Set.element == beginA->Set.element) { beginA->Set.element = '8';} beginC = beginC->next;} beginA = beginA->next; beginC = tempC;} beginA = tempA; while (beginA != NULL) { while (beginD != NULL) { if (beginD->Set.element == beginA->Set.element) { beginA->Set.element = '8';} beginD = beginD->next;} beginA = beginA->next; beginD = tempD;} beginA = tempA; beginD = tempD; int count = 0; while (beginA != NULL) { if (beginA->Set.element != '8') { beginD->Set.element = beginA->Set.element; count++; beginD = beginD->next;} beginA = beginA->next;} beginD = tempD; beginA = tempA; beginB = tempB; beginC = tempC; cout << "\nМножество Е: "; while (count != 0) { cout << beginD->Set.element; beginD = beginD->next; count--;} auto stop = chrono::steady_clock::now(); auto second = chrono::duration_cast<chrono::nanoseconds>(stop - start); cout << "\nВремя работы: " << second.count() << " наносекунд" << endl; } if (choice == 3) { int setArrayBitA[33]; int setArrayBitB[33]; int setArrayBitC[33]; int setArrayBitD[33]; int setArrayBitE[33]; for (int i = 0; i < 33; i++) { setArrayBitA[i] = false; setArrayBitB[i] = false; setArrayBitC[i] = false; setArrayBitD[i] = false; setArrayBitE[i] = false;} char setE[33]; cout << "Введите количество элементов множества A: "; cin >> numA; cin.ignore(); char* setA = new char[numA + 1]; inputA: cout << "Введите элементы множества A: "; cin.getline(setA, numA + 1, '\n'); for (int i = 0; i < numA; i++) { if (!isupper((unsigned char)setA[i])) { cout << "Вы произвели неверный ввод символа. Повторите ввод!\n"; 1 2 |