깊이 우선 탐색


그래프 G와 시작점 S가 주어졌을 때 S에서 도달 가능한 모든 간선을 찾는 과정


동작원리


탐색 시작 위치의 vertex의 인접한 간선을 통해 다른 vertex로 이동한 후 인접한 간선이 없을 때까지

반복하여 내려간 후 다시 위로 올라가는 과정을 반복해서 탐색하는 것


아래로 깊이 내려가며 탐색하기에 깊이 우선 탐색이라고 불림



코드)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
public class DfsExample {
    
    /*
     * 인접행렬로 구현된 그래프의 깊이 우선 탐색
     */
    
    static int nV; //총 vertex 수
    static int nE; //총 edge 수
    static int[][] adMatrix; //인접행렬
    static boolean[] visit; //방문여부 체크
    
 
    //재귀호출을 이용한 dfs구현
    
    public static void dfs(int i) {
        visit[i] = true;
        for(int j=0;j<nV;j++) {
            if(adMatrix[j][i]==1 && !visit[j]) {
                System.out.println(i + "에서 " + j + "로 이동");
                dfs(j);
            }
        }    
    }
 
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        nV = scan.nextInt();
        nE = scan.nextInt();
        
        adMatrix = new int[nV][nV];
        visit = new boolean[nV];
        
        for(int i=0;i<nE;i++) {
            int vertex1, vertex2;
            vertex1 = scan.nextInt();
            vertex2 = scan.nextInt();
            adMatrix[vertex2][vertex1] = 1;
        }
        
    
        for(int i=0;i<nV;i++) {
            System.out.print(i + "-" );
            for(int j=0;j<nV;j++) {
                System.out.print(adMatrix[j][i]+ " ");
            }
            System.out.println();
        }
 
        
        dfs(0);
    }
}
cs


HashTable이란?


HashMap과 동일한 내부구조를 가지고 있는 Map 구현 클래스



HashMap vs HashTable


 

HashMap 

HashTable 

 동일한 키 기준

 hashCode( )와 equals( ) 

 hashCode( )와 equals( ) 

 동기화된 메소드

 없음

 동기화된 메소드로 구성


HashMap과 HashTable은 동일한 내부 구조를 가지고 있지만

HashTable의 경우는 동기화된 메소드로 구성되어 있기 때문에 멀티 스레드가

동시에 이 메소드를 실행할 수 없고, 하나의 스레드가 실행을 완료해야만 다른 스레드가 실행가능하다.

이는 멀티 스레드 환경에서 안전하게 객체를 추가, 삭제할 수 있다는 것을 의미한다.



Properties란?


Hashtable의 하위 클래스로 Hashtable의 모든 특징을 가지고 있다.

차이점은 Properties는 키와 값을 String으로 제한하였다는 것이다.


주로 애플리케이션의 옵션 정보, 데이터베이스 연결정보 그리고 국제화 정보가 저장된

프로퍼티(~.properties) 파일을 읽을 때 주로 사용




'자료구조' 카테고리의 다른 글

[그래프] 깊이 우선 탐색(DFS)  (0) 2017.03.10
[Map] HashMap  (0) 2017.03.10
[Set]HashSet의 특징  (1) 2017.03.09
[그래프]넓이 우선 탐색(BFS)  (0) 2017.03.07
[그래프] 인접리스트와 인접행렬을 이용한 구현  (0) 2017.02.26

HashMap이란?


Map 인터페이스를 구현한 대표적인 Map 컬렉션



Map이란?


Key와 value으로 구성된 Entry 객체를 저장하는 구조를 가짐(key, value 모두 객체)

키는 중복 저장될 수 없지만 값은 중복 저장 가능

HashMap, HashTable, LinkedHashMap, Properties, TreeMap 등이 있다.



HashMap 특징


HashSet과 마찬가지로 hashcode()와 equals()로 동일한 키 여부를 결정한다.





기본 사용법 코드


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package map.hashmap;
 
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
 
