본문 바로가기
STL

STL set 구조체 활용 (2)- 정렬 기준 바꾸기

by Best Coding 2023. 3. 30.

2023.03.13 - [STL] - STL set 구조체활용(1) - 사용법(set은 만능이다?)

 

STL set 구조체활용(1) - 사용법(set은 만능이다?)

이번 글에서는 set의 기본 사용법을 알아보도록 하겠습니다. 그리고 마지막에는 Set을 문제 풀이에서 어떻게 사용하면 좋을지 말씀드리겠습니다. 1. set이란? set은 이진탐색트리(Binary Search Tree, BST)

best-coding.tistory.com

이전 글에서는 전반적인 set에서 구조체를 활용하는 방법에 대해서 알아봤습니다.

 

이번 글에서는 set 구조체에서 정렬기준 바꾸는 방법들을 알아보고, 코드의 의미가 뭔지도 알아보도록 하겠습니다.

set에 구조체 데이터를 담는 경우의 정렬 기준을 바꾸는 방법은 다음과 같습니다.  set 뿐만 아니라  map에도 똑같이 적용 가능합니다.

 

2가지 방법이 존재하는데 둘 중 무엇을 사용하던지 상관 없습니다!

 

방법1

#include<stdio.h>
#include<set>
using namespace std;

struct Data {
	int p;
	int id;
	int num;

	//p 큰게 앞으로, p가 같다면 id작은게 앞으로
	bool operator < (const Data &var) const {
		if (p == var.p)return id < var.id;
		return p > var.p;
	}
};

set<Data> mySet;

int main(void) {
	mySet.insert({ 1,2,10 });
	mySet.insert({ 1,1,10 });
	mySet.insert({ 2,1,10 });
	mySet.insert({ 2,5,10 });
	mySet.insert({ 3,3,10 });
	mySet.insert({ 3,1,10 });
	
	for (auto it = mySet.begin(); it != mySet.end(); it++) {
		printf("p: %d, id: %d, num: %d\n", it->p, it->id, it->num);
	}

	/* //결과
	p: 3, id : 1, num : 10
	p : 3, id : 3, num : 10
	p : 2, id : 1, num : 10
	p : 2, id : 5, num : 10
	p : 1, id : 1, num : 10
	p : 1, id : 2, num : 10
	*/
	return 0;
}

위 코드처럼 구조체 내부에 operator < 을 재정의 해주면 됩니다. 참고로 위 코드에서 p는  this.p랑 같은 것이라고 보면 됩니다. 즉 this가 var보다 앞쪽에 있을 조건을 적어주면 됩니다. 

 

방법2

#include<stdio.h>
#include<set>
using namespace std;

struct Data {
	int p;
	int id;
	int num;

	
};

struct DataCmp {
	//p 큰게 앞으로, p가 같다면 id작은게 앞으로
	bool operator () (const Data& first, const Data& second) const {
		if (first.p == second.p)return first.id < second.id;
		else return first.p > second.p;
	}
}; 

set<Data,DataCmp> mySet;

int main(void) {
	mySet.insert({ 1,2,10 });
	mySet.insert({ 1,1,10 });
	mySet.insert({ 2,1,10 });
	mySet.insert({ 2,5,10 });
	mySet.insert({ 3,3,10 });
	mySet.insert({ 3,1,10 });
	
	for (auto it = mySet.begin(); it != mySet.end(); it++) {
		printf("p: %d, id: %d, num: %d\n", it->p, it->id, it->num);
	}

	/* //결과
	p: 3, id : 1, num : 10
	p : 3, id : 3, num : 10
	p : 2, id : 1, num : 10
	p : 2, id : 5, num : 10
	p : 1, id : 1, num : 10
	p : 1, id : 2, num : 10
	*/
	return 0;
}

위 코드처럼 따로 데이터 비교용 구조체를 만들고, 그 구조체에서 operator ()을 재정의 해주면 됩니다. first가 앞에 위치하기 위한 조건을 적어준다고 생각하시면 됩니다.

 

참고( const와 &는 무엇을 의미하는건지?)

c++을 모르시는 분들의 경우 함수 파라미터에 붙어있는 const와 & 가 무엇인지 궁금하실 것 같습니다. 그리고 함수 시작하는 중괄호 전에 붙어있는 const도 처음 보실 것 같습니다. 

bool operator < (const Data &var) const {
		if (p == var.p)return id < var.id;
		return p > var.p;
}


struct DataCmp {
	//p 큰게 앞으로, p가 같다면 id작은게 앞으로
	bool operator () (const Data& first, const Data& second) const {
		if (first.p == second.p)return first.id < second.id;
		else return first.p > second.p;
	}
};

함수 파라미터에 붙어있는 const의 경우 해당 변수의 값을 변경할 수 없다는 뜻입니다. 함수 파라미터에 붙어있는 &의 경우 참조자를 의미합니다. Data& var도 가능하고 Data &var도 가능하고 Data & var도 가능합니다. 참조자는 어떤 메모리공간에 별명을 붙이는 것입니다. 즉 Data& var의 경우 어떤 메모리 공간을 var라는 이름으로 참조한다는 것입니다. 마지막으로 중괄호 전에 붙은 const는 해당 함수 내에서 모든 멤버변수(Data구조체의 경우 id,p) 값을 변경할 수 없다는 뜻입니다.

 

부가적으로 함수 파라미터에 붙어있는 const의 경우 포인터 타입일 경우 의미가 좀 더 복잡합니다.

const int* ptr1 = &value; // ptr1으로 value값 수정불가능(상수), 주소값 변경 가능
int* const ptr2 = &value; //  ptr2으로 value값 수정 가능, 주소값 변경 불가능(상수포인터)
const int* const ptr3 = &value; // ptr3으로 value 값 수정 불가능(상수), 주소값 변경 물가능(상수 포인터)

const가 타입 앞에 있을 경우: 값을 수정 불가능

const가 * 뒤에 있을 경우: 주소값 수정 불가능

 

다음에는 "set 구조체 활용 (3) - 포인터 사용"에 대해서 설명드리겠습니다.

2023.03.30 - [STL] - STL set 구조체 활용(3) - set에 구조체 포인터 담기

 

STL set 구조체 활용(3) - set에 구조체 포인터 담기

이전 글 2023.03.13 - [STL] - STL set 구조체활용(1) - 사용법(set은 만능이다?) STL set 구조체활용(1) - 사용법(set은 만능이다?) 이번 글에서는 set의 기본 사용법을 알아보도록 하겠습니다. 그리고 마지막에

best-coding.tistory.com

 

댓글