[알고리즘] C++로 이해하는 위상정렬

2025. 4. 16. 22:07·공부/알고리즘
목차
  1. ☑️ C++로 이해하는 위상정렬
  2. ☑️ 진입차수(In-degree)와 진출차수(Out-degree)
  3. ☑️ 위상정렬의 응용 분야
  4. ☑️ 위상정렬 구현하기
  5. 1️⃣ BFS 기반의 Kahn 알고리즘
  6. 2️⃣ DFS 기반의 Kahn 알고리즘

참고 : https://www.geeksforgeeks.org/topological-sorting/?ref=gcse_outind


☑️ C++로 이해하는 위상정렬

위상정렬(Topological Sort)은 방향 그래프에서 정점들을 선형으로 정렬하는 알고리즘이다. 풀어서 설명하면 그래프에서 순서가 있는 노드들을 순서대로 나열하는 행동을 한다. 우리가 출근을 하는 과정을 살펴보자.

1. 아침에 기상한다.
2. 씻는다.
3. 옷을 입는다.
4. 아침 식사를 한다.
5. 필요한 물건을 다 챙겼는지 확인한다.
6. 집 밖으로 나선다.

이런 과정들을 거쳐서 우리는 회사에 출근할 수 있다. 아침에 기상하는 것을 시작으로 집 밖으로 나서는 과정은 모두 순서대로 이루어진다. 아침에 기상하지 않고 식사를 하거나 집 밖으로 나설 수 없다.

 

위상정렬 알고리즘은 이처럼 명확한 순서가 있는 노드들을 정리해주는 개념을 의미한다. 순서가 있어야 하기 때문에 사이클이 없는 방향 그래프(DAG, Directed Acyclic Graph)에서만 사용 가능하다.

 

☑️ 진입차수(In-degree)와 진출차수(Out-degree)

위상정렬을 이해하기 위해서는 진입차수와 진출차수 개념에 대한 이해가 필요하다.

진입차수(In-dregree) : 다른 노드에서 특정 노드으로 들어오는 간선의 수
진출차수(Out-degree) : 특정 노드에서 다른 노드로 나가는 간선의 수

위상정렬을 구현하는 알고리즘들은 진입차수와 진출차수를 사용해서 동작하기 때문에 이에 대한 개념은 반드시 필요하다.

 

☑️ 위상정렬의 응용 분야

위상정렬의 핵심은 '선행 작업이 먼저 완료되어야 한다'는 점이기 때문에 반복되는 작업이 없고 선행 작업 관계를 나타내기 위해서 사용할 수 있다.

  1. 작업 스케줄링 : 작업 간에 선행 조건이 있다면 작업 순서를 결정하기 위해서 사용할 수 있다.
  2. 패키지 의존성 관리 : 한 패키지를 설치하기 위해 다른 패키지가 필요하다면 이를 확인하는 용도로 사용할 수 있다.
  3. 게임 퀘스트 진행 순서 : 게임 퀘스트 간의 의존성을 나타내고 진행 순서를 결정할 때 사용할 수 있다.
  4. 데이터 처리 파이프라인 : 데이터 처리를 위해서 다른 데이터가 필요한 지 식별할 때 사용할 수 있다.

 

☑️ 위상정렬 구현하기

1️⃣ BFS 기반의 Kahn 알고리즘

📌 의사코드

1. 모든 정점의 진입차수를 계산한다.
2. 진입차수가 0인 모든 정점을 Queue에 넣는다.
3. 큐가 비어질 때 까지 아래의 순서대로 작업을 진행한다.
	3-1. 큐에서 정점을 꺼내서 Result List에 추가한다.
    3-2. 해당 정점의 진입차수를 1 감소시킨다.
    3-3. 위 작업을 통해 진입차수가 0인 정점을 Queue에 추가한다.

 

📌 C++ 코드

// Including necessary header file
#include <bits/stdc++.h>
using namespace std;

// We mainly take input graph as a set of edges. This function is
// mainly a utility function to convert the edges to an adjacency
// list
vector<vector<int>> constructadj(int V,vector<vector<int>> &edges){
    
    // Graph represented as an adjacency list
    vector<vector<int> > adj(V);

    // Constructing adjacency list
    for (auto i : edges) {
        adj[i[0]].push_back(i[1]);
    }
    
    return adj;
}

// Function to return list containing vertices in
// Topological order.
vector<int> topologicalSort(int V, vector<vector<int> >& edges)
{
    vector<vector<int>> adj = constructadj(V,edges);
    
    // Vector to store indegree of each vertex
    vector<int> indegree(V);
    for (int i = 0; i < V; i++) {
        for (auto it : adj[i]) {
            indegree[it]++;
        }
    }
    // Queue to store vertices with indegree 0
    queue<int> q;
    for (int i = 0; i < V; i++) {
        if (indegree[i] == 0) {
            q.push(i);
        }
    }
    vector<int> result;
    while (!q.empty()) {
        int node = q.front();
        q.pop();
        result.push_back(node);
        
        // Decrease indegree of adjacent vertices as the
        // current node is in topological order
        for (auto it : adj[node]) {
            indegree[it]--;

            // If indegree becomes 0, push it to the queue
            if (indegree[it] == 0)
                q.push(it);
        }
    }

    // Check for cycle
    if (result.size() != V) {
        cout << "Graph contains cycle!" << endl;
        return {};
    }

    return result;
}