public class HashMapExample1 {
    public static void main(String[] args) {
        
        //Map 생성
        Map<String, Integer> map = new HashMap();
        
        
        //객체 저장
        map.put("원빈"50);
        map.put("장동건"70);
        map.put("하하"40);
        
        System.out.println("총 Entity 수 : " + map.size());
        
        //객체 찾기
        System.out.println("하하 : " + map.get("하하"));
        System.out.println();
        
        //하나씩 처리 - ketset()이용
        Set<String> keySet = map.keySet();
        Iterator<String> keyIterator = keySet.iterator();
        while(keyIterator.hasNext()) {
            String key = keyIterator.next();
            Integer value = map.get(key);
            System.out.println(key + " : " + value );
        }
        System.out.println();
        
        //객체 삭제
        map.remove("장동건");
        System.out.println("총 Entry 수 : " + map.size());
        
        //하나씩 처리 - entryset() 이용
        Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
        Iterator<Map.Entry<String, Integer>> entryIterator = entrySet.iterator();
        
        while(entryIterator.hasNext()) {
            Map.Entry<String, Integer> entry = entryIterator.next();
            String key = entry.getKey();
            Integer value = entry.getValue();
            System.out.println(key + " : " + value );
        }
        System.out.println();
        
        //객체 전체 삭제
        map.clear();
        System.out.println("총 Entry 수 : " + map.size());
    }
}
 
cs



hashcode( )와 eqauls( ) 재정의를 통한 동일한 키 삽입 예제 코드


키로 사용할 객체(hashcode() eqauls() 재정의)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Member {
    private String name;
    private int age;
    
    /*
        get, set 메소드 생략
    */
 
    @Override
    public int hashCode() {
        return name.hashCode() + age; //이름과 나이가 같으면 동일한 해쉬코드
    }
 
    @Override
    public boolean equals(Object obj) {
        if(obj instanceof Member) {
            Member member = (Member) obj;
            return member.getName().equals(name) && (member.getAge() == age); //이름과 나이가 같으면 true
        } else {
            return false;
        }
    }
}
cs



이름과 나이가 같은 경우 동일한 키로 판단


1
2
3
4
5
6
7
8
9
10
11
12
13
import java.util.HashMap;
import java.util.Map;
import set.hashset.Member;
 
public class HashMapExample2 {
    public static void main(String[] args) {
        Map<Member, String> map = new HashMap();
        map.put(new Member("명수"30), "골드"); //이름과 나이가 같은 Member 키로 저장
        map.put(new Member("명수"30), "골드");
        
        System.out.println("총 Entry 수 : " + map.size()); //1개만 저장된다.
    }
}
cs


HashSet


Set 인터페이스의 구현 클래스

HashSet은 객체들을 순서없이 저장하고 동일한 객체를 중복 저장하지 않는다.



HashSet의 가장 큰 특징


HashSet이 판단하는 동일한 객체란 꼭 같은 인스턴스를 뜻하지 않는다.

HashSet은 객체를 저장하기전 먼저 객체의 hashCode() 메서드를 호출하여 해시코드를 얻고

이미 저장되어 있는 객체들의 해시코드와 비교한다. 만약 동일한 해쉬코드가 있다면 다시 equals() 메소드로

두 객체를 비교해 참이면 동일한 객체로 저장하고 중복 저장하지 않는다.




예시 코드


Member 클래스


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class Member {
    private String name;
    private int age;
    
    public Member(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public int getAge() {
        return age;
    }
 
    public void setAge(int age) {
        this.age = age;
    }
 
    //hashCode()와 eqauls() 재정의    
    
    @Override
    public int hashCode() {  
        return name.hashCode() + age;  //name과 age가 같으면 동일한 hashcode 리턴
    }
 
    @Override
    public boolean equals(Object obj) {
        if(obj instanceof Member) {
            Member member = (Member) obj;
            return member.getName().equals(name) && (member.getAge() == age); //name과 age가 같으면 true
        } else {
            return false;
        }
    }
}
cs



HashSet을 이용한 동일한 데이터를 가진 객체 저장


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.util.HashSet;
import java.util.Set;
 
public class HashSetExample {
    public static void main(String[] args) {
        Set<Member> set = new HashSet();
        
        set.add(new Member("홍길동"30));
        set.add(new Member("홍길동"30));
        //인스턴스는 다르지만 내부 데이터는 동일한 Memeber 인스턴스 2개
        //2개를 모두다 넣지만 하나만 저장된다. (hashcode값이 같고, eqauls() true가 리턴되기에)
        
        System.out.println("총 객체 수 : " + set.size()); // 총 객체 수 : 1    출력
    }
}
cs


넓이 우선 탐색이란?


그래프 G와 시작점 S가 주어졌을 때 S에서 도달 가능한 모든 간선을 찾는 과정



동작 원리


먼저 거리가 1인 정점을 모든 찾은 후 2인 정점을 찾는 식으로 거리를 늘려가며 탐색

탐색을 하면서 시작점으로부터의 거리와 바로 직전 정점을 계산



전정점 그래프(넓이 우선 탐색 트리)


시작점으로부터 각 정점에 들려야 는 정점으로 만든 하위 그래프로 트리 형태

모든 정점이 연결되어 있고 nE(간선의 수) = nV(vertex의 수) - 1



예시)


