과제3 이름 : 정진우 학번 : 201868024 / 2학년 학교 : 전주대학교 학과 : 컴퓨터공학과 과목 : 알고리즘 교수님 : 장홍준 교수님 문제 본문 문제 해결 아이디어 를 모두 ascending order로 구현 했다. 2. quickSort, MergeSort 또한 모두 ascending order로 구현했다 3. 랜덤함수(random_device rRand; 하드웨어 리소스를 기반으로 바뀌는 함수) "c++11" 으로 배열에 모두넣고 랜덤함수로 셔플하게끔하여 중복없이 1~1000, 1~10000개를 만들게 하였다. 4. 성능은 c++에서 제공하는 clock_t 를 사용하여 시작할때를 start, 끝날때를 finish로 두어 finish-start = 런타임을 CLOCK_PER_SEC(초단위)으로 나누어 초단위로 출력하게 끔 하고 float형식으로 출력하게 하였다. 1. selectionSort, bubbleSort, insertionSort 문제점 & 해결방식 1. mergeSort a. 과제3 처음 실행했을때 시간이 너무 오래걸렸다 병합정렬은 입력에 관계없이 항상 O(nlogn)을 가지기 때문에 기초 비교정렬 에 비하면 줄긴 커녕 오히려 오래 걸렸다, 이유는 함수를 call by value로 호출방식을 정했기 때문에 호출이 될때마다 array를 복사해야했기에 메모리를 할당할때 O(n)이 걸리기때문에 O(n2 ) 이 소요된 것이다. 해결방법으로는 call by reference로 바꿨다. 1 를 사용하여 push_back으로 임시배열을 동적으로 할당해주려 했는데 이것 또한 재귀함수에서 연속적으 로 동적할당하게 되면 메모리를 x2 추가로 할당하게 되는데 이렇게 할당하게 되면 더 시간이 오래걸리는 문제가 있어 서 tmp배열(LAST-START+1)로 할당하고 push_back을 직접 대입으로 바꾸어 최적화 하였다. b. c++ vector https://www.acmicpc.net/board/view/31887 2. quickSort 와 마찬가지로 call by value 때는 오래 걸렸지만 call by reference로 바꾸어 해결했다. b. i , j를 조절해가며 피벗보다 크거나, 또는 피벗보다 작은 값을 찾을때 조건을 잘못주어서 무한루프에 빠지는 경우가 있 었다. 조건을 바꾸어서 해결했다. a. mergeSort 프로세스 동작과정 입력 N = {"500" or "5000" or "50000"}을 받고 이 수가아닐시 다시시도하게끔 2. 각 입력에 맞는 if문을 실행하여 선택정렬 , 버블정렬, 삽입정렬, 합병정렬, 퀵정렬, STL내장 정렬을 시행하여 시간을 재고 출력하게 하였다. 1. OUTPUT 랜덤 출력했을때 나타나는 화면이다 과제3 2 결과 컴퓨터가 1초에 계산하는 시간을 약 1억번이라고 가정하면 a. 3개 기초 정렬의 시간 복잡도의 상한은 O(n2 )라고 할 수 있다. b. 병합정렬과 퀵정렬의 시간 복잡도 상한은 O(nlogn) c. 퀵정렬의 최악의 경우에는 O(n2 )이라고 할수 있다. d. 출처 https://www.lgsl.kr/sto/stories/60/ALMA2020020003 2. 병합 정렬의 경우 퀵정렬 과 같이 항상 시간복잡도 O(nlogn)이 걸리지만 퀵정렬에 비하면 많이 느린 수준이다. 하지만 4 번째 사진의 결과처럼 퀵정렬과 병합정렬을 정렬된 상태로 정렬을 하면 병합정렬은 평균적인 입력과 차이가 없지만 퀵정렬 은 O(n2 )의 시간복잡도를 가지는 것을 볼 수 있다. 3. 번외로 c++ STL 내장되있는 sort(begin, end)함수는 quickSort와 mergeSort를 압도적으로 제치고 가장 빨랐다. 정확한 이유는 모르지만 추측하건대 a. 메모리 관리의 차이 b. introSort라는 정렬방식의 특징상 heapSort를 사용하기 때문에 1. i. https://justicehui.github.io/medium-algorithm/2019/03/24/IntroSort/ 내장함수이기때문에 정확한 이유는 좀 더 공부해보는게 좋겠다. c. 코드 /* wlsdn2749@jj.ac.kr * 2021. 10. 16 Algorithm Report3 * Prof. hongjun jang * Comparison Sorting algorithm code * 1. mergeSort * 2. quickSort * * input data NUMBER "500", "5000", "50000" * All input data is random without duplication * * output comes with existing sort to compare with * */ #include <iostream> 과제3 3 #include <vector> #include <algorithm> #include <random> #define SWAP(a,b) {int temp=a; a=b; b=temp;} // Macro : SWAP #define NUMBER1 500 #define NUMBER2 5000 #define NUMBER3 50000 using namespace std; void merge(vector<int>&, int, int, int); void caltime(clock_t start, clock_t finish) { clock_t runtime; runtime=finish-start; cout << " : " << (float)runtime/CLOCKS_PER_SEC << "sec\n"; } vector<int> shufflingRandomCreator(vector<int> array, int n){ random_device rRand; //Using hardware resource not Seed array.clear(); for(int i=0; i<n; i++){ array.push_back(i+1); // Insert array 1~n; } 실행시간 for(int i=0; i<n; i++){ int dest = rRand() % n; SWAP(array[i], array[dest]); } return array; } void selectionSort(vector<int>array, int n){ // n = input data NUMBER "1000 or 10000" clock_t start = clock(); // start for(int rightMost = n-1, maxValue=0; rightMost>0; rightMost--){ //0 < rightMost < n-1, initial Value = 0 for(int i = 0; i<=rightMost; i++){ // find maxValue if(array[i] > array[maxValue]){ maxValue = i; } } SWAP(array[maxValue], array[rightMost]); maxValue = 0; // maxValue reset } clock_t finish = clock(); // end caltime(start, finish); } void bubbleSort(vector<int>array, int n){ clock_t start = clock(); // start for(int rightMost = n-1; rightMost>0; rightMost--){ // n = input data NUMBER "1000 or 10000" for(int i = 0; i<rightMost; i++){ if(array[i] > array[i+1]){ // if element is bigger than next ... last i+1 = rightMost not error B SWAP(array[i], array[i+1]) // SWAP between adjacent elements } } } clock_t finish = clock(); // end caltime(start, finish); } void insertionSort(vector<int> array, int n){ clock_t start = clock(); // start for(int i=1; i<n; i++) { int loc = i - 1; int newItem = array[i]; //is completed upto A[i-1] while (loc >= 0 && newItem < array[loc]) { // if newitem > array[loc] : ends array[loc + 1] = array[loc]; loc--; } array[loc + 1] = newItem; // insert } clock_t finish = clock(); // end caltime(start, finish); } void printArray(vector<int>array){ vector<int>::iterator it; for(it = array.begin(); it!=array.end(); it++){ cout << " " << *it; } } /* * mergeSort * 과제3 4 * mergeSort is originated by divide and conquer algorithm, * Split continuously array in half and Sort array one by one and Finally array will be Sorted * Array is sorted by ascending order * Divide * 1. get parameter p = left, r = right * 2. q = (p+r)/2 q = mid * 3. recursively repeat ( p , q ) (q+1, r) * 4. conquer * * Conquer * 1. get parameter p = left, q = mid, r = right * 2. makes temporary array * 3. compare p~q's element with q+1~r's element * 4. put smaller element into temporary array * --------------------------------------------- sorted * 5. copy temporary array to array */ void mergeSort(vector<int>&array, int p, int r){ if(p < r) { int q = (p + r) / 2; mergeSort(array, p, q); mergeSort(array, q + 1, r); merge(array, p, q, r); } } void merge(vector<int>&array, int p, int q, int r){ int i = p; int j = q+1; int t = 0; vector<int>tmp(r-p+1); while(i<=q && j<=r) { // left array and right array is not max if(array[i] <= array[j]){ tmp[t++] = array[i++]; // compare each array and put smaller into tmp } else tmp[t++] = array[j++]; // Sort } while(i<=q) tmp[t++] = array[i++]; // left array index ++ to q while(j<=r) tmp[t++] = array[j++]; // right array index ++ to r i=p; vector<int>::iterator it; for(it=tmp.begin(); it!=tmp.end(); it++){ array[i++] = *it; // copy tmp to array } } /* * quickSort * * quickSort is originated by divide and conquer algorithm, * Array is sorted by ascending order * pivot is first element = p * Divide * 1. get parameter p = left, r = right * 2. exit condition : p>r * 3. while(p<r) find(greater than pivot, lesser than pivot) * 4. if(p>r) SWAP(right value, pivot value) * 5. else SWAP(left value, pivot value) * 6. based on pivot left side is lesser than pivot , right side is greater than pivot * 4. recursively repeat quickSort(p , changed pivot - 1 ) (changed pivot + 1 , r) * 5. conquer * * Conquer * If the Divide is repeated recursively until the number of elements is left, it is executed until there is one remaining. * Since the pivot position is fixed each time it is divided, Finally array will be sorted. */ void quickSort(vector<int>&array, int p, int r){ if(p >= r){ return; // exit condition } int pivot = p; // pivot is the most left int i = p+1; int j = r; while(i<=j){ // if i and j cross, stop while while(array[pivot] >= array[i] && r >= i){ // find greater than pivot i++; } while(array[pivot] <= array[j] && p < j){ // find lesser than pivot 과제3 5 j--; } if(i>j){ SWAP(array[j], array[pivot]); // if crossed, change right value with pivot value }else{ SWAP(array[i], array[j]); // if not cross, change left value with right value } // left value is smaller than right value } quickSort(array, p, j-1); // based on pivot, left side quickSort(array, j+1, r); // based on pivot, right side } int main() { int N; // N = 500 or 5000 or 50000 while(1) { cout << " : " ; cin >> N; if (N == NUMBER1 || N == NUMBER2 || N == NUMBER3) { vector<int> array; array = shufflingRandomCreator(array, N); cout << "<<< >>> \n"; selectionSort(array, N); cout << "\n<<< >>> \n"; bubbleSort(array, N); cout << "\n<<< >>> \n"; insertionSort(array, N); 데이터의 개수 선택 정렬 버블 정렬 삽입 정렬 array = shufflingRandomCreator(array, N); clock_t start = clock(); // start cout << "\n<<< >>> \n"; mergeSort(array, 0, N); clock_t finish = clock(); // end caltime(start, finish); 병합 정렬 array = shufflingRandomCreator(array, N); start = clock(); // start cout << "\n<<< >>> \n"; quickSort(array, 0, N); finish = clock(); // end caltime(start, finish); 퀵 정렬 array = shufflingRandomCreator(array, N); start = clock(); cout << "\n<<<STL >>> \n"; sort(array.begin(), array.end()); finish = clock(); caltime(start, finish); break; 정렬 } else { cout << " } 입력 실패, 입력값은 500 or 5000 or 50000 이여야 합니다.\n"; } return 0; } Notion Link https://juniper-sale-45c.notion.site/3-8cbb0f7963c14781a83fbe76c5e038f8 과제3 6