우선순위 큐, 순열, k값 찾기

2025. 2. 10. 18:12·알고리즘(코딩테스트)

1. 우선순위 큐


1 - 1. 기본 개념

  • 우선순위를 가지고 정렬 되어 있는 큐
  • 내부적으로 Heap 자료구조를 사용한다.
  • 삽입 삭제는 "항상" O(logN), 우선순위 높은 원소 검색은 O(1)

 

1 - 2. 사용하기

  • 기본적으로 가장 큰 원소가 먼저 나오는 최대 힙으로 구현 되어 있다.
  • 최소힙을 위해서는 아래와 같이 구현하면 된다.
    • 첫번째 인자는 자료형
    • 두번째 인자는 구현체
    • 세번째 인자는 비교연산자(비교 함수)
priority_queue<int, vector<int>, greater<int>> minPQ;
  • 새롭게 만든 타입을 사용하는 경우의 예시
#include <iostream>
#include <string>
#include <queue>
using namespace std;

class Student
{
public:
	string name;
	int age;
};

struct cmp
{
	bool operator()(Student& a, Student& b)
	{
		return a.age < b.age;
	}
};
int main()
{
	priority_queue<Student, vector<Student>, cmp>pq;

	Student s1("A", 19);
	Student s2("B", 22);
	Student s3("Z", 30);
	Student s4("C", 15);

	pq.push(s1);
	pq.push(s2);
	pq.push(s3);
	pq.push(s4);

	while (!pq.empty())
	{
		cout << pq.top().name << " " << pq.top().age << " ";
		cout << "\n";
		pq.pop();
	}
}

 

 

1 - 3. 주의 사항

  • 주의 사항 1) 벡터와는 다른 정렬 기준
    • 기본적으로 vector에서 비교함수를 return a.age < b.age 로 만들면, 오름차순 정렬이 된다.
    • 그러나 우선순위큐는 "내림차순"이기 때문에, 비교연산자에서 a.age < b.age를 통해서 나온 결과물이 vector와 반대인 내림차순으로 나오게 된다.
    • 아래 코드 참고
#include <iostream>
#include <string>
#include <queue>
#include <algorithm>
using namespace std;

class Student
{
public:
	string name;
	int age;
};

struct cmp
{
	bool operator()(Student& a, Student& b)
	{
		return a.age < b.age;
	}
};

bool cmp2(Student& a, Student& b)
{
	return a.age < b.age;
}

int main()
{
	vector<Student> vec;

	priority_queue<Student, vector<Student>, cmp>pq;

	vec.push_back({ "A", 19 });
	vec.push_back({ "B", 22 });
	vec.push_back({ "Z", 30 });
	vec.push_back({ "C", 15 });

	sort(vec.begin(), vec.end(), cmp2);

	for (const auto v : vec)
		cout << v.name << " " << v.age << "\n";
	cout << "\n";

	//
	Student s1("A", 19);
	Student s2("B", 22);
	Student s3("Z", 30);
	Student s4("C", 15);

	pq.push(s1);
	pq.push(s2);
	pq.push(s3);
	pq.push(s4);

	while (!pq.empty())
	{
		cout << pq.top().name << " " << pq.top().age << " ";
		cout << "\n";
		pq.pop();
	}
}
  • 위 코드의 출력 결과물
    • 위) 벡터의 정렬
    • 아래) 우선순위 큐정렬

  • 주의 사항 2) 같은 값이 있는 경우
    • Student의 age가 다 같은 경우 위의 코드를 실행하면, name의 우선순위와는 관련없는 결과가 나온다.
    • 그렇기 때문에, age가 같은 경우 name으로 정렬해주는 등의 처리가 있으면 좋을 것이다.
#include <iostream>
#include <string>
#include <queue>
#include <algorithm>
using namespace std;

class Student
{
public:
	string name;
	int age;
};

struct cmp
{
	bool operator()(Student& a, Student& b)
	{
		return a.age < b.age;
	}
};

int main()
{
	vector<Student> vec;

	priority_queue<Student, vector<Student>, cmp>pq;
    
	Student s1("A", 19);
	Student s2("B", 19);
	Student s3("C", 19);
	Student s4("D", 19);
	Student s5("Z", 19);
	Student s6("F", 19);

	pq.push(s1);
	pq.push(s2);
	pq.push(s3);
	pq.push(s4);
	pq.push(s5);
	pq.push(s6);

	while (!pq.empty())
	{
		cout << pq.top().name << " " << pq.top().age << " ";
		cout << "\n";
		pq.pop();
	}
}

 

 

2.  순열


