위 글은 큰돌의 터전 님의 강의자료를 참조해서 정리하고 제가 알고리즘을 풀면서 더 추가적으로 사용할 만한 내용들을 정리한 글입니다.
알고리즘 풀이 강의로 큰돌의 터전님의 강의 강력 추천드립니다.
강의링크
fill()과 memset()
fill()과 memset()은 배열을 초기화 할 때 쓰입니다
fill()
fill()은 O(n)의 시간복잡도를 가지며 fill(시작값, 끝값, 초기화하는값)로 값을 초기화합니다. 모든 값을 기반으로 초기화가 가능합니다.
void fill (ForwardIterator first, ForwardIterator last, const T& val);
fill()로 배열의 값을 초기화한다고 했을 때 배열의 모든 값이 아닌 일부값을 초기화하는 경우도 있지만 보통은 전체를 초기화 합니다.
#include <bits/stdc++.h>
using namespace std;
vector<int> v[10]; // 초기값이 0인 vector 1개를 생성
vector<int> v2(10, 0); // 크기 10 * 10, 초기값은 0 2차원 vector 생성
vector <vector<int> > v3(10, vector<int>(10, 0)); // 크기가 정해지지 않은 2차원 vector 생성
vector<vector<int> > v4; // 1차원 배열을 만들어서 0으로 초기화하는 방법입니다. // 그러나 일부 컴파일러에서 통하지 않을 수도 있으니 쓰지 않는 것이 좋습니다.
int dp[10] = {0,}; // 1차원 배열 a, 2차원 배열 a2
int a[1000];
int a2[1000][1000];
int main()
{
// 이터레이터 기반으로 초기화
fill(v2.begin(), v2.end(), INF);
// 10으로 초기화, 1004까지 전체적으로 초기화 합니다.
fill(a, a + max_n, 10); // fill을 이용한 2차원 배열 초기화 방법 1
for(int i = 0; i < max_n; i++) fill(a2[i], a2[i] + max_n, INF); // fill을 이용한 2차원 배열 초기화 방법 2 [이걸 추천합니다.]
fill(&a2[0][0], &a2[0][0] + max_n * max_n, INF);
return 0;
}
memset()
memset()은 바이트단위로 초기화를 하며 0, -1, char형의 하나의 문자(a, b, c, 등..)으로 초기화를 할 때만 사용합니다.
void * memset ( void * ptr, int value, size_t num );
memset(배열의 이름, k, 배열의 크기) 이렇게 사용합니다.
#include <bits/stdc++.h>
using namespace std;
const int max_n = 1004;
int a[max_n];
int a2[max_n][max_n];
int main()
{
memset(a, -1, sizeof(a));
memset(a2, 0, sizeof(a2));
for(int i = 0; i < 10; i++) cout << a[i] << " ";
return 0;
}
//-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 %
앞의 코드를 보듯이 fill 보다는 간편하게 초기화하는 것을 볼 수 있습니다. 0 또는 -1이란 값으로 초기화할 때는 memset을 쓰는 것이 좋습니다. 그러나. 1 또는 10 이런 숫자는 절대 이 memset()으로 초기화 못하니 주의해주세요!
memcpy()
어떤 변수의 메모리에 있는 값들을 다른 변수의 “특정 메모리값”으로 복사할 때 사용합니다. 주로 배열을 깊은 복사할 때 사용합니다.
void * memcpy ( void * destination, const void * source, size_t num );
#include <bits/stdc++.h>
using namespace std;
int a[5], temp[5];
int main()
{
for(int i = 0; i < 5; i++)a[i] = i;
memcpy(temp, a, sizeof(a));
for(int i : temp) cout << i << ' ';
cout << '\n'; // 원본 배열 a를 수정하여 출력하는 로직
// a를 수정해서 ~~를 더하는 로직이 될 수 있겠죠?
a[4] = 1000; for(int i : a) cout << i << ' ';
cout << '\n'; // 그 다음 다시 temp를 기반으로 원본배열을 담아 둠.
memcpy(a, temp, sizeof(temp));
for(int i : a) cout << i << ' ';
cout << '\n'; return 0;
}
/*
0
1
2
3
4
0
1
2
3
1000
0
1
2
3
4
*/
sort()
sort()는 배열 등 컨테이너들의 요소를 정렬하는 함수입니다. 보통 array나 vector를 정렬할 때 쓰이며 O(nlogn)의 시간복잡도를 가지는 함수입니다. sort()에 들어가는 매개변수로는 3가지가 있으며 2개는 반드시 넣어야 하며 한개는 선택입니다. (넣어도 되고 안 넣어도 됩니다. 커스텀하게 정렬하고 싶을 때 넣습니다.)
sort(first, last, *커스텀비교함수)
이렇게 들어갑니다. first는 정렬하고 싶은 배열의 첫번째 이터레이터, last는 정렬하고 싶은 배열의 마지막 이터레이터를 넣으면 됩니다. 또한 [first,last) 라는 범위를 갖습니다.
즉, first는 포함하고 last는 포함하지 않는다는 의미입니다. 그렇기 때문에 예를 들어 크기가 5인 a라는 배열 전체를 sort한다고 하면 sort(a[0],a[0] + 5)라고 해야 합니다. 즉, last에 배열의 마지막요소가 아닌 그 “다음”의 위치를 넣어주어야 합니다.
다시 말하자면 a[0] + 5는 배열의 마지막원소가 아닙니다. 마지막원소는 a[0] + 4이겠죠? 하지만 sort()의 특성상 last)로 last는 포함하지 않기 때문에 마지막 원소 그 다음의 위치를 가리켜야 하는 것이죠.
3번째 인자로는 커스텀비교함수(선택)이 있습니다. sort에 커스텀비교함수를 넣지 않으면 기본적으로 오름차순이며 이를 3번째 인자에 greater<int>()를 넣어 내림차순등으로 변경할 수 있습니다. 참고로 less<int>()을 통해 오름차순으로 정렬할 수 도 있습니다
#include <bits/stdc++.h>
using namespace std;
vector<int> a; int b[5];
int main()
{
for(int i = 5; i >= 1; i--) b[i - 1] = i;
for(int i = 5; i >= 1; i--) a.push_back(i);
// 오름차순
sort(b, b + 5);
sort(a.begin(),a.end());
for(int i : b) cout << i << ' ';
cout << '\n';
for(int i : a) cout << i << ' ';
cout << '\n';
sort(b, b + 5, less<int>());
sort(a.begin(),a.end(), less<int>());
for(int i : b) cout << i << ' '; cout << '\n';
for(int i : a) cout << i << ' '; cout << '\n';
//내림차순
sort(b, b + 5, greater<int>());
sort(a.begin(),a.end(), greater<int>());
for(int i : b) cout << i << ' '; cout << '\n';
for(int i : a) cout << i << ' '; cout << '\n';
return 0;
}
/*
12345
12345
12345
12345
54321
54321
*/
pair를 기반으로 한 vector 정렬
pair를 기반으로 만들어진 vector의 경우 따로 설정하지 않으면 first, second, third 순으로 차례차례 오름차순 정렬됩니다.
#include<bits/stdc++.h>
using namespace std;
vector<pair<int, int>> v;
int main()
{
for(int i = 10; i >= 1; i--)
{
v.push_back({i, 10 - i});
}
sort(v.begin(), v.end());
for(auto it : v) cout << it.first << " : " << it.second << "\n";
return 0;
}
/*
1:9
2:8
3:7
4:6
5:5
6:4
7:3
8:2
9:1
10:0
*/
unique()
unique는 범위안의 있는 요소 중 중복되는 요소를 제거하고 중복되지 않은 요소들로 앞에서부터 정렬되어 채웁니다. 그리고 나서 나머지 요소들은 삭제하지 않고 그대로 두는 함수입니다. O(n)의 시간복잡도를 가집니다.
#include <bits/stdc++.h>
using namespace std;
vector<int> v;
int main ()
{
for(int i = 1; i <= 5; i++)
{
v.push_back(i);
v.push_back(i);
}
for(int i : v) cout << i << " "; cout << '\n';
// 중복되지 않은 요소로 채운 후, 그 다음 이터레이터를 반환한다.
auto it = unique(v.begin(), v.end());
cout << it - v.begin() << '\n';
//앞에서 부터 중복되지 않게 채운 후 나머지 요소들은 그대로 둔다.
for(int i : v) cout << i << " "; cout << '\n';
return 0;
}
/*
1 1 2 2 3 3 4 4 5 5
5
1 2 3 4 5 3 4 4 5 5 */
따라서 unique()를 통해 중복되지 않은 요소들의 집합을 만들고 싶다면 다음 코드처럼 구축 하면 됩니다. sort(), erase(), unique() 순입니다.
#include <bits/stdc++.h>
using namespace std;
vector<int> v;
int main ()
{
for(int i = 1; i <= 5; i++)
{
v.push_back(i);
v.push_back(i);
}
for(int i = 5; i >=1; i--)
{
v.push_back(i);
v.push_back(i);
}
sort(v.begin(), v.end());
for(int i : v) cout << i << " "; cout << '\n';
v.erase(unique(v.begin(), v.end()), v.end());
for(int i : v) cout << i << " ";
return 0;
}
// 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 5 5 5 5
// 1 2 3 4 5
stable_sort()
stable_sort 함수는 여러 값들이 묶여 있을 때 하나의 요소로 정렬 할 때 다른 요소들의 정렬 순서도 정렬 전과 같이 유지 될 수 있도록 하는 정렬입니다.
#include <algorithm>
bool my_sort(pair<int,int> a,pair<int,int> b)
{
return (a.second > b.second);
}
stable_sort(arr.begin(),arr.end(),my_sort);
사용은 sort와 비슷하게 사용이 됩니다.
또 stable_sort가 sort보다 빠르며, 유용하게 쓰일 때가 있다.
인자로 비교하는 함수에 레퍼런스 타입을 넣어주게 되면 컴파일 에러가 난다.
bool my_sort(pair<int,int> &a,pair<int,int> &b)
비교 함수를 이렇게 만들었었는데 자꾸 에러가 나서 레퍼런스를 지웠더니 컴파일이 됐다.
이렇게 const를 붙혀도 된다.
bool my_sort(const pair<int,int> &a,const pair<int,int> &b)
{
return (a.second > b.second);
}
이게 되는 이유는 함수의 전달인자가 반드시
bool cmp(const Type1 &a, const Type2 &b);
이렇게 생겨야 하기 때문이다.
'CPP' 카테고리의 다른 글
list(C++)(알고리즘) (0) | 2022.12.29 |
---|---|
c++ Vector 사용법(알고리즘) (0) | 2022.12.29 |
이터레이터(C++)(알고리즘) (0) | 2022.12.29 |
pair와 tuple(C++)(알고리즘) (find,find_if, 람다식 캡쳐절) (0) | 2022.12.29 |
string 사용법(C++)(알고리즘) (0) | 2022.12.29 |