주어진 그래프



1을 시작점으로한 넓이 우선 탐색 트리






코드 구현


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
public class BfsExample {
    
    /*
     * 인접리스트로 구현된 그래프의 넓이우선 탐색
     */
    
    static int nV; //총 vertex 개수
    static int nE; //총 edge 개수
    static ArrayList<ArrayList<Integer>> adList = new <ArrayList<Integer>> ArrayList();
    //그래프 구현을 위한 인접리스트
 
    static int[] visit; //방문여부와 완료여부를 표시
    // 0 - 방문 안함,   1 - 방문했지만 아직 탐색 안됨 , 2 - 탐색완료
    static int[][] vertexInfo; //vertex의 위치 정보를 담는 2차원 배열
                               //i번쨰 vertex의 정보 - vertexInfo[i][0] = distance
                               //                   vertexInfo[i][1] = preVertex(상위 vertex)
    
    public static void bfs(int i) {
        visit = new int[nV];
        vertexInfo = new int[nV][2];
        Queue<Integer> q = new LinkedList();
 
        q.offer(i); //탐색 시작 위치의 vertex를 큐에 넣는다.
        visit[i] = 1;
        vertexInfo[0][i] = 0;
        while(!q.isEmpty()) { //Queue의 모든 작업이 없을때 까지
            int temp = q.poll(); //Queue에서 작업(탐색을 위한 데이터)을 가져온다.
            int tempDistance = vertexInfo[temp][0]; 
            for(int j:adList.get(temp)) { //인접리스트에서 temp번째 vertex가 가지고 있는 간선 수만큼 반복
                if(visit[j]==0) { //vertex에 한번도 방문 안했을떄
                    visit[j] = 1//방문 체크를 한다.
                    vertexInfo[j][0= tempDistance + 1;
                    vertexInfo[j][1= temp; //상위 vertex 정보를 넣는다.
                    System.out.println(temp + "에서 " + j + "로 이동");
                    q.offer(j); //새로 찾은 vertex를 탐색하기 위해 Queue에 삽입
                }
            }
            visit[temp] = 2//탐색 완료된 vertex 플래그
        }    
    }
 
    public static void main(String[] args) {
        
        //인접리스트를 이용한 그래프 구현
        Scanner scan = new Scanner(System.in);
 
        nV = scan.nextInt();
        nE = scan.nextInt();
 
 
        for(int i=0;i<nV;i++) adList.add(new<Integer> ArrayList());
        //adList에 담을 리스트(각 vertex마다 인접한 vertext를 표현한 리스트)
 
        for(int i=0;i<nE;i++) {
            int vertex1, vertex2;
            vertex1 = scan.nextInt();
            vertex2 = scan.nextInt();
 
            adList.get(vertex1).add(vertex2);
            adList.get(vertex2).add(vertex1);
        }
        
        //넓이우선 탐색시작
        bfs(1);
        
        int i = 0;
        for(int[] vertex:vertexInfo) {
            System.out.print(i++ + "-");
            System.out.print("distance" + vertex[0+ ", ");
            System.out.println("preVertex" + vertex[1]);
        }
    }
}
cs


'자료구조' 카테고리의 다른 글

[Map] HashMap  (0) 2017.03.10
[Set]HashSet의 특징  (1) 2017.03.09
[그래프] 인접리스트와 인접행렬을 이용한 구현  (0) 2017.02.26
ArrayList와 LinkedList  (0) 2017.01.02
Array 배열 for Java  (0) 2016.12.23

인접리스트를 이용해 구현한 방향성 그래프



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Scanner;
 
public class DirectedAdList {
    
    /*
     * 방향성이 있는 그래프를 인접 리스트로 구현
     */
    
    static int nV; //총 vertex 개수
    static int nE; //총 edge 개수
    
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        
        nV = scan.nextInt();
        nE = scan.nextInt();
        ArrayList<ArrayList<Integer>> adList = new <ArrayList<Integer>> ArrayList();
        
        for(int i=0;i<nV;i++) adList.add(new<Integer> ArrayList());
        //adList에 담을 리스트(각 vertex마다 인접한 vertext를 표현한 리스트)
        
        for(int i=0;i<nE;i++) {
            int vertex1, vertex2;
            vertex1 = scan.nextInt();
            vertex2 = scan.nextInt();
            
            adList.get(vertex1).add(vertex2);
        }
        
        
        //인접리스트 출력
        for(int i=0;i<nV;i++) {
            Iterator<Integer> iter = adList.get(i).iterator();
            System.out.print(i);
            if(iter.hasNext()) System.out.print("-");
            while(iter.hasNext()) System.out.print(iter.next() + " ");
            System.out.println("");
        }
    }
}
cs



인접리스트를 이용해 구현한 비방향성 그래프


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class UndirectedAdList {
    /*
     * 비방향 그래프를 인접리스트를 통해 구현
     * 비항향 그래프를 구현하기 위해 방향성 그래프로 변환하여 구현
     * 그렇기에 edge정보를 담기위한 공간이 방향성 그래프에비해 많이듬(2배)
     * 정점과 간선의 개수가 증가하면 증가할수록 공간이 많이 필요하다.
     * 이를 해결하기 위해 인접행렬이 나옴
     */
    
    
    static int nV; //총 vertex 개수
    static int nE; //총 edge 개수
    
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        
        nV = scan.nextInt();
        nE = scan.nextInt();
        ArrayList<ArrayList<Integer>> adList = new <ArrayList<Integer>> ArrayList();
        
        for(int i=0;i<nV;i++) adList.add(new<Integer> ArrayList());
        //adList에 담을 리스트(각 vertex마다 인접한 vertext를 표현한 리스트)
        
        for(int i=0;i<nE;i++) {
            int vertex1, vertex2;
            vertex1 = scan.nextInt();
            vertex2 = scan.nextInt();
            
            adList.get(vertex1).add(vertex2);//비방향 그래프이기 때문에 번갈아서 구현
            adList.get(vertex2).add(vertex1);//비방향 그래프를 방향성그래프로 변환하여 구현하기에
                                             //번갈아서 edge를 구현해야한다.
        }
        
        
        //인접리스트 출력
        for(int i=0;i<nV;i++) {
            Iterator<Integer> iter = adList.get(i).iterator();
            System.out.print(i);
            if(iter.hasNext()) System.out.print("-");
            while(iter.hasNext()) System.out.print(iter.next() + " ");
            System.out.println("");
        }
    }
}
cs



인접행렬를 이용해 구현한 방향성 그래프


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import java.util.Scanner;
 
public class DirectedAdMatrix {
    