주어진 범위 안에서 순열을 찾아주는 아래와 같은 함수가 있다.

algorithm 헤더를 include 한 다음 사용한다.

2 -1. next_permutation

  • 주어진 범위를 사전순으로 "다음 순열"로 바꿔준다.
    • 다음 순열이라는 것이 사전 순서로 현재 순열의 다음 순열을 뜻한다.
  • 간단한 예제
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int main()
{
	vector<int> vec = { 1,2,3 };
	for (int x : vec)
		cout << x << " "; //1 2 3 
	cout << "\n";

	next_permutation(vec.begin(), vec.end());
	for (int x : vec)
		cout << x << " "; //1 3 2
}

 

2 - 2. prev_permutation

  • 주어진 범위를 사전순으로 "이전 순열"로 바꿔준다.
  • 간단한 예제
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int main()
{
	vector<int> vec = { 1,2,3 };
	for (int x : vec)
		cout << x << " "; //1 2 3 
	cout << "\n";

	prev_permutation(vec.begin(), vec.end());
	for (int x : vec)
		cout << x << " "; //3 2 1
}

 

2 - 3. 추가 예제

  • 1,2,3으로 만들수 있는 모든 순열을 출력하는 예제이다.
    • 만약 vec을 {1,3,2} 로 만들면 1,3,2 이후의 순열 값들이 나오게 된다.
    • 만약 vec을  {3,2,1}로 만들면 3,2,1 만 출력되게 된다. 
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int main()
{
	vector<int> vec = { 1,2,3 };
	do
	{
		for (int x : vec)
			cout << x << " ";
		cout << "\n";
	} while (next_permutation(vec.begin(), vec.end()));
}

 

 

3. k값 찾기 - nth_element


nth_element 함수는 pivot을 기반으로 사용하는 위치만 정렬하여, 원하는 위치의 값을 찾을 수 있는 함수이다.

  • 함수 기본 시그니처
template<class RandomIt>
void nth_element(RandomIt first, RandomIt nth, RandomIt last);
  • 파라메터
    • first: 정렬 시작하는 시작점
    • last: 정렬 끝나는 끝점
    • nth: 정렬을 하게되는 기준점
  • 결과
    • nth 로 지정한 위치에 있는 숫자까지 정렬을 해서, nth 번째 자리에 nth 번째로 작은 원소가 있고
    • nth자리 앞에는 정렬된 수들이, 이후로는 정렬되지 않은 수들이 존재
  • 예제
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main()
{
	vector<int> vec = { 5, 6, 4, 3, 2, 6, 7, 9, 3 };
	nth_element(vec.begin(), vec.begin() + vec.size() / 2, vec.end());
	cout << "중간값: " << vec[vec.size() / 2] << "\n"; // 5

	nth_element(vec.begin(), vec.begin() + 1, vec.end());
	cout << "두번째로 작은 원소: " << vec[1] << "\n"; // 3

	nth_element(vec.begin(), vec.begin() + 1, vec.end(), greater<int>());
	cout << "두번째로 큰 원소: " << vec[1] << "\n"; // 7
}

'알고리즘(코딩테스트)' 카테고리의 다른 글

알고리즘 관련 함수 1  (0) 2025.02.12
C++ 간단한 string 함수들  (0) 2025.02.11
map & set  (0) 2025.02.05
unordered_map 순환  (1) 2025.02.04
허프만 코딩 & 유클리드 호제법  (0) 2025.01.07
'알고리즘(코딩테스트)' 카테고리의 다른 글
  • 알고리즘 관련 함수 1
  • C++ 간단한 string 함수들
  • map & set
  • unordered_map 순환
gbleem
gbleem
gbleem 님의 블로그 입니다.
  • gbleem
    gbleem 님의 블로그
    gbleem
  • 전체
    오늘
    어제
    • 분류 전체보기 (184)
      • Unreal Engine (73)
      • C++ (19)
      • 알고리즘(코딩테스트) (27)
      • TIL (60)
      • CS (4)
      • 툴 (1)
  • 블로그 메뉴

    • 홈
    • 카테고리
  • 링크

    • 과제용 깃허브
    • 깃허브
    • velog
  • 공지사항

  • 인기 글

  • 태그

    addonscreendebugmessage
    템플릿
    cin함수
    싱글턴
    C++
    motion matching
    BFS
    DP
    applydamage
    매크로 지정자
    Vector
    additive animation
    map을 vector로 복사
    actor 클래스
    const
    상속
    character animation
    blend pose
    gamestate
    enhanced input system
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
gbleem
우선순위 큐, 순열, k값 찾기
상단으로

티스토리툴바