int main()
{

    // Number of nodes
    int V = 6;

    // Edges
    vector<vector<int> > edges
        = {{0, 1}, {1, 2}, {2, 3},
           {4, 5}, {5, 1}, {5, 2}};

    vector<int> result = topologicalSort(V, edges);

    // Displaying result
    for (auto i : result) {
        cout << i << " ";
    }

    return 0;
}

 

2️⃣ DFS 기반의 Kahn 알고리즘

📌 의사코드

1. 모든 정점에 대해서 DFS를 수행한다.
2. DFS에서 방문이 끝난 정점을 Stack에 추가한다.
3. Stack을 뒤집는다. (위상정렬 한 결과가 나온다.)

 

📌 C++ 코드

#include <bits/stdc++.h>
using namespace std;

// Function to perform DFS and topological sorting
void topologicalSortUtil(int v, vector<vector<int>> &adj, vector<bool> &visited, stack<int> &st)
{

    // Mark the current node as visited
    visited[v] = true;

    // Recur for all adjacent vertices
    for (int i : adj[v])
    {
        if (!visited[i])
            topologicalSortUtil(i, adj, visited, st);
    }

    // Push current vertex to stack which stores the result
    st.push(v);
}

vector<vector<int>> constructadj(int V, vector<vector<int>> &edges)
{

    vector<vector<int>> adj(V);
    for (auto it : edges)
    {
        adj[it[0]].push_back(it[1]);
    }

    return adj;
}

// Function to perform Topological Sort
vector<int> topologicalSort(int V, vector<vector<int>> &edges)
{

    // Stack to store the result
    stack<int> st;

    vector<bool> visited(V, false);
    vector<vector<int>> adj = constructadj(V, edges);
    // Call the recursive helper function to store
    // Topological Sort starting from all vertices one by
    // one
    for (int i = 0; i < V; i++)
    {
        if (!visited[i])
            topologicalSortUtil(i, adj, visited, st);
    }

    vector<int> ans;

    // Append contents of stack
    while (!st.empty())
    {
        ans.push_back(st.top());
        st.pop();
    }

    return ans;
}

int main()
{

    // Graph represented as an adjacency list
    int v = 6;
    vector<vector<int>> edges = {{2, 3}, {3, 1}, {4, 0}, {4, 1}, {5, 0}, {5, 2}};

    vector<int> ans = topologicalSort(v, edges);

    for (auto node : ans)
    {
        cout << node << " ";
    }
    cout << endl;

    return 0;
}

 

'공부 > 알고리즘' 카테고리의 다른 글

[알고리즘] C++로 이해하는 그리디  (0) 2025.04.23
[알고리즘] C++로 이해하는 브루트포스  (0) 2025.04.19
[알고리즘] C++로 이해하는 동적 프로그래밍  (0) 2025.04.07
[알고리즘] C++로 이해하는 검색 알고리즘(선형 검색, 이진 검색, 해시법 등)  (0) 2025.04.06
[알고리즘] C++로 이해하는 DFS와 BFS  (0) 2025.04.03
  1. ☑️ C++로 이해하는 위상정렬
  2. ☑️ 진입차수(In-degree)와 진출차수(Out-degree)
  3. ☑️ 위상정렬의 응용 분야
  4. ☑️ 위상정렬 구현하기
  5. 1️⃣ BFS 기반의 Kahn 알고리즘
  6. 2️⃣ DFS 기반의 Kahn 알고리즘
'공부/알고리즘' 카테고리의 다른 글
  • [알고리즘] C++로 이해하는 그리디
  • [알고리즘] C++로 이해하는 브루트포스
  • [알고리즘] C++로 이해하는 동적 프로그래밍
  • [알고리즘] C++로 이해하는 검색 알고리즘(선형 검색, 이진 검색, 해시법 등)
태역
태역
  • 태역
    RYULAB
    태역
  • 전체
    오늘
    어제
    • 분류 전체보기
      • 언어
        • C
        • C++
        • C#
      • 엔진, 프레임워크
        • Unity
        • Unreal
        • Electron
      • 공부
        • 디자인 패턴
        • 수학
        • CS
        • Git
        • 알고리즘
        • 자료구조
      • 코테
        • 프로그래머스
        • 백준
      • 독서
        • Effective C#
        • CLR via C#
        • 뇌를 자극하는 윈도우즈 시스템 프로그래밍
        • 오브젝트
        • CSAPP
        • OSTEP
      • 프로젝트
        • Unity
      • 개발 일지
        • 퓨처리티
        • 골든타임
      • 활동
        • 게임잼 후기
        • 게임제작동아리 브릿지
        • 크래프톤 정글
        • 기타
      • 기타
  • 블로그 메뉴

    • 링크

    • 공지사항

      • 2024 04 17
    • 인기 글

    • 태그

      티스토리챌린지
      인프런 #인프런강의후기 #게임개발 #게임개발강의 #인강후기 #강의후기 #게임개발자 #인프런강의
      오블완
    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.3
    태역
    [알고리즘] C++로 이해하는 위상정렬
    상단으로

    티스토리툴바

    단축키

    내 블로그

    내 블로그 - 관리자 홈 전환
    Q
    Q
    새 글 쓰기
    W
    W

    블로그 게시글

    글 수정 (권한 있는 경우)
    E
    E
    댓글 영역으로 이동
    C
    C

    모든 영역

    이 페이지의 URL 복사
    S
    S
    맨 위로 이동
    T
    T
    티스토리 홈 이동
    H
    H
    단축키 안내
    Shift + /
    ⇧ + /

    * 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.