    /*
     * 인접행렬을 이용해 구현한 방향성 그래프
     */
    
    static int nV; //총 vertex 수
    static int nE; //총 edge 수
    static int[][] adMatrix;
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        nV = scan.nextInt();
        nE = scan.nextInt();
        
        adMatrix = new int[nV][nV];
        
        for(int i=0;i<nE;i++) {
            int vertex1, vertex2;
            vertex1 = scan.nextInt();
            vertex2 = scan.nextInt();
            adMatrix[vertex2][vertex1] = 1;
        }
        
    
        for(int i=0;i<nV;i++) {
            System.out.print(i + "-" );
            for(int j=0;j<nV;j++) {
                System.out.print(adMatrix[j][i]+ " ");
            }
            System.out.println();
        }
    }    
}
cs



인접행렬를 이용해 구현한 방향성 그래프


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
public class UndirectedADMatrix {
    
    /*
     * 인접행렬을 이용해 구현한 비방향성 그래프
     */
    
    static int nV; //총 vertex 수
    static int nE; //총 edge 수
    static int[][] adMatrix;
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        nV = scan.nextInt();
        nE = scan.nextInt();
        
        adMatrix = new int[nV][nV];
        
        for(int i=0;i<nE;i++) {
            int vertex1, vertex2;
            vertex1 = scan.nextInt();
            vertex2 = scan.nextInt();
            adMatrix[vertex2][vertex1] = 1//비방향성이기에 같이 표현
            adMatrix[vertex1][vertex2] = 1;
        }
        
    
        for(int i=0;i<nV;i++) {
            System.out.print(i + "-" );
            for(int j=0;j<nV;j++) {
                System.out.print(adMatrix[j][i]+ " ");
            }
            System.out.println();
        }
    }
    
    /*
     * 공간 복잡도가 vertex의 수 * vertex의 수
     * 공간이 항상 미리 정해지기에 edge가 vertex에 비해 적을 경우
     * 공간 낭비가 일어난다.
     * 
     * 그래프가 드문드문이면 인접리스트 E<V*V
     * 촘촘하면 인접행렬 (행렬은 1비트만 사용)
     * 
     * 간선을 찾는데 걸리는 시간
     * 인접행렬 : 1
     * 인접리스트 : V
     * 
     * 모든 간선을 찾거나 방문하는데 걸리는 시간
     * 인접행렬 : V*V
     * 인접리스트 : V+E
     */
}
cs


