이 영역을 누르면 첫 페이지로 이동
쿄코코 블로그의 첫 페이지로 이동

쿄코코

페이지 맨 위로 올라가기

쿄코코

얼레벌레 생활🤯

CHAPTER 6 -번외 정렬 - 위상 정렬(Topology Sort) - Python(파이썬)

  • 2022.06.08 22:34
  • Study Platform📚/(알고리즘)- [이코테] 이것이 코딩테스트다 정리
    반응형

    참고 자료 : https://m.blog.naver.com/ndb796/221236874984

     

    위상 정렬

    : 순서가 정해져 있는 작업을 수행해야 할 때 그 순서를 정해주기 위해서 사용하는 알고리즘

    ex ]

    0번 -> 1번 ->3번 -> 5번 순으로 이어진 후에  4번이 나오기 전에 2번 만족

    이런식으로 그래프의 흐름이 있고 다양한 조건들이 얽혀있을 때 일렬로 그래프의 순서를 나열할 수 있어야함

    ex]  0 -> 1 -> 3 -> 5 -> 2 -> 4 -> 6 

     

    1. 위상 정렬의 특징

    - 여러개의 답이 존재 할 수 있다 

    - DAG(Directed Acyclic Graph)에만 존재(방향그래프이지만 사이클이 존재하지 않는 그래프)

      -> 사이클이 발생하는 경우 위상 정렬을 수행할 수 없다. Why? 위상 정렬은 시작점이 존재해야만 사용할 수 있는 알고리즘

    - 위상 정렬 문제 : ① 현재 그래프는 위상 정렬이 가능한지 ② 위상 정렬이 가능하다면 그 결과는 무엇인지

    2. 큐를 이용한 위상 정렬 수행

       ① 진입차수가 0인 정점을 큐에 삽입 ( 진입차수 : 노드로 들어오는 다른 노드의 개수 ) 

       ② 큐에서 원소를 꺼내 연결된 모든 간선 제거

       ③ 간선 제거 이후에 진입차수가 0이 된 정점을 큐에 삽입

       ④ 큐가 빌 때까지 2번 - 3번 과정을 반복. (모든 원소를 방문하기 전에 큐가 제거될 경우 사이클이 존재)

       ⑤ 큐에서 꺼낸 순서가 위상 정렬의 결과

    정점 0 1 2 3 4 5 6
    진입차수 0 1 1 1 2 1 1

    이므로 진입차수가 0인 0부터 큐에 삽입

    1. 진입차수가 0인 0부터 큐에 삽입

    2. 큐에서 0을 꺼내 연결된 간선 제거 ( 꺼낸 수 : 0 )

    정점 0 1 2 3 4 5 6
    진입차수 0 1-1 = 0  1-1 = 0 1 2 1 1

    3. 진입차수 표(2번,3번) 변경

    4.진입차수가 0인 1,2 큐에 삽입

    5. 큐에서 꺼낸 1을 꺼낸 후 간선을 제거(꺼낸 수: 0 -> 1 )

     

    정점 0 1 2 3 4 5 6
    진입차수 0 0 0 1-1=0 2 1 1

    6. 진입차수표(3번) 변경

    7. 진입차수가 0인 3이 큐에 삽입

    8. 큐에서 2를 꺼낸 후에 간선을 제거(꺼낸 수 : 0 -> 1 -> 2 )

    정점 0 1 2 3 4 5 6
    진입차수 0 0 0 0 2-1 = 1 1 1

    9. 진입차수표 (4번) 변경

     

    10. 큐에는 이제 3만이 남아 있음

     

    11. 큐에서 3을 꺼내서 간선 제거(꺼낸 수: 0 -> 1- > 2 -> 3)

    정점 0 1 2 3 4 5 6
    진입차수 0 0 0 0 1 1-1=0 1

    12. 진입차수표 (5번) 변경

    13. 진입차수가 0인 5를 큐에 삽입

    14. 큐에서 5를 꺼내서 간선 제거(꺼낸 수 : 0 -> 1-> 2-> 3 -> 5)

     

    정점 0 1 2 3 4 5 6
    진입차수 0 0 0 0 1-1=0 0 1

    15. 진입차수표 (4번) 변경

    16.진입차수표가 0인 4를 큐에 삽입

    17. 큐에서 4를 꺼내서 간선 제거( 꺼낸수: 0 -> 1-> 2-> 3-> 5-> 4 )

     

    정점 0 1 2 3 4 5 6
    진입차수 0 0 0 0 0 0 1-1=0

    19. 진입차수표 (6번) 변경

    20. 진입차수표가 0인 6를 큐에 삽입

    21. 큐에서 6을 꺼내서 간선을 제거해야하지만 없으므로 끝 (꺼낸 수 : 0 -> 1-> 2-> 3-> 5-> 4 ->6)


    참고 자료 : https://freedeveloper.tistory.com/390

    입력 예시 

    7 7 ( 노드의 수 | 간선의 개수 )
    1 2 ( 1-> 2 )
    1 3 ( 1 ->3 )
    2 4 ( 2 ->4 )
    3 5 ( 3 ->5 )
    4 6 ( 4 ->6 )
    5 7 ( 5 ->7 )
    6 5 ( 6 ->5 )
    출력 예시

    1 2 3 4 6 5 7 







    💻 Python(파이썬)

    import sys
    from collections import deque
    
    #노드의 개수, 간선의 개수 입력 받기
    v,e = map(int,sys.stdin.readline().split())
    #진입차수표( 노드의 수 +1 )
    table = [0]*(v+1)
    #노드 연결 정보 리스트( 노드의 수 +1 )
    graph = [[] for _ in range(v+1)]
    
    #간선 개수만큼 간선 정보를 입력 받기
    for _ in range(e):
        a,b = map(int, sys.stdin.readline().split())
        graph[a].append(b)#A -> B
        table[b]+=1 #진입차수표도 하나씩 증가
    
    #위상 정렬 함수
    def toplogy_sort():
        #큐 구현
        q = deque()
    
        #처음 시작 시 진입차수가 0인 노드를 큐에 삽입
        for i in range(1,v+1):
            if table[i]==0:
                q.append(i)
    
        #큐가 빌때까지 수행
        while q:
            #제일 왼쪽에 있는 큐를 pop
            now = q.popleft()
            #now와 연결된 그래프
            for i in graph[now]:
                table[i]-=1#1씩 제거
                #진입차수가 0인 값은 큐에 다시 삽입
                if table[i]==0:
                    q.append(i)
            #now 값 print
            print(now,end=" ")
    
    toplogy_sort()

    💻 Java(자바)

    import java.util.*;
    
    public class Main {
        // 노드의 개수(V)와 간선의 개수(E)
        public static int v, e;
        // 모든 노드에 대한 진입차수는 0으로 초기화
        public static int[] table;
        // 각 노드에 연결된 간선 정보를 담기 위한 연결 리스트 초기화
        public static ArrayList<ArrayList<Integer>> graph = new ArrayList<ArrayList<Integer>>();
    
        // 위상 정렬 함수
        public static void topologySort() {
            Queue<Integer> q = new LinkedList<>(); // 큐 라이브러리 사용
    
            // 처음 시작할 때는 진입차수가 0인 노드를 큐에 삽입
            for (int i = 1; i <= v; i++) {
                if (table[i] == 0) {
                    q.offer(i);
                }
            }
    
            // 큐가 빌 때까지 반복
            while (!q.isEmpty()) {
                // 큐에서 원소 꺼내기
                int now = q.poll();
                // 해당 원소와 연결된 노드들
                for (int i = 0; i < graph.get(now).size(); i++) {
                    //진입차수 1씩 제거
                    table[graph.get(now).get(i)] -= 1;
                    // 진입차수가 0인 값은 큐에 삽입
                    if (table[graph.get(now).get(i)] == 0) {
                        q.offer(graph.get(now).get(i));
                    }
                }
                System.out.print(now+" ");
            }
        }
    
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
    
            v = sc.nextInt();
            e = sc.nextInt();
    
            // 그래프 초기화
            for (int i = 0; i <= v; i++) {
                graph.add(new ArrayList<Integer>());
            }
    
            table = new int[v+1];
    
            // 방향 그래프의 모든 간선 정보를 입력 받기
            for (int i = 0; i < e; i++) {
                int a = sc.nextInt();
                int b = sc.nextInt();
                graph.get(a).add(b); // 정점 A에서 B로 이동 가능
                // 진입 차수를 1 증가
                table[b] += 1;
            }
    
            topologySort();
        }
    }

     

    반응형

    'Study Platform📚 > (알고리즘)- [이코테] 이것이 코딩테스트다 정리' 카테고리의 다른 글

    [이코테]CHAPTER 09 최단 경로 알고리즘 - 플로이드워셜 알고리즘 - Python(파이썬),Java(자바)  (0) 2022.06.11
    [이코테] CHAPTER 09 최단 경로 알고리즘 - 다익스트라 최단 경로 알고리즘  (0) 2022.05.23
    [이코테] CHAPTER 05 DFS/BFS - BFS(deque 메서드) - Python(파이썬),Java(자바)  (0) 2022.05.18
    [이코테]CHAPTER 05 DFS/BFS - 스택, 큐, 재귀함수, DFS  (0) 2022.05.17
    [이코테] CHAPTER 06 정렬 - 계수 정렬  (0) 2022.05.16

    댓글

    이 글 공유하기

    • 구독하기

      구독하기

    • 카카오톡

      카카오톡

    • 라인

      라인

    • 트위터

      트위터

    • Facebook

      Facebook

    • 카카오스토리

      카카오스토리

    • 밴드

      밴드

    • 네이버 블로그

      네이버 블로그

    • Pocket

      Pocket

    • Evernote

      Evernote

    다른 글

    • [이코테]CHAPTER 09 최단 경로 알고리즘 - 플로이드워셜 알고리즘 - Python(파이썬),Java(자바)

      [이코테]CHAPTER 09 최단 경로 알고리즘 - 플로이드워셜 알고리즘 - Python(파이썬),Java(자바)

      2022.06.11
    • [이코테] CHAPTER 09 최단 경로 알고리즘 - 다익스트라 최단 경로 알고리즘

      [이코테] CHAPTER 09 최단 경로 알고리즘 - 다익스트라 최단 경로 알고리즘

      2022.05.23
    • [이코테] CHAPTER 05 DFS/BFS - BFS(deque 메서드) - Python(파이썬),Java(자바)

      [이코테] CHAPTER 05 DFS/BFS - BFS(deque 메서드) - Python(파이썬),Java(자바)

      2022.05.18
    • [이코테]CHAPTER 05 DFS/BFS - 스택, 큐, 재귀함수, DFS

      [이코테]CHAPTER 05 DFS/BFS - 스택, 큐, 재귀함수, DFS

      2022.05.17
    다른 글 더 둘러보기

    정보

    쿄코코 블로그의 첫 페이지로 이동

    쿄코코

    • 쿄코코의 첫 페이지로 이동

    검색

    메뉴

    • 홈

    카테고리

    • 분류 전체보기 (169)
      • Python (24)
        • 😈 99클럽 코테 스터디 4기 TIL (23)
        • 궁금한거 정리 (1)
      • SQL (16)
        • HackerRank (15)
      • [백준] Python,Java로 풀기📖 (71)
        • 정렬(Sorting) (6)
        • 그리디 (5)
        • 문자열 (7)
        • 수학 (3)
        • DFS&BFS (10)
        • 구현 (4)
        • 다이나믹 (17)
        • 이분탐색 (1)
        • 자료구조 (10)
        • 최단거리 (5)
        • 인덱스트리 (0)
      • [프로그래머스]Python,Java로 풀기 (6)
        • Level 1 (4)
        • Level 2 (2)
      • Study Platform📚 (25)
        • 김영한👨🏻‍🏫의 스프링 부트와 JPA 실무 완전 .. (5)
        • (알고리즘)- [이코테] 이것이 코딩테스트다 정리 (10)
        • 그림으로 배우는 Http&Network Basic (10)
      • 까먹을까봐 적는 것들 (5)
      • 테스트 보고 난 후..🤔 (0)
      • kt 에이블스쿨 (18)

    최근 글

    인기 글

    댓글

    공지사항

    아카이브

    태그

    • 코딩테스트준비
    • 티스토리챌린지
    • TiL
    • 오블완
    • 99클럽
    • 항해99
    • 프로그래머스
    • 백준

    나의 외부 링크

    정보

    쿄코코의 쿄코코

    쿄코코

    쿄코코

    블로그 구독하기

    • 구독하기
    • RSS 피드

    방문자

    • 전체 방문자
    • 오늘
    • 어제

    티스토리

    • 티스토리 홈
    • 이 블로그 관리하기
    • 글쓰기
    Powered by Tistory / AXZ. © 쿄코코. Designed by Fraccino.

    티스토리툴바