-
Graph 활용-1Data Structures/Graph 2023. 9. 29. 17:13728x90
출처 엔지니어 대한민국
문제 1. Graph에서 두지점의 경로찾기
그래프에서 두 개의 노드가 서로 찾아갈 수 있는 경로가 있는지 확인하는 함수를 구현해보자 그래프에서 특정 노드 A와 B를 잇는 간선의 존재 여부를 판단하는 메서드이다.
DFS와 BFS 두 가지 방법 모두 경로를 찾을수 있지만 이런 문제의 경우 시작점을 기준으로 영역을 점차 넓히며 접근하는게 조금 더 빠른 방법일 수 있기 때문에 BFS, 넓이 우선 탐색을 사용해 접근한다.
구현
import java.util.LinkedList; import java.util.Iterator; import java.util.NoSuchElementException; class Queue<T>{ } class Graph{ class Node{ int data; // 인접한 노드들과의 관계 LinkedList<Node> adjacent; // 방문했는지 마킹 boolean marked; //Node 생성자 Node (int data){ this.data = data; this.marked = false; adjacent = new LinkedList<Node>(); } } Node[] nodes; // node들을 저장할 배열 Graph(int size){ nodes = new Node[size]; for(int i=0; i<size; i++){ nodes[i] = new Node(i); } } //두 노드의 관계를 저장 void addEdge(int i1, int i2){ Node n1 = nodes[i1]; Node n2 = nodes[i2]; //상대방이 있는지 확인하고 없으면 추가 if(!n1.adjacent.contains(n2)){ n1.adjacent.add(n2); } if(!n2.adjacent.contains(n1)){ n2.adjacent.add(n1); } } // 검색전 모든 Making Flag를 false로 초기화하는 메서드 void initMarks(){ for (Node n : nodes) { n.marked = false; } } // 배열 인덱스로 호출하면 노드로 변환해서 호출하는 함수 boolean search(int i1, int i2) { return search(nodes[i1], nodes[i2]); } // start와 end Node를 받는 두 개의 노드 경로를 확인하는 함수 boolean search(Node start, Node end){ initMarks(); LinkedList<Node> q = new LinkedList<Node>(); q.add(start); while(!q.isEmpty()){ Node root = q.removeFirst(); if(root == end){ return true; } for(Node n : root.adjacent) { if(n.marked == false){ n.marked = true; q.add(n); } } } return false; } public class Test { public static void main(String[] args){ Graph g = new Graph(9); g.addEdge(0,1); g.addEdge(1,2); g.addEdge(1,3); g.addEdge(2,4); g.addEdge(3,4); g.addEdge(3,5); g.addEdge(5,6); g.addEdge(5,7); g.addEdge(6,8); /* 0 / 1 ㅡㅡ3 7 | / | \ / | / | 5 2ㅡㅡ4 \ 6ㅡ8 */ System.out.println(g.search(1,8)); } }search(Node start, Node end)함수는 먼저start노드를 큐에 담고 인접한 노드를 하나씩 추가하고end노드와 비교하며 일치 여부를 판단하는 메서드이다.
모든 노드를 탐색하며 진행하는데 이 때 탐색이 끝났음에도return되지 않는다면false를 반환하며 종료된다.
문제 2. 배열을 이진 검색 트리로 만들기
정렬이 되어 있고, 고유한 정수로만 이루어진 배열이 있다. 이 배열로 이진 검색 트리를 구현하시오.
배열이 정렬되어있는 상태이고, 배열의 데이터가 고유하기 때문에 배열의 가운데에 있는 숫자를 보고 검색하고자 하는 숫자보다 크면 오른쪽으로, 작으면 왼쪽으로 찾아 들어가는 방법을 통해 접근할 수 있다.
만약 배열이 짝수로 존재한다면, 딱 떨어지는 중간 값이 없기 때문에 앞에 있는 숫자를 중간 값으로 취급하는 조건을 달아준다.
int[] arr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};이진 검색 트리(Binary Search Tree)는 모든 노드가 최대 두 개의 자식 노드를 가지면서, 왼쪽 자식 노드는 현재 노드보다 작은 값을, 오른쪽 자식 노드는 현재 노드보다 큰 값을 가지는 트리이다.
이진 검색 트리에서 특정 값을 검색하는 경우, 루트 노드부터 시작하여 찾고자 하는 값이 현재 노드보다 작으면 왼쪽 자식 노드를 탐색하고, 크면 오른쪽 자식 노드를 탐색하며 이 과정을 반복하여 값을 찾는다.
따라서, 위 와 같은
arr배열이 존재하고 이를 이진 검색 트리로 만든다면 다음과 같은 과정을 갖는다.- 배열 arr의 중앙에 위치한 값을 기준으로 루트 노드를 생성한다.
- 루트 노드의 왼쪽 서브트리는 arr의 왼쪽 절반을 이진 검색 트리로 변환한다.
- 루트 노드의 오른쪽 서브트리는 arr의 오른쪽 절반을 이진 검색 트리로 변환한다.
- 이 과정을 각 서브트리에 대해 재귀적으로 반복
(배열의 길이가 짝수일경우 앞에 존재하는 데이터를 기준으로 한다.)

class Tree{ class Node { int data; // 왼쪽 오른쪽 Node를 저장한 변수 선언 Node left; Node right; // 생성자에서 데이터를 받아 노드에 저장한다. Node (int data){ this.data = data; } } // Tree 멤버 변수(Tree가 시작되는 root 변수 선언) Node root; /* 배열 정보를 받아 트리를 만드는 일을 시작해주는 함수 선언 * 이 함수는 재귀 호출을 반복적으로 실행하기 전 * 재귀 호출에 필요한 정보를 처음으로 던져주는 역할을하고 * 재귀 호출이 끝나면 가장 꼭대기에 있는 루트 노드의 주소를 받아서 멤버 변수에 저장한다. */ public void makeTree(int[] a){ root = makeTreeR(a, 0, a.length -1); } // 재귀함수 선언, 인자 : 배열 정보, 시작 인덱스, 끝 인덱스 public Node makeTreeR(int[] a, int start, int end) { /* 시작 인덱스가 끝 인덱스보다 커질 경우 재귀 종료 (끝나는 지점을 명확히 해주는게 재귀 호출의 가장 중요한 부분이다.) */ if(start > end) return null; // 받은 시작 지점과 끝 지점으로 중간 지점 계산 int mid = (start + end) / 2; // 중간 지점으로 받은 값으로 노드 생성 Node node = new Node(a[mid]); /* 재귀 호출 * left : 시작 값(0)부터 중간 값 - 1 까지 탐색 * right : 중간 값 + 1 부터 마지막 값 까지 탐색 */ node.left = makeTreeR(a, start, mid-1); node.right = makeTreeR(a, mid+1, end); return node; } /* 트리가 잘 만들어졌는지 확인하는 이진 검색 함수 생성 * 검색 시작 노드와 찾을 값을 함수 인자로 받는다. * 만약 찾는 값이 Node.data보다 작을 경우 조건문에 의해 왼쪽 트리를 탐색하고 * 더 크다면 오른쪽 트리를 탐색하는 과정을 반복한다. */ public void searchBTree(Node n, int find) { if(find < n.data) { System.out.println("Data is smaller than " + n.data); searchBTree(n.left, find); }else if(find > n.data){ System.out.println("Data is bigger than " + n.data); searchBTree(n.right, find); }else{ System.out.println("Data found!"); } } } public class Test{ public static void main (String[] args){ int[] a = new int[10]; for(int i=0; i<a.length; i++){ a[i] = i; } Tree t = new Tree(); t.makeTree(a); t.searchBTree(t.root, 2); } } 결과 : Data is smaller than 4 Data is bigger than 1 Data found!

'Data Structures > Graph' 카테고리의 다른 글
최대 부분 증가 수열 - LIS (0) 2023.09.29 Tree (0) 2023.09.29 Graph에 대해 (0) 2023.09.29 Graph 검색 구현 (0) 2023.09.28