'자료구조' 카테고리의 다른 글

[Map] HashMap  (0) 2017.03.10
[Set]HashSet의 특징  (1) 2017.03.09
[그래프]넓이 우선 탐색(BFS)  (0) 2017.03.07
ArrayList와 LinkedList  (0) 2017.01.02
Array 배열 for Java  (0) 2016.12.23

ArrayList란?



배열을 사용하여 리스트를 구현한 것


ArrayList의 구성 - 엘리먼트들로 구성

element의 구성 - 데이터와 인덱스로 구성


장점 - 인덱스를 가지고 있기에 조회가 빠르다

단점 - 추가/삭제시 엘리먼트들을 밀고 당기는 작업이 필요하기 때문에 추가/삭제 속도가 느리다.

   데이터 공간의 낭비가 발생한다.



LinkedList란?


노드와 노드간의 연결로 리스트를 구현한 것


LinkedList의 구성 - Node(or vertex)로 구성, Head는 첫번째 Node를 가리킨다.

Node의 구성 - 데이터를 담는 data field, 연결정보를 담고 있는 linkd field


장점 - 추가/삭제가 빠르다. 데이터 공간의 낭비가 없다

단점 - 조회시 일일히 다 순회하기 때문에 느리다.

'자료구조' 카테고리의 다른 글

[Map] HashMap  (0) 2017.03.10
[Set]HashSet의 특징  (1) 2017.03.09
[그래프]넓이 우선 탐색(BFS)  (0) 2017.03.07
[그래프] 인접리스트와 인접행렬을 이용한 구현  (0) 2017.02.26
Array 배열 for Java  (0) 2016.12.23

배열이란?


여러 데이터를 하나의 이름으로 그룹핑하여 관리하기 위한 자료구조


거의 모든 언어에 포함



배열의 구성

    public class ArrayTest {
         int[] numbers1 = new int[4];
       // int[]에서 
       // int는 엘리먼트의 데이터 타입, []은 배열을 의미
       // new int[4]에서
       // new는 생성자, [4]는 배열의 크기
    }
    

배열은 엘리먼트로 구성되어 있고,

엘리먼트는 index와 value로 구성되어 있다.


 학생1

학생2 

학생3 

학생4 

 0


여기서 학생1이 value이고 0은 index

학생1과 0을 묶어서 엘리먼트 하나를 이룬다.


배열의 생성

    public class ArrayTest {
         int[] numbers1 = new int[4];
         int[] numbers2 = {10, 20, 30, 40};
         int[] numbers3 = new int[] {10, 20, 30, 40};
    }
    

배열에 들어갈 값을 미리 알고 있을 경우, 생성과 초기화를 한번에 할 수 있다.



배열의 조회

    public class ArrayTest {    
        public static void main(String[] args) {
                 int[] numbers1 = new int[4];
                 int[] numbers2 = {10, 20, 30, 40};
                 int[] numbers3 = new int[] {10, 20, 30, 40};
          
                 // 나중에 배열 초기화 방법
                numbers1[0] = 10;
                numbers1[1] = 20;
		
                //배열의 값조회(인덱스를 이용)
                System.out.println(numbers1[0]); //  10이 출력
                
               //배열의 길이
               System.out.println(numbers1.length);  // 4가 출력(처음 만들때 4개의 방을 만들었음)
	}     
    }



배열과 반복문 (배열 사용법!!)

  
               //배열의 길이
               System.out.println(numbers1.length);  // 4가 출력(처음 만들때 4개의 방을 만들었음)

               for(int i=0; i


배열의 단점과 장점


단점 : 배열의 크기가 조정이 불가능, 처음 생성할 때 크기로 고정

        별다른 기능(메서드)가 없다.


장점 : 크기가 고정되어있고, 별다른 기능이 없기 때문에 작고 가볍고 단순하다.

         이는 다른 곳의 부품이 되기 쉽다는 의미, 배열의 확장성이 강하다!! 다른 자료구조나 활용도 면에서...



참고: https://opentutorials.org/module/1335/8738

'자료구조' 카테고리의 다른 글

[Map] HashMap  (0) 2017.03.10
[Set]HashSet의 특징  (1) 2017.03.09
[그래프]넓이 우선 탐색(BFS)  (0) 2017.03.07
[그래프] 인접리스트와 인접행렬을 이용한 구현  (0) 2017.02.26
ArrayList와 LinkedList  (0) 2017.01.02

+ Recent posts