일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- DP
- 가끔은 말로
- 조합론
- object detection
- tensorflow
- 2023
- 문자열
- dfs
- 가끔은_말로
- 분할 정복
- dropout
- lazy propagation
- 알고리즘
- 플로이드 와샬
- 자바스크립트
- BFS
- 백트래킹
- 너비 우선 탐색
- NEXT
- 우선 순위 큐
- 이분 탐색
- back propagation
- Overfitting
- 회고록
- 미래는_현재와_과거로
- c++
- pytorch
- 크루스칼
- 다익스트라
- 세그먼트 트리
Archives
- Today
- Total
Doby's Lab
[알고리즘] Merge Sort (합병 정렬) 구현 (C++) 본문
Merge Sort란 분할 정복의 방법을 차용한 방식으로 어떠한 경우에도 시간 복잡도가 O(nlogn)이 나오는 정렬 알고리즘이다.
- 크기가 1인 배열이 될 때까지 분할한다.
- 왼쪽 오른쪽으로 분할된 배열을 합치면서(merge) 정렬한다.
시간 복잡도가 O(nlogn)이 나오는 이유는 원소의 개수가 n인 배열을 트리화(?)시키면 무조건 높이는 logn이 된다는 사실을 안다.
+병합하는 단계에서 리커시브 콜의 길이를 생각해보면 된다.
분할하는 단계는 시간 복잡도로 치지 않는다.
그리고, 각각의 단계(각각의 리커시브 콜 모음)에서 최대 n번의 비교 연산이 일어나므로 O(n * logn)으로
>> O(nlogn)이 되는 것이다.
+다른 정렬과 달리 정렬이 된 배열을 따로 선언해줄 필요가 있었다.
#include <iostream>
#include <vector>
using namespace std;
vector<int> v;
vector<int> merge(vector<int> left, vector<int> right){
vector<int> sortingArr;
int leftIdx = 0;
int rightIdx = 0;
// left와 right에서 작은 원소들 부터 push
while(leftIdx < left.size() && rightIdx < right.size()){
if(left[leftIdx] < right[rightIdx]){
sortingArr.push_back(left[leftIdx]);
leftIdx++;
}
else{
sortingArr.push_back(right[rightIdx]);
rightIdx++;
}
}
// 남은 원소들 마저 push 해주어야 함.
if(leftIdx == left.size()){
while(rightIdx < right.size()){
sortingArr.push_back(right[rightIdx]);
rightIdx++;
}
}
else{
while(leftIdx < left.size()){
sortingArr.push_back(left[leftIdx]);
leftIdx++;
}
}
/*
cout << "merge..." << '\n';
for(int i = 0; i < sortingArr.size(); i++){
cout << sortingArr[i] << ' ';
}
cout << '\n';
*/
return sortingArr;
}
vector<int> mergeSort(vector<int> arr){
if(arr.size() < 2) return arr;
int mid = arr.size() / 2;
vector<int> left;
vector<int> right;
// 벡터 복사 관련 메서드 없나?
for(int i = 0; i < mid; i++){
left.push_back(arr[i]);
}
for(int i = mid; i < arr.size(); i++){
right.push_back(arr[i]);
}
/*
cout << '\n';
cout << "sorting..." << '\n';
for(int i = 0; i < left.size(); i++){
cout << left[i] << ' ';
}
for(int i = 0; i < right.size(); i++){
cout << right[i] << ' ';
}
cout << '\n';
*/
return merge(mergeSort(left), mergeSort(right));
}
int main(){
// 배열에 8 ~ 1 내림차순으로 push
for(int i = 8; i >= 1; i--){
v.push_back(i);
}
for(int i = 0; i < v.size(); i++){
cout << v[i] << ' ';
}
vector<int> sorted = mergeSort(v);
cout << '\n';
// 정렬된 배열 출력
for(int i = 0; i < sorted.size(); i++){
cout << sorted[i] << ' ';
}
return 0;
}
[vector.ver]
#include <iostream>
#include <vector>
using namespace std;
int n, m;
vector<int> v(100001, 0);
vector<int> merge(vector<int> leftArr, vector<int> rightArr){
vector<int> sorted;
int leftIdx = 0, rightIdx = 0;
while(leftIdx < leftArr.size() && rightIdx < rightArr.size()){
if(leftArr[leftIdx] < rightArr[rightIdx]){
sorted.push_back(leftArr[leftIdx]);
leftIdx++;
}
else{
sorted.push_back(rightArr[rightIdx]);
rightIdx++;
}
}
if(leftIdx == leftArr.size()){
while(rightIdx < rightArr.size()){
sorted.push_back(rightArr[rightIdx]);
rightIdx++;
}
}
else{
while(leftIdx < leftArr.size()){
sorted.push_back(leftArr[leftIdx]);
leftIdx++;
}
}
return sorted;
}
vector<int> mergeSort(vector<int> arr, int size){
if(size < 2) return arr;
int mid = size / 2;
vector<int> leftArr;
vector<int> rightArr;
for(int i = 0; i < mid; i++){
leftArr.push_back(arr[i]);
}
for(int i = mid; i < size; i++){
rightArr.push_back(arr[i]);
}
return merge(mergeSort(leftArr, mid), mergeSort(rightArr, size - mid));
}
int main(){
cin >> n;
for(int i = 0; i < n; i++){
cin >> v[i];
}
vector<int> mergeSortTree = mergeSort(v, n);
cout << mergeSortTree.size() << '\n';
for(int i = 0; i < n; i++){
cout << mergeSortTree[i] << ' ';
}
}
728x90
'PS > Study Note' 카테고리의 다른 글
Convex Hull (Monotone Chain 기법) 연구 일지 (0) | 2022.04.17 |
---|---|
SCC 알고리즘 2가지 (0) | 2022.04.02 |
[알고리즘] 최소 스패닝 트리 (C++), 크루스칼 알고리즘 (0) | 2021.12.16 |
[자료구조] 우선순위 큐, 비교 연산자 (C++) (0) | 2021.11.30 |
[알고리즘] 2차원 배열이란 키워드 (0) | 2021.11.24 |