<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>SuperM</title>
    <link>https://hibee.tistory.com/</link>
    <description>핑~</description>
    <language>ko</language>
    <pubDate>Fri, 26 Jun 2026 18:25:03 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>슈퍼마리호</managingEditor>
    <image>
      <title>SuperM</title>
      <url>https://tistory1.daumcdn.net/tistory/2873781/attach/87d9be4f29624a3f83011df46b405d73</url>
      <link>https://hibee.tistory.com</link>
    </image>
    <item>
      <title>[DP] 2. 디자인 패턴 (Design Pattern)</title>
      <link>https://hibee.tistory.com/307</link>
      <description>&lt;html&gt;
&lt;head&gt;
&lt;meta charset='UTF-8'&gt;&lt;meta name='viewport' content='width=device-width initial-scale=1'&gt;
&lt;title&gt;2_디자인 패턴&lt;/title&gt;&lt;/head&gt;
&lt;body&gt;&lt;h2&gt;2. 디자인 패턴 (Design Pattern)&lt;/h2&gt;
&lt;blockquote&gt;&lt;ol&gt;
&lt;li&gt;디자인 패턴이란?&lt;/li&gt;
&lt;li&gt;스트래티지 패턴&lt;/li&gt;
&lt;li&gt;싱글턴 패턴&lt;/li&gt;
&lt;li&gt;옵서버 패턴&lt;/li&gt;
&lt;li&gt;템플릿 메서드 패턴&lt;/li&gt;
&lt;li&gt;팩토리 메서드 패턴&lt;/li&gt;

&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;1. 디자인 패턴이란?&lt;/h3&gt;
&lt;p&gt;소프트웨어를 설계할 때, 특정 맥락에서 자주 발생하는 고질적인 문제들이 또 발생했을 때 &lt;code&gt;재사용&lt;/code&gt; 을 통해 해결할 수 있는 방법이다.&lt;/p&gt;
&lt;blockquote&gt;&lt;ul&gt;
&lt;li&gt;바퀴를 다시 발명하지 마라 (Don&amp;#39;t reinvent the wheel)&lt;/li&gt;
&lt;li&gt;이미 만들어져서 잘 되는 것을 처음부터 다시 만들 필요가 없다는 의미이다&lt;/li&gt;

&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;2. 스트래티지 패턴&lt;/h3&gt;
&lt;p&gt;행위를 클래스로 캡슐화해 동적으로 행위를 자유롭게 바꿀 수 있게 해주는 패턴이다. 같은 문제를 해결하는 여러 알고리즘이 클래스별로 &lt;code&gt;캡슐화&lt;/code&gt; 되어 있고, 이들이 필요할 때 마다 교체할 수 있도록 함으로써 동일한 문제를 다른 알고리즘으로 해결할 수 있게 해준다. 즉, 전략을 쉽게 바꿀 수 있도록 도와주는 디자인 패턴이다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;GoF에 따르면, Strategy 패턴의 의도는 다음과 같다.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;다양한 알고리즘 군을 정의하고, 이들 각각을 캡슐화하여, 호환성 있게 만든다.&lt;/p&gt;
&lt;p&gt;Strategy 패턴은 알고리즘을 이용하는 클라이언트와는 상관없이 독립적으로 이 알고리즘이 변화할 수 있게 해준다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;예를 들어, 국제적인 e-tail 시스템에서는 다른 나라의 세금을 계산하기 위해 서로 다른 세금 계산 알고리즘을 사용한다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;3. 싱글턴 패턴&lt;/h3&gt;
&lt;p&gt;전역 변수를 사용하지 않고, &lt;code&gt;객체를 하나만 생성&lt;/code&gt; 하도록 하며, 생성된 객체를 어디에서든지 참조할 수 있도록 하는 패턴이다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;GoF에 따르면, Singleton 패턴의 의도는 다음과 같다.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;한 클래스가 오직 하나의 인스턴스만을 갖도록 하고, 이 인스턴스에 접근할 수 있는 광범위한 지시자(global point) 를 제공한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;아래는 java를 이용한 기본적인 싱글턴 패턴의 소스 코드이다.&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-java' lang='java'&gt;class USTax {
  private static USTax instance;
  private USTax() { }
  
  public static USTax getInstance() {
    if(instance == null)
      instance = new USTax();
    
    return instance;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;하지만 이 코드에서는 한 가지 문제점이 발생한다.&lt;/p&gt;
&lt;p&gt;만약 다중 스레드 환경에서 동시에 getInstance() 를 호출한다고 가정해보자. 두 스레드는 동시에 null 을 확인하는데, 이 때 두 스레드는 모두 인스턴스를 생성하지 않았다. 따라서, 두 스레드가 &lt;code&gt;new USTax()&lt;/code&gt; 를 수행하게 되어 2개의 인스턴스가 생성된다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이에 대한 해결책으로, &lt;code&gt;synchronized&lt;/code&gt; 키워드를 사용한 &lt;code&gt;doSync()&lt;/code&gt; 메소드를 활용하는 방법이 있다.&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-java' lang='java'&gt;class USTax {
  private static USTax instance;
  private USTax() { }
  
  public synchronized static void doSync() {
    if(instance == null)
      instance = new USTax();
  }
  
  public static USTax getInstance() {
    if(instance == null)
      doSync();
    
    return instance;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;4. 옵서버 패턴&lt;/h3&gt;
&lt;p&gt;한 객체의 상태 변화에 따라 다른 객체의 상태도 연동되도록 일대다 객체 의존 관계를 구성하는 패턴이다. Observer 패턴에서 이벤트를 발생시키고 있는 객체인 Subject는 그 이벤트에 대해 알아야 하는 모든 객체를 예측할 수 가 없다. 따라서 Observer 인터페이스를 생성하고 모든 Observer가 자신을 Subject에 등록하는 책임을 가지도록 요구한다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;GoF에 따르면, Observer 패턴의 의도는 다음과 같다.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;한 객체의 상태가 변경되면, 이 객체에 의존적인 모든 객체가 통지를 받고 자동으로 수정되게 하기 위해, 객체들 간의 일대다 의존관계를 정의하는 것이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;예를 들어, 차량 연료량 클래스는 연료량이 부족한 경우 연료량에 관심을 가지는 구체적인 &lt;strong&gt;클래스(연료량 부족 경고 클래스, 주행 가능 거리 출력 클래스)&lt;/strong&gt; 에 직접 의존하지 않는 방식으로 이를 통보해야한 다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;5. 템플릿 메소드 패턴&lt;/h3&gt;
&lt;p&gt;어떤 작업을 처리하는 일부분을 서브 클래스로 캡슐화하여 전체 일을 수행하는 구조는 바꾸지 않으면서 특정 단계에서 수행하는 내역을 바꾸는 패턴이다. 즉, 전체적으로는 다른 구문으로 구성된 메소드의 코드 죽복을 최소화 할 때 유용하다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;GoF에 따르면, Templete Method 패턴의 의도는 다음과 같다.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Operation에 알고리즘의 골격을 정의하고, 이 알고리즘이 가진 몇 가지 단계의 내용은 서브클래스에게 정의를 맡긴다. Templete Method 패턴은 알고리즘의 구조를 변경하지 않으면서 알고리즘의 단계의 내용을 재정의 한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;6. 팩토리 메소드 패턴&lt;/h3&gt;
&lt;p&gt;객체 생성 처리를 서브 클래스로 분리하여 처리하도록 캡슐화하는 패턴이다. 즉, 객체의 생성 코드를 별도의 클래스/메소드로 분리함으로써 객체 생성의 변화에 대비하는 방법이다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;GoF에 따르면, Factory Method 패턴의 의도는 다음과 같다.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;객체 생성을 위한 인터페이스를 정의하고, 어떤 클래스가 인스턴스화되는지에 대한 결정은 서브클래스가 내리게 한다. Factory Method 패턴은 클래스가 서브클래스에게 인스턴스화에 대한 책임을 전가할 수 있게 해준다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;</description>
      <category>CS/Design Pattern</category>
      <author>슈퍼마리호</author>
      <guid isPermaLink="true">https://hibee.tistory.com/307</guid>
      <comments>https://hibee.tistory.com/307#entry307comment</comments>
      <pubDate>Wed, 1 May 2019 19:22:41 +0900</pubDate>
    </item>
    <item>
      <title>[AL] 9. 자료구조 (Trie)</title>
      <link>https://hibee.tistory.com/306</link>
      <description>&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;9. 자료구조 (Trie)&lt;/h2&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;트라이(Trie)&lt;/li&gt;
&lt;li&gt;구현 방법&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;1. 트라이(Trie)&lt;/h3&gt;
&lt;h4&gt;1.1. 개념&lt;/h4&gt;
&lt;p&gt;트라이(Trie) 는 Re&lt;b&gt;tire&lt;/b&gt;val(탐색) 에서 나온 단어이며, 문자열에서의 검색을 빠르게 해주는 자료구조이다.&lt;/p&gt;
&lt;p&gt;만약 정수형에서 BST 를 이용한다면 &lt;code&gt;O(logN)&lt;/code&gt; 의 시간만에 검색을 할 수 있다. 하지만 문자열에서 BST 를 사용한다고 할 때, 문자열의 길이가 M 이라면 &lt;code&gt;O(M logN)&lt;/code&gt; 의 시간 복잡도를 갖는다.&lt;/p&gt;
&lt;p&gt;이 때, 트라이를 이용한다면 &lt;code&gt;O(M)&lt;/code&gt; 의 시간만에 원하는 문자열을 검색할 수 있게 된다!&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;1.2. 예시&lt;/h4&gt;
&lt;p&gt;우선 문자열 5개 {&quot;blog&quot;, &quot;he&quot;, &quot;her&quot;, &quot;supreme&quot;, &quot;superm&quot;} 이 있다고 가정해보자. 트라이는 이때 아래와 같은 트리를 형성하게 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;Trie.png&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wNWfF/btquI06bYM5/m22bzwlkbL5Eab22O2z8zk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wNWfF/btquI06bYM5/m22bzwlkbL5Eab22O2z8zk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wNWfF/btquI06bYM5/m22bzwlkbL5Eab22O2z8zk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwNWfF%2FbtquI06bYM5%2Fm22bzwlkbL5Eab22O2z8zk%2Fimg.png&quot; data-filename=&quot;Trie.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;루트 노드가 되는 최상위 노드에는 어떠한 단어도 들어가지 않고, 루트 아래 노드부터 문자열들의 접두사가 하나씩 나타나게 된다.&lt;/p&gt;
&lt;p&gt;superm 은 s &amp;rarr; su &amp;rarr; sup &amp;rarr; supe &amp;rarr; super &amp;rarr; superm 으로 이루어지는데 이 과정에서 나타난 것들은 모두 superm 의 접두사이다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;1.3. 트라이의 단점&lt;/h4&gt;
&lt;p&gt;트라이는 공간 복잡도에서 치명적인 단점을 갖는다.&lt;/p&gt;
&lt;p&gt;트라이에서 저러한 O(m)의 시간 복잡도가 나오기 위해서는 다음 문자를 가리키는 노드가 필요하다. 예를 들어, 알파벳에 대해 트리를 형성해야 한다면 a~z 인 총 26개의 포인터 배열을 가지고 있어야 한다.&lt;/p&gt;
&lt;p&gt;즉, 최종 메모리는 &lt;code&gt;O(포인터 크기 * 포인터 배열의 개수 * 트라이에 존재하는 총 노드의 수)&lt;/code&gt; 가 된다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;2. 구현 방법&lt;/h3&gt;
&lt;h4&gt;2.1. 소스 코드 (C++)&lt;/h4&gt;
&lt;pre class=&quot;gradle&quot;&gt;&lt;code&gt;struct Trie {
  bool finish;		// 끝나는 지점
  Trie* next[26];	// 알파벳 26개에 대한 트라이
  
  Tire() : finish(false) {
    memset(next, 0, sizeof(next));
  }
  ~Trie() {
    for(int i=0; i&amp;lt;26; i++){
      if(next[i])
        delete next[i];
    }
  }
  
  void insert(const char* key) {
    if(*key == '\0')
      finish = true;	// 문자열이 끝나는 지점 표시
    else{
      int current = *key - 'A';
      if(next[current] == NULL){
        next[current] = new Trie();	// 탐색이 처음되는 지점일 경우 동적할당
      }
      next[current]-&amp;gt;insert(key+1);	// 다음 문자 삽입
    }
  }
  
  Trie* find(const char* key){
    if(*key == '\0')
      return this;		// 문자열이 끝나는 위치를 반환
    
    int current = *key - 'A';
    if(next[current] == NULL)
      return NULL;		// 찾는 값이 존재하지 않음
    return next[current]-&amp;gt;find(key+1);	// 다음 문자 탐색
  }
  
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr /&gt;
&lt;h4&gt;참고 자료&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.crocus.co.kr/1053&quot;&gt;https://www.crocus.co.kr/1053&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://brunch.co.kr/@springboot/75&quot;&gt;https://brunch.co.kr/@springboot/75&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>CS/Algorithm</category>
      <author>슈퍼마리호</author>
      <guid isPermaLink="true">https://hibee.tistory.com/306</guid>
      <comments>https://hibee.tistory.com/306#entry306comment</comments>
      <pubDate>Tue, 23 Apr 2019 15:00:17 +0900</pubDate>
    </item>
    <item>
      <title>[OS] 8. 디스크 관리 (Disk Management)</title>
      <link>https://hibee.tistory.com/305</link>
      <description>&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;8. 디스크 관리&lt;/h2&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;디스크 관리&lt;/li&gt;
&lt;li&gt;디스크 스케줄링&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;1. 디스크 관리&lt;/h3&gt;
&lt;p&gt;디스크에 대한 &lt;code&gt;접근 시간(Access Time)&lt;/code&gt; 은 아래와 같이 구분된다&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;b&gt;탐색 시간(Seek Time)&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;디스크 헤드를 해당 실린더 위치로 이동시키는 데 걸리는 시간&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;회전 지연 시간(Rotational Latency)&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;디스크가 회전해서 읽고 쓰려는 섹터가 헤드 위치에 도달하기까지 걸리는 시간&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;전송 시간(Transfer Time)&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;해당 섹터가 헤드 위치에 도달한 후 데이터를 실제로 섹터에 읽고 쓰는데 소요되는 시간&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;2. 디스크 스케줄링&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;효율적인 디스크 입출력을 위해 여러 섹터들에 대한 입출력 요청이 들어왔을 때, 이들을 어떠한 순서로 처리할 것인지 결정하는 매커니즘이다. 디스크 스케줄링의 가장 중요한 목표는 디스크 헤드의 이동 거리를 줄이는 것이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;2.1. FCFS 스케줄링&lt;/h4&gt;
&lt;p&gt;디스크에 먼저 들어온 요청을 먼저 처리하는 방식을 말한다.&lt;/p&gt;
&lt;p&gt;만약 입출력 요청이 한쪽 끝과 반대쪽 끝에 번갈아 도착한다면 헤드는 디스크를 계속 왕복하며 일을 처리해야 하므로 탐색 시간이 매우 늘어나는 결과를 초래한다.&lt;/p&gt;
&lt;h4&gt;2.2. SSTF 스케줄링&lt;/h4&gt;
&lt;p&gt;현재 헤드의 위치로부터 가장 가까운 위치에 있는 요청을 제일 먼저 처리하는 알고리즘을 말한다.&lt;/p&gt;
&lt;p&gt;헤드의 이동 거리를 줄여 디스크 입출력의 효율성을 증가시키지만, &lt;code&gt;기아 현상(Starvation)&lt;/code&gt; 을 발생시킬 수 있다. 만약 현재 위치와 가까운 곳에 지속적인 요청이 들어올 경우 헤드와 먼 요청은 무한히 기다려야 하는 문제가 발생할 수 있다.&lt;/p&gt;
&lt;h4&gt;2.3. SCAN 알고리즘 (= 엘리베이터 스케줄링 알고리즘)&lt;/h4&gt;
&lt;p&gt;헤드가 디스크 원판의 한쪽 끝에서 다른 쪽 끝으로 이동하며, 그 경로에 존재하는 모든 요청을 처리한다. 즉, 디스크의 어떠한 위치에 요청이 들어오는가와 상관없이 정해진 방향으로 이동하며 요청을 처리하는 방법이다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;FCFS의 비효율성&lt;/code&gt; , &lt;code&gt;SSTF의 비형평성&lt;/code&gt; 을 극복한 방법이지만, 가운데 위치가 기다리는 평균 시간이 더 짧다는 문제점을 지니고 있다.&lt;/p&gt;
&lt;h4&gt;2.4. C-SCAN 알고리즘&lt;/h4&gt;
&lt;p&gt;SCAN 알고리즘의 문제점을 극복한 방법으로, 다른 쪽 끝에 도달해 방향을 바꾼 후에는 요청을 처리하지 않고 곧바로 출발점으로 다시 이동만 한다. SCAN 보다 헤드의 이동 거리는 조금 길어지지만 탐색 시간의 편차를 해결할 수 있다.&lt;/p&gt;
&lt;h4&gt;2.5. LOOK / C-LOOK&lt;/h4&gt;
&lt;p&gt;SCAN 알고리즘은 요청의 존재 여부와 관계 없이 헤드가 무조건 디스크의 끝에서 끝으로 이동하는 반면에, LOOK 은 한쪽 방향으로 이동 중이다가 전방에 더 이상 대기중인 요청이 없으면 이동 방향을 즉시 변경하는 방식이다.&lt;/p&gt;
&lt;p&gt;C-LOOK 은 전방에 요청이 없을 때 방향을 바꾼다는 측면에서 LOOK 과 유사하며, 한쪽 방향으로 이동할 때만 요청을 처리한다는 점에서 C-SCAN 과 유사하다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CS/Operating System</category>
      <author>슈퍼마리호</author>
      <guid isPermaLink="true">https://hibee.tistory.com/305</guid>
      <comments>https://hibee.tistory.com/305#entry305comment</comments>
      <pubDate>Mon, 22 Apr 2019 17:41:38 +0900</pubDate>
    </item>
    <item>
      <title>[OS] 7. 가상 메모리 (Virtual Memory)</title>
      <link>https://hibee.tistory.com/304</link>
      <description>&lt;h2&gt;7. 가상 메모리 (Virtual Memory)&lt;/h2&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;가상 메모리&lt;/li&gt;
&lt;li&gt;요구 페이징&lt;/li&gt;
&lt;li&gt;페이지 교체 알고리즘&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;1. 가상 메모리 (Virtual Memory)&lt;/h3&gt;
&lt;h4&gt;1.1. 배경&lt;/h4&gt;
&lt;p&gt;운영체제는 CPU에서 당장 수행해야 할 부분만 메모리에 올려놓고 그렇지 않은 부분은 디스크의 &lt;code&gt;스왑 영역(Swap Area)&lt;/code&gt; 에 내려놓았다가 다시 필요해지면 메모리에 올라가 있는 부분과 교체하는 방식을 사용한다. 이와 같이 메모리의 연장 공간으로 스왑 영역이 사용될 수 있기 때문에 프로그램 입장에서는 물리적 메모리 크기에 대한 제약을 생각할 필요가 없다.&lt;/p&gt;
&lt;h4&gt;1.2. 개념&lt;/h4&gt;
&lt;p&gt;가상 메모리는 프로세스마다 각각 0번지부터의 주소 공간을 가지게 되며, 이들 공간 중 일부는 물리적 메모리에 적재되고 일부는 디스크의 스왑 영역에 존재하게 된다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;2. 요구 페이징&lt;/h3&gt;
&lt;h4&gt;2.1. 요구 페이징 (Demand Paging)&lt;/h4&gt;
&lt;p&gt;프로그램 실행 시, 프로세스를 구성하는 모든 페이지를 한꺼번에 메모리에 올리는 것이 아니라 당장 사용될 페이지만을 메모리에 올리는 방식이다.&lt;/p&gt;
&lt;p&gt;당장 실행에 필요한 페이지만을 메모리에 적재하기 때문에, 메모리 사용량이 감소하고 프로세스 전체를 메모리에 올리는 데 들었던 입출력 오버헤드도 줄어든다.&lt;/p&gt;
&lt;p&gt;요구 페이징에서는 유효-무효비트 를 두어 각 페이지가 메모리에 존재하는지를 구별한다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;b&gt;유효비트&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;현재 페이지가 메모리에 있는 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;무효비트&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;현재 페이지가 스왑 영역에 있는 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h4&gt;2.2. 페이지 부재 (Page Fault)&lt;/h4&gt;
&lt;p&gt;CPU가 참조하려는 페이지가 현재 메모리에 올라와 있지 않아 유효-무효비트가 무효로 세팅되어 있는 경우를 말한다.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;페이지 부재 처리&lt;/b&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;CPU가 무효 페이지에 접근하면, 주소 변환을 담당하는 하드웨어인 MMU가 &lt;code&gt;페이지 부재 트랩(page fault trap)&lt;/code&gt; 을 발생시킨다. 그러면 CPU 제어권이 커널 모드로 전환되고, 운영체제의 &lt;code&gt;페이지 부재 처리 루틴(page fault handler)&lt;/code&gt; 이 호출되어 아래와 같이 처리를 진행한다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;해당 페이지에 대한 접근이 적법한지를 체크&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;물리적 메모리에서 비어 있는 &lt;code&gt;프레임(free frame)&lt;/code&gt; 을 할당받아 그 공간에 해당 페이지를 읽어옴&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;만약 비어 있는 프레임이 없다면 페이지 중 하나를 스왑 영역으로 쫓아냄 &lt;code&gt;swap out&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이 과정은 오랜 시간이 소요되므로, 페이지 부재를 발생시킨 프로세스는 CPU 제어권을 빼앗기고 &lt;code&gt;blocked&lt;/code&gt; 상태가 된다. 작업이 모두 완료되면 해당 페이지를 다시 유효비트로 설정하고, blocked 상태의 프로세스를 &lt;code&gt;ready queue&lt;/code&gt; 로 이동시킨다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;3. 페이지 교체 알고리즘&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;페이지 부재가 발생했을 때, 페이지 부재율을 최소화하여 swap out 시킬 페이지를 선택하는 알고리즘&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;3.1. 최적 페이지 교체 (Optimal Page Replacement)&lt;/h4&gt;
&lt;p&gt;페이지 교체시 물리적 메모리에 존재하는 페이지 중 가장 먼 미래에 참조될 페이지를 쫓아내는 방법이다. 이 알고리즘은 미래에 어떤 페이지가 어떠한 순서로 참조될지 미리 알고있다는 전재 하에 운영하므로 실제로 사용할 수 있는 알고리즘은 아니다.&lt;/p&gt;
&lt;h4&gt;3.2. FIFO 알고리즘&lt;/h4&gt;
&lt;p&gt;페이지 교체시 물리적 메모리에 가장 먼저 올라온 페이지를 우선적으로 내쫓는다. 페이지의 향후 가능성을 고려하지 않고, 물리적 메모리에 들어온 순서대로 내쫓을 대상을 선정하기 때문에 비효율적인 상황이 발생할 수 있다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;b&gt;FIFO 이상 현상&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;메모리를 증가시켰음에도 불구하고 페이지 부재가 오히려 늘어나는 상황&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;3.3. LRU 알고리즘&lt;/h4&gt;
&lt;p&gt;최근에 참조된 페이지가 가까운 미래에 다시 참조될 가능성이 높다는 &lt;code&gt;시간 지역성(Temporal Locality)&lt;/code&gt; 을 활용해서 페이지 교체시 가장 오래 전에 참조가 이루어진 페이지를 교체하는 방법이다.&lt;/p&gt;
&lt;h4&gt;3.4. LFU 알고리즘&lt;/h4&gt;
&lt;p&gt;페이지 부재시 과거에 참조 횟수가 가장 적었던 페이지를 교체하는 방법이다. 최저 참조 횟수를 가진 페이지가 여러 개 존재한다면 임의로 하나를 선정하여 쫓아낸다. &lt;code&gt;LRU&lt;/code&gt; 는 직접 참조된 시점만을 반영하지만, &lt;code&gt;LFU&lt;/code&gt; 는 참조 횟수를 통해 장기적인 시간 규모에서의 참조 성향을 고려한다는 장점을 가지고 있다.&lt;/p&gt;
&lt;h4&gt;3.5. Clock 알고리즘&lt;/h4&gt;
&lt;p&gt;LRU 와 LFU 알고리즘은 페이지의 최근 참조 시각 및 참조 횟수를 유지해야 하므로 시간적인 오버헤드가 발생한다. 클럭 알고리즘은 하드웨어적인 지원을 통해 운영 오버헤드를 감소시킨 방법이다.&lt;/p&gt;
&lt;p&gt;LRU 를 근사(approximation)시킨 알고리즘으로 &lt;code&gt;NUR(Not Used Recently)&lt;/code&gt; 또는 &lt;code&gt;NRU(Not Recently Used)&lt;/code&gt; 라고 불린다. LRU 이 가장 오래 전에 참조된 페이지를 교체하는 것에 비해, 클럭 알고리즘은 오랫동안 참조되지 않은 페이지 중 하나를 교체한다. 교체되는 페이지의 참조 시점이 가장 오래되었다는 것을 보장하지 못한다는 점에서 LRU를 근사시킨 알고리즘으로 볼 수 있다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;하드웨어에 의해 조작되며 운영체제는 참조 비트(Reference bit) 를 참고하여 Victim 결정&lt;/li&gt;
&lt;li&gt;Reference bit = 1 (최근사용) , Reference bit = 0 (최근사용 X)&lt;/li&gt;
&lt;li&gt;시계방향으로 움직이며 참조 비트가 1이면 0으로 바꾸고, 한바퀴 돌고와서도 0인 것을 교체&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CS/Operating System</category>
      <author>슈퍼마리호</author>
      <guid isPermaLink="true">https://hibee.tistory.com/304</guid>
      <comments>https://hibee.tistory.com/304#entry304comment</comments>
      <pubDate>Mon, 22 Apr 2019 17:41:12 +0900</pubDate>
    </item>
    <item>
      <title>[OS] 6. 메모리 관리 (Memory Management)</title>
      <link>https://hibee.tistory.com/303</link>
      <description>&lt;h2&gt;6. 메모리 관리&lt;/h2&gt;
&lt;blockquote&gt;
&lt;ol start=&quot;&quot;&gt;
&lt;li&gt;메모리 관리 (Memory Management)&lt;/li&gt;
&lt;li&gt;연속 할당 방식 (Contiguous Allocation)&lt;/li&gt;
&lt;li&gt;비연속 할당 방식 (Noncontiguous Allocation)&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;1. 메모리 관리 (Memory Management)&lt;/h3&gt;
&lt;h4&gt;1.1. 메모리 관리&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;b&gt;물리적 주소 (Physical Address)&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;물리 메모리에 실제 올라기는 위치&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;논리적 주소 (Logical Address)&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;프로그램이 메모리에 적재되면 생기는 해당 프로세스를 위한 독자적인 주소 공간&lt;/li&gt;
&lt;li&gt;CPU 가 보는 주소는 Logical Address&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;주소 바인딩 (Address Binding)&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;프로세스의 논리적 주소를 물리적 메모리 주소로 연결시켜 주는 작업&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;1.2. MMU&lt;/h4&gt;
&lt;p&gt;논리적 주소를 물리적 주소로 매핑해 주는 하드웨어 장치로서, &lt;code&gt;재배치 레지스터(Relocation Register)&lt;/code&gt; 와 &lt;code&gt;한계 레지스터(Limit Register)&lt;/code&gt; 를 사용하여 매핑한다. 매핑하는 과정은 아래와 같다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol start=&quot;&quot;&gt;
&lt;li&gt;
&lt;p&gt;CPU가 논리적 주소 &lt;code&gt;123&lt;/code&gt; 번지에 있는 내용을 요청&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;재배치 레지스터에 저장된 &lt;code&gt;23000&lt;/code&gt; 이라는 값에 논리적 주소를 더함&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;논리적 주소 &lt;code&gt;123&lt;/code&gt; 번지는 물리적 메모리의 시작 위치인 재배치 레지스터 값으로부터 요청된 위치가 얼마나 떨어져있는지를 나타내는 &lt;b&gt;오프셋(offset)&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;한계 레지스터는 해당 프로세스의 크기를 저장&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;만약 요청한 논리적 주소가 이 값을 벗어나면 트랩을 이용해 프로세스 강제 종료&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;23123&lt;/code&gt; 번지의 물리적 메모리에는 CPU가 요청한 정보가 들어있음&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;MMU.png&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dwKMX0/btquHQvvn5c/DDxAoQPrDtMz5dgExudAUK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dwKMX0/btquHQvvn5c/DDxAoQPrDtMz5dgExudAUK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dwKMX0/btquHQvvn5c/DDxAoQPrDtMz5dgExudAUK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdwKMX0%2FbtquHQvvn5c%2FDDxAoQPrDtMz5dgExudAUK%2Fimg.png&quot; data-filename=&quot;MMU.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;1.3. 관련 용어&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;b&gt;동적 로딩 (Dynamic Loading)&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;물리 메모리에 프로세스 전체를 올려놓는 것이 아닌, &lt;code&gt;필요한 루틴&lt;/code&gt; 을 그 때마다 적재하는 방식&lt;/li&gt;
&lt;li&gt;다중 프로그래밍 환경에서 효율성을 높이기 위함&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;동적 연결 (Dynamic Linking)&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Linking(Object File과 Library File을 묶어 실행 파일 생성)&lt;/code&gt; 을 실행 시점에서 하는 것&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;중첩 (Overlay)&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;프로세스의 크기가 물리 메모리보다 클 때 유용한 방법&lt;/li&gt;
&lt;li&gt;프로세스에서 당장 필요한 부분을 메모리에 적재하는 방식&lt;/li&gt;
&lt;li&gt;&lt;code&gt;동적 로딩&lt;/code&gt; 과 유사하지만 그 목적이 다름&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;스와핑 (Swapping)&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;프로세스를 일시적으로 &lt;code&gt;Swap Area&lt;/code&gt; 로 쫓아내는 것&lt;/li&gt;
&lt;li&gt;다중 프로그래밍 환경에서 프로그램 수를 조절하여 성능 이슈를 해결하기 위함&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;2. 연속 할당 방식 (Contiguous Allocation)&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;각각의 프로세스가 메모리의 연속적인 공간에 적재되도록 하는 방식&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;2.1. 고정 분할 방식 (Fixed Partition Allocation)&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;물리적 메모리를 주어진 개수만큼의 영구적인 &lt;code&gt;분할(Partition)&lt;/code&gt; 으로 미리 나누어 각 분할에 하나의 프로세스를 적재하여 실행하도록 하는 방식&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;융통성이 매우 떨어지는 방식&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;b&gt;외부 단편화&lt;/b&gt; 및 &lt;b&gt;내부 단편화&lt;/b&gt;가 발생할 수 있음&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;외부 단편화 : 빈 파티션이지만 프로세스보다 크기가 작아 이용될 수 없음&lt;/li&gt;
&lt;li&gt;내부 단편화 : 파티션에 프로세스를 적재했을 때, 공간이 남아 메모리 낭비 발생&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;2.2. 가변 분할 방식 (Variable Partition Allocation)&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;프로그램의 크기를 고려하여 파티션의 크기 및 개수를 동적으로 바꾸는 방식&lt;/li&gt;
&lt;li&gt;어떤 프로그램이 종료되었을 때, 그 빈 파티션에서 &lt;b&gt;외부 단편화&lt;/b&gt;가 발생할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;가변 분할 방식에서 크기가 n인 프로세스를 적재할 파티션을 찾는 방법&lt;/b&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;b&gt;First Fit&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;크기가 n 이상인 것 중, 최초로 찾은 파티션에 적재&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;Best Fit&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;크기가 n 이상인 것 중, 가장 크기가 작은 파티션에 적재&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;Worst Fit&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;크기가 가장 큰 파티션에 적재&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;3. 비연속 할당 방식 (Noncontiguous Allocation)&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;하나의 프로세스가 메모리의 여러 영역에 분산되어 올라가는 방식&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;3.1. 페이징 (Paging)&lt;/h4&gt;
&lt;p&gt;프로세스의 가상 메모리를 동일한 사이즈의 페이지 단위로 나누어 물리적 메모리에 불연속적으로 저장하는 방식&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;물리 메모리와 가상 메모리를 동일한 크기의 &lt;code&gt;Frame&lt;/code&gt; 으로 나눔&lt;/li&gt;
&lt;li&gt;모든 프로세스가 각각의 주소 변환을 위한 &lt;code&gt;페이지 테이블&lt;/code&gt; 을 가지며, 이 테이블은 프로세스가 가질 수 있는 페이지의 개수만큼 주소 변환 엔트리를 갖음&lt;/li&gt;
&lt;li&gt;특정 프로세스의 몇 번째 페이지가 물리적 메모리의 몇 번째 프레임에 들어 있다는 페이지별 주소 변환 정보를 유지하고 있어야함&lt;/li&gt;
&lt;li&gt;&lt;code&gt;외부 단편화 X , 내부 단편화 O&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;3.2. 세그먼테이션 (Segmentation)&lt;/h4&gt;
&lt;p&gt;프로세스의 가상 메모리를 의미 단위인 세그먼트로 나누어 물리 메모리에 적재하는 방식&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;일반적으로 &lt;code&gt;code, data, stack&lt;/code&gt; 부분이 하나씩의 세그먼트로 정의&lt;/li&gt;
&lt;li&gt;논리적인 단위인 세그먼트로 나누었기 때문에 그 크기가 균일하지 않음&lt;/li&gt;
&lt;li&gt;페이징 기법과는 달리, 프로그램을 의미 단위로 나누었기 때문에 부가적인 메모리 관리 오버헤드가 뒤따름&lt;/li&gt;
&lt;li&gt;세그먼트는 의미 단위이기 때문에 공유와 보안에 있어 페이징 기법보다 효과적&lt;/li&gt;
&lt;li&gt;세그먼트의 길이가 동일하지 않으므로 &lt;code&gt;외부 단편화&lt;/code&gt; 발생&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;3.3. 페이지드 세그먼테이션 (Paged Segmentation)&lt;/h4&gt;
&lt;p&gt;페이징 기법과 세그먼테이션 기법의 장점만을 취하는 주소 변환 기법&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;프로그램을 의미 단위인 세그먼트로 나누지만, 세그먼트가 임의의 길이를 가질 수 없고 반드시 동일한 크기의 페이지들의 집합 으로 구성&lt;/li&gt;
&lt;li&gt;물리 메모리에 적재하는 단위는 페이지 단위&lt;/li&gt;
&lt;li&gt;하나의 세그먼트 크기를 페이지 크기의 배수로 함으로써 외부 단편화 해결&lt;/li&gt;
&lt;li&gt;세그먼트 단위로 프로세스 간의 공유나 프로세스 내의 접근 권한 보호로 페이징 기법의 약점 보완&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CS/Operating System</category>
      <author>슈퍼마리호</author>
      <guid isPermaLink="true">https://hibee.tistory.com/303</guid>
      <comments>https://hibee.tistory.com/303#entry303comment</comments>
      <pubDate>Mon, 22 Apr 2019 17:40:42 +0900</pubDate>
    </item>
    <item>
      <title>[AL] 8. 최단 경로 알고리즘</title>
      <link>https://hibee.tistory.com/302</link>
      <description>&lt;h2&gt;8. 최단 경로 알고리즘&lt;/h2&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;최단 경로(Short Path) 알고리즘&lt;/li&gt;
&lt;li&gt;다익스트라(Dijkstra) 알고리즘&lt;/li&gt;
&lt;li&gt;플로이드-와샬(Floyd-Warshall) 알고리즘&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;1. 최단 경로(Short Path) 알고리즘&lt;/h3&gt;
&lt;h4&gt;1.1. 알고리즘의 종류&lt;/h4&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;b&gt;Single-Source (One-to-All)&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;하나의 출발 노드로부터 다른 모든 노드까지의 최단 경로&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Dijkstra Algorithm&lt;/code&gt; 을 사용하여 해결&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;b&gt;Single-Destination&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;모든 노드로부터 하나의 노드까지의 최단 경로&lt;/li&gt;
&lt;li&gt;모든 Edge를 뒤집으면 &lt;code&gt;One-to-All&lt;/code&gt; 과 동일함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;b&gt;Single-Pair (One-to-One)&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;하나의 출발 노드로부터 하나의 목적 노드로까지의 최단 경로&lt;/li&gt;
&lt;li&gt;시간복잡도에서 &lt;code&gt;One-to-All&lt;/code&gt; 보다 비효율적&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;b&gt;All-Pair (All-to-All)&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;모든 노드 쌍의 최단 경로&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Floyd-Warshall Algorithm&lt;/code&gt; 을 사용하여 해결&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;2. 다익스트라(Dijkstra) 알고리즘&lt;/h3&gt;
&lt;h4&gt;2.1. Logic&lt;/h4&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;초기 dist 배열을 모두 INF 값으로 초기화&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;첫 정점을 기준으로 연결되어 있는 정점을 추가해가며 최단 거리를 갱신함&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A &amp;rarr; B 인 경우, dist[b] 는 아래의 2개 중 최소값을 저장함&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;시작점 부터 a 까지의 최소비용 + a &amp;rarr; b 의 가중치&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;기존에 가지고 있던 b 의 최소비용&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;2.2. Relax 연산&lt;/h4&gt;
&lt;pre class=&quot;processing&quot;&gt;&lt;code&gt;// u : 정점1
// v : 정점2
// w : 정점1과 정점2의 가중치
if(dist[v] &amp;gt; dist[u] + w){
  dist[v] = dist[u] + w;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;2.3. 진행 과정&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;graph.png&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dzFHeT/btquGXgqacT/I4LZjed5Sii7MFUQ5DbWi0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dzFHeT/btquGXgqacT/I4LZjed5Sii7MFUQ5DbWi0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dzFHeT/btquGXgqacT/I4LZjed5Sii7MFUQ5DbWi0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdzFHeT%2FbtquGXgqacT%2FI4LZjed5Sii7MFUQ5DbWi0%2Fimg.png&quot; data-filename=&quot;graph.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;먼저 시작점은 &lt;code&gt;E&lt;/code&gt; 이다&lt;/p&gt;
&lt;p&gt;&lt;code&gt;E&lt;/code&gt; 에서 갈 수 있는 경로는 &lt;code&gt;B&lt;/code&gt; 와 &lt;code&gt;D&lt;/code&gt; 이다&lt;/p&gt;
&lt;p&gt;먼저 &lt;code&gt;D&lt;/code&gt; 노드를 보면, 현재 비용은 &amp;infin; 이고, E를 거쳐 갈 수 있는 비용은 2 이다. 이 중 최소값은 2이다&lt;/p&gt;
&lt;p&gt;&lt;code&gt;B&lt;/code&gt; 노드의 경우, 현재 비용은 &amp;infin; 이고, E를 거쳐 갈 수 있는 비용은 4 이다. 이 중 최소값은 4이다&lt;/p&gt;
&lt;p&gt;이제 나머지 정점 중에서 가장 짧은 정점을 가지고 있는 &lt;code&gt;D&lt;/code&gt; 를 고른다&lt;/p&gt;
&lt;p&gt;&lt;code&gt;D&lt;/code&gt; 노드에서 갈 수 있는 경로는 &lt;code&gt;B&lt;/code&gt; 와 &lt;code&gt;C&lt;/code&gt; 이다&lt;/p&gt;
&lt;p&gt;&lt;code&gt;B&lt;/code&gt; 의 현재 비용은 4 이고, &lt;code&gt;D&lt;/code&gt; 를 거치는 비용은 3 이다. 이 중 최소값은 3이다&lt;/p&gt;
&lt;p&gt;&lt;code&gt;C&lt;/code&gt; 노드의 경우 현재 비용은 &amp;infin; 이고, &lt;code&gt;D&lt;/code&gt; 를 거치는 비용은 3 이다. 이 중 최소값은 3이다&lt;/p&gt;
&lt;p&gt;이런 식으로 진행 하다보면 최소 경로를 모두 구할 수 있다&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;3. 플로이드-와샬(Floyd-Warshall) 알고리즘&lt;/h3&gt;
&lt;h4&gt;3.1. Logic&lt;/h4&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;두 정점 사이에 간선이 존재하지 않는다면 dist 배열에 INF 를 설정&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;만약 간선이 존재한다면 가중치를 설정&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;i &amp;rarr; j&lt;/code&gt; 의 최단 경로는 k를 지나는 경우와 지나지 않는 경우 중 하나이다&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;정점 i 와 j 의 경우를 탐색할 때, k는 모든 정점을 반복문으로 탐색&lt;/li&gt;
&lt;li&gt;&lt;code&gt;i &amp;rarr; j 의 비용&lt;/code&gt; 과 &lt;code&gt;i &amp;rarr; k + k &amp;rarr; j 의 비용&lt;/code&gt; 중 최소값을 저장&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;3.2. 소스 코드 (C++)&lt;/h4&gt;
&lt;pre class=&quot;c++ cpp&quot;&gt;&lt;code&gt;int dist[15][15];
int n;

int floyd(){
  
  for(int k=1; k&amp;lt;=n; k++){
    for(int i=1; i&amp;lt;=n; i++){
      for(int j=1; j&amp;lt;=n; j++){
        if(dist[i][j] &amp;gt; dist[i][k] + dist[k][j]){
          dist[i][j] = dist[i][k] + dist[k][j];
        }
      }
    }
  }
    
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;3.3. 정리&lt;/h4&gt;
&lt;p&gt;&lt;b&gt;Case : 정점 V 개 , 간선 E 개&lt;/b&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;b&gt;다익스트라 알고리즘&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;시작점으로부터 나머지 정점까지의 최단거리를 구할 때&lt;/li&gt;
&lt;li&gt;공간 복잡도 : &lt;code&gt;V^2 (인접행렬)&lt;/code&gt; , &lt;code&gt;V+E (인접리스트)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;시간 복잡도 : &lt;code&gt;V^2 (인접행렬)&lt;/code&gt; , &lt;code&gt;E logV (인접리스트+우선순위 큐)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;플로이드 와샬 알고리즘&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;각 정점간 최단 경로를 구할 때&lt;/li&gt;
&lt;li&gt;공간 복잡도 : &lt;code&gt;V^2&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;시간 복잡도 : &lt;code&gt;V^3&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;장단점&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;만약 간선 수가 많은 경우 &lt;code&gt;플로이드 알고리즘&lt;/code&gt; 이 유리할 수 있음&lt;/li&gt;
&lt;li&gt;한 점으로부터 각 정점까지의 최단거리만 필요하다면 &lt;code&gt;다익스트라&lt;/code&gt; 가 압도적으로 빠름&lt;/li&gt;
&lt;li&gt;그래프의 음의 가중치 간선이 존재한다면 &lt;code&gt;다익스트라 X , 플로이드 O&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;</description>
      <category>CS/Algorithm</category>
      <author>슈퍼마리호</author>
      <guid isPermaLink="true">https://hibee.tistory.com/302</guid>
      <comments>https://hibee.tistory.com/302#entry302comment</comments>
      <pubDate>Sat, 20 Apr 2019 17:01:54 +0900</pubDate>
    </item>
    <item>
      <title>[OS] 5. 데드락 (Deadlock)</title>
      <link>https://hibee.tistory.com/301</link>
      <description>&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;5. 데드락 (Deadlock)&lt;/h2&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;데드락 (Deadlock)&lt;/li&gt;
&lt;li&gt;데드락의 처리&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;1. 데드락 (Deadlock)&lt;/h3&gt;
&lt;h4&gt;1.1. Deadlock (= 교착 상태)&lt;/h4&gt;
&lt;p&gt;일련의 프로세스들이 서로가 가진 자원을 기다리며 &lt;code&gt;Block&lt;/code&gt; 된 상태&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;1.2. Deadlock 발생의 4가지 조건&lt;/h4&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;b&gt;Mutual Exclusion (상호 배제)&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;매 순간 하나의 프로세스만이 자원을 사용할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;b&gt;No Preemption (비선점)&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;프로세스는 자원을 스스로 내놓을 뿐 강제로 빼앗기지 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;b&gt;Hold and Wait (점유 대기)&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;자원을 가진 프로세스가 다른 자원을 기다릴 때, 보유 자원을 놓지 않고 갖고 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;b&gt;Circular Wait (순환 대기)&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;자원을 기다리는 프로세스간, 사이클이 형성되어야함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;2. 데드락의 처리&lt;/h3&gt;
&lt;h4&gt;2.1. Deadlock Prevention&lt;/h4&gt;
&lt;p&gt;자원 할당 시, 데드락의 4가지 조건 중, 어느 하나가 만족되지 않도록 하는 것&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;b&gt;상호 배제 (Mutual Exclusion) 부정&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;여러 개의 프로세스가 공유 자원을 사용할 수 있도록 한다&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;비선점 (No Preemption) 부정&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Save &amp;amp; Restore&lt;/code&gt; 이 가능한 자원에서 선점(Preemption)을 허용한다&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;점유 대기 (Hold and Wait) 부정&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;프로세스 시작 시, 모든 자원을 할당한다&lt;/li&gt;
&lt;li&gt;자원이 필요한 경우, 보유 자원을 놓는다&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;순환 대기 (Circular Wait) 부정&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;할당 순서를 정하여, 정해진 순서대로 자원을 할당한다&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;2.2. Deadlock Avoidance&lt;/h4&gt;
&lt;p&gt;자원 요청에 대한 부가적인 정보를 이용하여, 데드락의 가능성이 없는 경우에만 자원 할당&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;b&gt;자원 할당 그래프 (Resource Allocation Graph)&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;각 자원의 타입이 한 개 씩 있는 경우 (Single Instance)&lt;/li&gt;
&lt;li&gt;프로세스와 자원의 요청 및 할당 관계를 표시함&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Circular Wait&lt;/code&gt; 조건을 발견하기 위한 목적으로 사용&lt;/li&gt;
&lt;li&gt;사이클을 형성 (단, 자원이 사이클을 형성하는 프로세스 외의 다른 프로세스들에게도 점유 당하고 있다면 제외) 한다면 데드락이 발생하는 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;은행원 알고리즘 (Banker's Algorithm)&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;각 자원의 타입이 여러개 있는 경우 (Multiple Instance)&lt;/li&gt;
&lt;li&gt;프로세스가 자원을 요구할 때, 시스템이 자원을 할당한 후 안정 상태로 남아있게 되는지를 사전에 검사하여 교착상태를 회피하는 방법&lt;/li&gt;
&lt;li&gt;알고리즘을 이용해 &lt;code&gt;안정 상태&lt;/code&gt; 인지 확인하고 안정 상태라면 자원을 할당하고 그렇지 않으면 다른 프로세스들이 자원을 해제할 때까지 대기&lt;/li&gt;
&lt;li&gt;할당할 수 있는 자원의 수와 사용자의 수가 일정해야하고, 항상 불안정 상태를 방지해야 하므로 자원 이용도가 낮다는 단점을 지님&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;2.3. Deadlock Detection &amp;amp; Recovery&lt;/h4&gt;
&lt;p&gt;데드락 발생은 허용하되, 그에 대한 감지를 하여 데드락 발견시 회복함&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;b&gt;Detection&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Single Instance&lt;/code&gt; 의 경우 자원할당 그래프&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Multiple Instance&lt;/code&gt; 의 경우 Banker's Algorithm&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;Recovery&lt;/b&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Process Termination&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;데드락에 연관된 모든 프로세스를 죽임&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Resource Preemption&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;비용을 최소화할 Victim 프로세스를 선정하여 자원을 빼앗음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;2.4. Deadlock Ignore&lt;/h4&gt;
&lt;p&gt;데드락을 시스템이 책임지지 않음&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;데드락이 매우 드물게 발생하므로, 데드락에 대한 조치 자체가 더 큰 overhead 일 수 있음&lt;/li&gt;
&lt;li&gt;만약, 시스템에서 데드락이 발생한 경우, 프로그래머가 직접 process를 죽이는 방법으로 대처&lt;/li&gt;
&lt;li&gt;UNIX, Windows 등 대부분의 OS 가 채택&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr /&gt;
&lt;h4&gt;예상 질문&lt;/h4&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;교착상태란 무엇인가를 설명한 후, 교착상태 발생 조건 4가지에 대하여 설명하세요&lt;/li&gt;
&lt;li&gt;교착상태 회피 기법인 Banker's Algorithm 에 대하여 설명하세요&lt;/li&gt;
&lt;li&gt;기아상태를 설명하는 Dining Philosophers Problem 에 대하여 설명하세요&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;참고자료&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://m.blog.naver.com/dong5053/220717510273&quot;&gt;https://m.blog.naver.com/dong5053/220717510273&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>CS/Operating System</category>
      <author>슈퍼마리호</author>
      <guid isPermaLink="true">https://hibee.tistory.com/301</guid>
      <comments>https://hibee.tistory.com/301#entry301comment</comments>
      <pubDate>Thu, 18 Apr 2019 19:17:25 +0900</pubDate>
    </item>
    <item>
      <title>[AL] 7. 최소 비용 신장 트리(MST) 알고리즘</title>
      <link>https://hibee.tistory.com/300</link>
      <description>&lt;p&gt;&amp;lt;!doctype html&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;7. 최소 비용 신장 트리(MST) 알고리즘&lt;/h2&gt;
&lt;blockquote&gt;
&lt;ol start=&quot;&quot;&gt;
&lt;li&gt;신장 트리 (Spanning Tree)&lt;/li&gt;
&lt;li&gt;최소 비용 신장 트리 (MST)&lt;/li&gt;
&lt;li&gt;Kruskal MST 알고리즘&lt;/li&gt;
&lt;li&gt;Prim MST 알고리즘&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;1. 신장 트리 (Spanning Tree)&lt;/h3&gt;
&lt;h4&gt;1.1. Spanning Tree&lt;/h4&gt;
&lt;p&gt;그래프 내의 모든 정점을 포함하는 트리&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Spanning Tree는 그래프의 &lt;code&gt;최소 연결 부분 그래프&lt;/code&gt; 이다&lt;/li&gt;
&lt;li&gt;트리의 특수한 형태로 모든 정점들이 연결되어 있고 사이클은 존재하지 않는다&lt;/li&gt;
&lt;li&gt;&lt;code&gt;n&lt;/code&gt; 개의 정점을 정확히 &lt;code&gt;n-1&lt;/code&gt; 개의 간선으로 연결한다&lt;/li&gt;
&lt;li&gt;&lt;code&gt;BFS, DFS&lt;/code&gt; 를 이용하여 그래프에서 Spanning Tree를 찾을 수 있다&lt;/li&gt;
&lt;li&gt;하나의 그래프에는 많은 Spanning Tree가 존재한다&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;spanning tree.png&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5T336/btquYXzxkEG/KB00c5Gr1pSDBTM0GEZcSk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5T336/btquYXzxkEG/KB00c5Gr1pSDBTM0GEZcSk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5T336/btquYXzxkEG/KB00c5Gr1pSDBTM0GEZcSk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5T336%2FbtquYXzxkEG%2FKB00c5Gr1pSDBTM0GEZcSk%2Fimg.png&quot; data-filename=&quot;spanning tree.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;2. 최소 비용 신장 트리 (MST, Minimum Spanning Tree)&lt;/h3&gt;
&lt;h4&gt;2.1. MST&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;Spanning Tree&lt;/code&gt; 중에서 사용된 간선들의 가중치 합이 최소인 트리&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;각 간선의 가중치가 동일하지 않을 때, 단순히 가장 적은 간선을 사용한다고 최소 비용이 아니다&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MST&lt;/code&gt; 는 간선의 가중치를 고려하여 최소 비용을 선택하는 알고리즘이다&lt;/li&gt;
&lt;li&gt;즉, 그래프에 있는 모든 정점을 선택하고 가장 적은 수의 간선과 비용으로 Spanning Tree 를 구성하는 것이다&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;3. Kruskal MST 알고리즘&lt;/h3&gt;
&lt;h4&gt;3.1. 이론&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;탐욕적인 방법(Greedy)&lt;/code&gt; 을 이용하여 가중치 그래프의 모든 정점을 최소 비용으로 연결하는 방법&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;MST 가 &lt;code&gt;최소 비용의 간선으로 구성됨&lt;/code&gt; , &lt;code&gt;사이클을 포함하지 않음&lt;/code&gt; 의 조건에 근거하여 각 단계에서 사이클을 이루지 않는 최소 비용 간선을 선택한다&lt;/li&gt;
&lt;li&gt;간선 선택을 기반으로 하는 알고리즘이다&lt;/li&gt;
&lt;li&gt;이전 단계에서 만들어진 신장 트리와는 상관없이 무조건 최소 간선만을 선택하는 방법이다&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;3.2. 과정&lt;/h4&gt;
&lt;ol start=&quot;&quot;&gt;
&lt;li&gt;
&lt;p&gt;그래프의 간선들을 가중치의 오름차순으로 정렬한다&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;정렬된 간선 리스트에서 순서대로 사이클을 형성하지 않는 간선을 선택한다&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;즉, 가장 낮은 가중치를 먼저 선택한다&lt;/li&gt;
&lt;li&gt;사이클을 형성하는 간선을 제외한다&lt;/li&gt;
&lt;li&gt;해당 간선을 현재의 MST의 집합에 추가한다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;주의할점&lt;/b&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;간선을 추가할 때 사이클이 생성되는지를 체크해야함&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;새로운 간선이 이미 다른 경로에 의해 연결되어 있는 정점들을 연결할 때 사이클을 형성함&lt;/li&gt;
&lt;li&gt;즉, 추가할 때 새로운 간선의 양끝 정점이 같은 집합에 속해 있으면 사이클이 형성됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://hibee.tistory.com/298&quot;&gt;Union-Find 알고리즘&lt;/a&gt;을 이용하여 사이클 생성 여부를 확인할 수 있다!&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;시간 복잡도&lt;/b&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Union-Find 알고리즘을 이용하면 Kruskal 알고리즘의 시간 복잡도는 간선들을 정렬하는 시간에 좌우된다. 즉, 간선 N개를 효율적으로 정렬한다면 &lt;code&gt;O(N logN)&lt;/code&gt; 의 시간 복잡도를 갖는다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;3.3. 소스 코드 (C++)&lt;/h4&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;// Krusal
typedef struct kruskal {
    int from,to,val;
} Edge;

bool comp(Edge e1, Edge e2){
    return e1.val &amp;lt; e2.val;
}

class Kruskal {
private:
    int parent[MAX+1];
    int res;
    vector&amp;lt;Edge&amp;gt; edge;
public:
    // 생성자
    Kruskal(){
        for(int i=1; i&amp;lt;=MAX; i++){
            parent[i] = i;
        }
        
        go();
    }
    
    // Union
    void merge(int u,int v){
        u = find(u);
        v = find(v);
        
        if(u == v) return;
        
        parent[u] = v;
    }
    
    // Find
    int find(int u){
        if(parent[u] == u) return u;
        
        else return parent[u] = find(parent[u]);
    }
    
    // GO
    void go(){
        int V,E;
        
        cin &amp;gt;&amp;gt; V &amp;gt;&amp;gt; E;
        
        // 간선의 정보 입력
        for(int i=0; i&amp;lt;E; i++){
            Edge e;
            cin &amp;gt;&amp;gt; e.from &amp;gt;&amp;gt; e.to &amp;gt;&amp;gt; e.val;
            edge.push_back(e);
        }
        
        // 간선을 가중치로 오름차순 정렬
        sort(edge.begin(),edge.end(),comp);
        
        for(int i=0; i&amp;lt;E; i++){
            // 두 정점이 사이클을 형성하지 않는다면
            if(find(edge[i].from) != find(edge[i].to)){
                // 가중치값 더해줌
                res += edge[i].val;
                
                // MST 형성
                merge(edge[i].from, edge[i].to);
            }
        }
        
        cout &amp;lt;&amp;lt; res &amp;lt;&amp;lt; &quot;\n&quot;;
    }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;4. Prim MST 알고리즘&lt;/h3&gt;
&lt;h4&gt;4.1. 이론&lt;/h4&gt;
&lt;p&gt;시작 정점에서부터 출발하여 신장트리 집합을 단계적으로 &lt;code&gt;확장&lt;/code&gt; 해나가는 방법&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;4.2. 과정&lt;/h4&gt;
&lt;ol start=&quot;&quot;&gt;
&lt;li&gt;
&lt;p&gt;시작 단계에서는 시작 정점만이 MST 에 포함된다&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;앞 단계에서 만들어진 MST 집합에 인접한 정점들 중에서 최소 간선으로 연결된 정점을 선택하여 트리를 확장한다&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;즉, 가장 낮은 가중치를 먼저 선택한다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;위의 과정을 트리가 &lt;code&gt;N-1&lt;/code&gt; 개의 간선을 가질 때까지 반복한다&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;시간 복잡도&lt;/b&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;1차 반복문이 정점의 수인 n만큼 반복하고, 2차 반복문이 n번 반복된다. 따라서 Prim 알고리즘은 &lt;code&gt;O(N^2)&lt;/code&gt; 의 시간 복잡도를 갖는다. 만약, 우선순위 큐를 사용한다면 &lt;code&gt;O(E logV)&lt;/code&gt; 의 시간 복잡도를 갖는다.&lt;/p&gt;
&lt;p&gt;따라서 그래프 내의 간선의 숫자가 적은 &lt;code&gt;희소 그래프(Sparse Graph)&lt;/code&gt; 의 경우 &lt;code&gt;Kruskal 알고리즘&lt;/code&gt; 이 유리하고, 그래프 내의 간선의 숫자가 많은 &lt;code&gt;밀집 그래프(Dense Graph)&lt;/code&gt; 의 경우 &lt;code&gt;Prim 알고리즘&lt;/code&gt; 이 유리하다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;4.3. 소스 코드 (C++)&lt;/h4&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;// Prim
typedef pair&amp;lt;int, int&amp;gt; pii;

class Prim {
private:
    bool visited[MAX+1];
    vector&amp;lt;pii&amp;gt; adj[MAX];
public:
    Prim(){
        memset(visited, false, sizeof(visited));
        
        go();
    }
    
    int prim(int start){
        int res = 0;
        visited[start] = true;
        
        // 우선순위 큐
        priority_queue&amp;lt;pii, vector&amp;lt;pii&amp;gt;, greater&amp;lt;pii&amp;gt;&amp;gt; pq;
        
        // 시작정점의 간선들 삽입
        for(int i=0; i&amp;lt;adj[start].size(); i++){
            pq.push(pii(adj[start][i].first ,adj[start][i].second));
        }
        
        while(!pq.empty()){
            int curr = pq.top().first;
            int cost = pq.top().second;
            pq.pop();
            
            if(!visited[curr]){
                visited[curr] = true;
                res += cost;
                
                for(int i=0; i&amp;lt;adj[curr].size(); i++){
                    pq.push(pii(adj[curr][i].first ,adj[curr][i].second));
                }
            }
        }
        
        return res;
    }
    
    void go(){
        int V,E;
        
        cin &amp;gt;&amp;gt; V &amp;gt;&amp;gt; E;
        
        // 간선의 정보 입력
        for(int i=0; i&amp;lt;E; i++){
            int from, to, val;
            
            cin &amp;gt;&amp;gt; from &amp;gt;&amp;gt; to &amp;gt;&amp;gt; val;
            
            adj[from].push_back(pii(to,val));
            adj[to].push_back(pii(from,val));
        }
        
        cout &amp;lt;&amp;lt; prim(1) &amp;lt;&amp;lt; &quot;\n&quot;;
    }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr /&gt;
&lt;h4&gt;참고 자료&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://gmlwjd9405.github.io/2018/08/29/algorithm-kruskal-mst.html&quot;&gt;Kruskal Algorithm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gmlwjd9405.github.io/2018/08/30/algorithm-prim-mst.html&quot;&gt;Prim Algorithm&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.crocus.co.kr/733?category=209527&quot;&gt;https://www.crocus.co.kr/733?category=209527&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>CS/Algorithm</category>
      <author>슈퍼마리호</author>
      <guid isPermaLink="true">https://hibee.tistory.com/300</guid>
      <comments>https://hibee.tistory.com/300#entry300comment</comments>
      <pubDate>Wed, 17 Apr 2019 20:09:42 +0900</pubDate>
    </item>
    <item>
      <title>[DP] 1. 객체 지향 프로그래밍 (OOP)</title>
      <link>https://hibee.tistory.com/299</link>
      <description>&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;1. 객체 지향 프로그래밍&lt;/h2&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;객체 지향 프로그래밍 (OOP)&lt;/li&gt;
&lt;li&gt;OOP 특징&lt;/li&gt;
&lt;li&gt;오버로딩과 오버라이딩&lt;/li&gt;
&lt;li&gt;추상클래스와 인터페이스&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;1. 객체 지향 프로그래밍 (OOP)&lt;/h3&gt;
&lt;h4&gt;1.1. OOP (Object Oriented Programming)&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;OOP(객체 지향 프로그래밍)&lt;/code&gt; 이전의 프로그래밍을 살펴보면, 컴퓨터가 사고하는대로 프로그래밍을 하는 &lt;code&gt;컴퓨터 중심적 패러다임&lt;/code&gt; 이었다. 하지만, 객체 지향 프로그래밍이란 &lt;code&gt;인간 중심적 패러다임&lt;/code&gt; 이라고 할 수 있다. 즉, 현실 세계를 프로그래밍으로 옮겨와 프로그래밍하는 것을 말한다. 현실 세계의 사물들을 객체라고 보고, 그 객체로부터 개발하고자 하는 애플리케이션에서 필요한 특징들을 뽑아와 프로그래밍 하는 것이다.&lt;/p&gt;
&lt;h4&gt;1.2. 클래스 (Clsss)&lt;/h4&gt;
&lt;p&gt;연관되어 있는 변수와 메서드의 집합이다. 객체를 만들어 내기 위한 설계도 혹은 틀이라 표현할 수 있다.&lt;/p&gt;
&lt;h4&gt;1.3. 객체 (Object)&lt;/h4&gt;
&lt;p&gt;소프트웨어 세계에 구현할 대상이다. 클래스에 선언된 모양 그대로 생선된 실체로, &lt;code&gt;클래스의 인스턴스&lt;/code&gt; 라고도 부른다. 객체는 모든 인스턴스를 대표하는 포괄적인 의미를 갖는다.&lt;/p&gt;
&lt;h4&gt;1.4. 인스턴스 (Instance)&lt;/h4&gt;
&lt;p&gt;클래스를 바탕으로 소프트웨어에 구현된 구체적인 실체이다. 즉, 객체를 소프트웨어에 실체화 하면 그것을 인스턴스라고 부른다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;인스턴스는 객체에 포한된다고 볼 수 있다&lt;/li&gt;
&lt;li&gt;OOP 관점에서 객체가 메모리에 할당되어 실제 사용될 때 &lt;code&gt;인스턴스&lt;/code&gt; 라고 부른다&lt;/li&gt;
&lt;li&gt;인스턴스는 어떤 원본(추상적인 개념)으로부터 생성된 &lt;code&gt;복제본&lt;/code&gt; 을 의미한다&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;2. OOP 특징&lt;/h3&gt;
&lt;h4&gt;2.1. 추상화 (Abstraction)&lt;/h4&gt;
&lt;p&gt;어떤 영역에서 필요로 하는 속성이나 행동을 추출하는 작업&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;사물들의 공통된 특징, 즉 &lt;code&gt;추상적 특징&lt;/code&gt; 을 파악해 인식의 대상으로 삼는 행위&lt;/li&gt;
&lt;li&gt;구체적인 사물들의 공통적인 특징을 파악해서 이를 하나의 &lt;code&gt;개념(집합)&lt;/code&gt; 으로 다루는 수단&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;2.2. 캡슐화 (Encapsulation)&lt;/h4&gt;
&lt;p&gt;캡슐화는 낮은 결합도 를 유지할 수 있도록 해주는 객체지향 설계 원리이다&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;캡슐화는 &lt;code&gt;정보 은닉&lt;/code&gt; 을 통해 높은 응집도와 낮은 결합도를 갖도록 해준다&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;b&gt;정보 은닉 (Information Hiding)&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;필요가 없는 정보는 외부에서 접근하지 못하도록 제한하는 것&lt;/li&gt;
&lt;li&gt;&lt;code&gt;private&lt;/code&gt; 키워드&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;응집도 (Cohesion)&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;클래스나 모듈 안의 요소들이 얼마나 밀접하게 관련되어 있는지&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;결합도 (Coupling)&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;어떤 기능을 실행하는 데 다른 클래스나 모듈들에 얼마나 의존적인지&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h4&gt;2.3. 일반화 (Generalization)&lt;/h4&gt;
&lt;p&gt;일반화는 여러 개체들이 가진 공통된 특성을 부각시켜 하나의 개념이나 법칙으로 성립시키는 과정이다&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;일반화 관계는 객체지향 프로그래밍 관계에서 &lt;code&gt;상속 관계&lt;/code&gt; 라고 한다&lt;/li&gt;
&lt;li&gt;따라서 속성이나 기능의 재사용만 강조해서 사용하는 경우가 많다&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;b&gt;일반화는 또 다른 캡슐화&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;일반화 관계는 자식 클래스를 외부로부터 은닉하는 캡슐화의 일종이다&lt;/li&gt;
&lt;li&gt;즉, 자식 클래스 자체를 캡슐화 하는 것으로 확장된다&lt;/li&gt;
&lt;li&gt;서브 클래스의 캡슐화는 &lt;code&gt;외부 클라이언트&lt;/code&gt; 가 개별적인 클래스들과 무관하게 프로그래밍을 할 수 있게 한다&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h4&gt;2.4. 다형성 (Polymorphism)&lt;/h4&gt;
&lt;p&gt;다형성은 서로 다른 클래스의 객체가 &lt;code&gt;같은 메시지&lt;/code&gt; 를 받았을 때, &lt;code&gt;각자의 방식&lt;/code&gt; 으로 동작하는 능력이다&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;다형성이 상속과 연계되어 동작하면 매우 효과적이다&lt;/li&gt;
&lt;li&gt;다형성과 일반화 관계는 코드를 간결하게 할 뿐 아니라 변화에도 유연하게 대처할 수 있게한다&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;scala&quot;&gt;&lt;code&gt;// 부모 클래스
public abstract class Pet {
  public abstract void talk();
}

// 자식 클래스
public class Cat extends Pet {
  public void talk(){ System.out.println(&quot;야옹&quot;); }
}
public class Dog extends Pet {
  public void talk(){ System.out.println(&quot;멍멍&quot;); }
}
public class Parrot extends Pet {
  public void talk(){ System.out.println(&quot;안녕&quot;); }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;3. 오버로딩과 오버라이딩&lt;/h3&gt;
&lt;h4&gt;3.1. 오버로딩 (Overloading)&lt;/h4&gt;
&lt;p&gt;두 메서드가 같은 이름을 갖고 있으나, 인자의 수나 자료형이 다른 경우를 말한다&lt;/p&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;public double getArea(Circle c) { }
public double getArea(Circle c1, Circle c2) { }
public double getArea(Square s) { }
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;3.2. 오버라이딩 (Overriding)&lt;/h4&gt;
&lt;p&gt;상위 클래스의 메서드와 이름의 용례(signature)가 같은 함수를 하위 클래스에 재정의 하는 것을 말한다&lt;/p&gt;
&lt;pre class=&quot;scala&quot;&gt;&lt;code&gt;public abstract class Shape {
  public void print() { System.out.println(&quot;Shape&quot;); }
}

public class Circle extends Shape {
  @Override
  public void print() { System.out.println(&quot;Circle&quot;); }
}

public class Square extends Shape {
  @Override
  public void print() { System.out.println(&quot;Square&quot;); }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;4. 추상클래스와 인터페이스&lt;/h3&gt;
&lt;h4&gt;4.1. 추상 클래스 (Abstract Class)&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;abstract&lt;/code&gt; 키워드로 선언된 클래스를 뜻하며, 하나 이상의 추상 메소드를 가지고 있다면 반드시 추상 클래스로 선언해야한다.&lt;/p&gt;
&lt;pre class=&quot;scala&quot;&gt;&lt;code&gt;abstract class Shape {
  Shape() { }
  void edit() { }
  abstract public void draw();
}

class Circle extends Shape {
  public void draw() { System.out.println(&quot;Circle&quot;); }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;4.2. 인터페이스 (Interface)&lt;/h4&gt;
&lt;p&gt;추상 메소드와 상수만을 포함하며, &lt;code&gt;interface&lt;/code&gt; 키워드를 사용하여 선언한다. 상속받을 서브 클래스에게 구현할 메소드의 원형을 모두 알려주어, 클래스가 자신의 목적에 맞게 메소드를 구현하도록 한다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;오직 상수 필드와 추상 메소드로 구성됨&lt;/li&gt;
&lt;li&gt;모든 메소드는 추상 메소드로서, abstract public 생략 가능&lt;/li&gt;
&lt;li&gt;상수는 public static final 이며, 생략 가능&lt;/li&gt;
&lt;li&gt;인터페이스를 상속받아 새로운 인터페이스를 만들 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;interface Phone {
  int BUTTONS = 20;
  void sendCall();	// 추상 메소드
  abstract public void receiveCall();	// 추상 메소드
}

class IphoneX implements Phone {
  // Phone의 모든 추상 메소드를 구현한다
  public void sendCall() { }
  public void receiveCall() { }
  // 추가적으로 다른 메소드를 작성할 수 있다
  public void callSiri() { }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;4.3. 추상 클래스와 인터페이스&lt;/h4&gt;
&lt;p&gt;&lt;b&gt;공통점&lt;/b&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;인스턴스(객체) 를 생성할 수 없다&lt;/li&gt;
&lt;li&gt;선언만 있고 구현 내용은 없다&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;b&gt;차이점&lt;/b&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;서로 다른 목적을 가지고 있다&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;추상클래스 : 자식 클래스가 추상 메소드를 구체화하여 그 기능을 확장&lt;/li&gt;
&lt;li&gt;인터페이스 : 서로 관련이 없는 클래스에서 공통적으로 사용하지만 각각 기능을 구현할 때&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;추상 클래스는 클래스이지만 인터페이스는 클래스가 아니다&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;추상 클래스는 단일 상속이지만 인터페이스는 다중 상속이 가능하다&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;추상 클래스는 &lt;code&gt;is a kind of&lt;/code&gt; , 인터페이스는 &lt;code&gt;can do this&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;추상클래스 : Appliances - TV, Refrigerator&lt;/li&gt;
&lt;li&gt;인터페이스 : Flyalbe - Plane, Bird&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr /&gt;
&lt;h4&gt;참고 자료&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://gmlwjd9405.github.io/2018/07/05/oop-features.html&quot;&gt;https://gmlwjd9405.github.io/2018/07/05/oop-features.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>CS/Design Pattern</category>
      <author>슈퍼마리호</author>
      <guid isPermaLink="true">https://hibee.tistory.com/299</guid>
      <comments>https://hibee.tistory.com/299#entry299comment</comments>
      <pubDate>Fri, 12 Apr 2019 19:46:20 +0900</pubDate>
    </item>
    <item>
      <title>[AL] 6. Union-Find 알고리즘</title>
      <link>https://hibee.tistory.com/298</link>
      <description>&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;6. Union-Find 알고리즘&lt;/h2&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Union-Find&lt;/li&gt;
&lt;li&gt;Union-Find 구현&lt;/li&gt;
&lt;li&gt;최적화 (Optimization)&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;1. Union-Find&lt;/h3&gt;
&lt;h4&gt;1.1. Union-Find 란?&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;서로소 집합(Disjoint Set)&lt;/code&gt; 라고 불리며, &lt;code&gt;Union(x,y)&lt;/code&gt; 과 &lt;code&gt;Find(x)&lt;/code&gt; 연산을 수행한다&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Union(x,y)&lt;/code&gt; 를 수행하면 x와 y는 같은 집합에 속하게 되며, &lt;code&gt;Find(x)&lt;/code&gt; 와 &lt;code&gt;Find(y)&lt;/code&gt; 는 x, y 가 같은 집합에 속할 때만 같은 값을 가진다. 따라서, 전체 요소들을 서서히 묶어나가는 상황에서 유용하게 사용할 수 있는 자료구조이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;1.2. 원리&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;배열을 이용해서 &lt;code&gt;Tree&lt;/code&gt; 자료구조를 만들어 구현하며, 최상단 노드를 &lt;code&gt;Root&lt;/code&gt; 노드로 하여 집합을 구분한다&lt;/li&gt;
&lt;li&gt;주어진 두 원소 또는 집합을 합하는 &lt;code&gt;Union&lt;/code&gt; 부분과 원소가 어떤 집합에 있는지 찾는 &lt;code&gt;Find&lt;/code&gt; 부분으로 이루어져있다&lt;/li&gt;
&lt;li&gt;&lt;code&gt;parent[i]&lt;/code&gt; : 원소 &lt;code&gt;i&lt;/code&gt; 의 부모 노드를 가지고 있는 배열, 즉 &lt;code&gt;parent[i]&lt;/code&gt; 는 &lt;code&gt;i&lt;/code&gt; 의 부모노드&lt;/li&gt;
&lt;li&gt;&lt;code&gt;(1,2) (2,5) (5,6) (5,8) (3,4)&lt;/code&gt; 수행 시, 아래와 같은 결과를 보인다&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;union-find.png&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwFVF3/btqt4y98Nzt/LawTBcPJCpNrVmaFa84p2K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwFVF3/btqt4y98Nzt/LawTBcPJCpNrVmaFa84p2K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwFVF3/btqt4y98Nzt/LawTBcPJCpNrVmaFa84p2K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwFVF3%2Fbtqt4y98Nzt%2FLawTBcPJCpNrVmaFa84p2K%2Fimg.png&quot; data-filename=&quot;union-find.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;2. Union-Find 구현&lt;/h3&gt;
&lt;h4&gt;2.1. 초기화&lt;/h4&gt;
&lt;p&gt;N 개의 원소가 각각의 집합에 포함되어 있도록 초기화 한다&lt;/p&gt;
&lt;pre class=&quot;qml&quot;&gt;&lt;code&gt;void Set(){
    for(int i=1; i&amp;lt;=SIZE; i++){
        parent[i] = i;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;2.2. Union&lt;/h4&gt;
&lt;p&gt;두 원소 u, v 가 주어질 때, 이들이 속한 두 집합을 하나로 합친다&lt;/p&gt;
&lt;pre class=&quot;gradle&quot;&gt;&lt;code&gt;// u와 v의 원소가 들어오면 각각의 Root 노드를 찾아주고
// 두 root노드가 같지 않다면, u의 root 노드를 v로 설정해준다
void Union(int u,int v){
    
    u = Find(u);
    v = Find(v);
    
    // root가 같다면 이미 같은 트리
    if(u == v) return;
  
    // u의 루트가 v가 되도록
    parent[u] = v;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;2.3. Find&lt;/h4&gt;
&lt;p&gt;어떤 원소 u 가 주어질 때, 이 원소가 속한 집합의 Root 를 반환한다&lt;/p&gt;
&lt;pre class=&quot;mel&quot;&gt;&lt;code&gt;int Find(int u){
    
    // Root인 경우 x를 반환
    if(parent[u] == u){
        return u;
    }
    
    // 아니면 Root를 찾아감
    return parent[u] = Find(parent[u]);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;3. 최적화 (Optimization)&lt;/h3&gt;
&lt;p&gt;이와 같이 트리로 구현하는 방법에는 큰 문제점이 발생할 수 있다.&lt;/p&gt;
&lt;p&gt;바로 최악의 경우 완전히 비대칭적인 트리, 즉 연결 리스트 형태가 될 수 있다는 것이다. 만약 트리의 모양이 일자로 나온다면 Union 연산과 Find 연산의 수행시간이 &lt;code&gt;O(N)&lt;/code&gt; 이 되버려 배열로 구현했을 때 보다도 효율이 나빠지게 된다.&lt;/p&gt;
&lt;p&gt;이 문제는 두 트리를 합칠 때, &lt;code&gt;항상 높이가 더 낮은 트리를 높은 트리 밑에 넣음&lt;/code&gt; 으로서 해결이 가능하다. 이렇게 되면 트리의 높이가 크게 높아지는 현상을 방지할 수 있다. 이러한 최적화를 &lt;code&gt;union-by-rank&lt;/code&gt; 라 하며, 여기서 rank 는 해당 트리의 높이를 저장한다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;b&gt;시간 복잡도&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;일단 트리로 압축시켰기 때문에 &lt;code&gt;find&lt;/code&gt; 시간복잡도는 &lt;code&gt;O(logN)&lt;/code&gt; 을 갖게된다&lt;/p&gt;
&lt;p&gt;또한 &lt;code&gt;union&lt;/code&gt; 도 &lt;code&gt;find&lt;/code&gt; 의 지배를 받기에 &lt;code&gt;O(logN)&lt;/code&gt; 을 갖게 된다&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;사실 실제 시간 복잡도는 O( (N)) 이라고 한다.  는 애커만 함수를 뜻하며 N이 2^65536 일때, 함수 값이 5가 된다. 따라서 그냥 상수로 봐도 무방하다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;3.1. 최적화 소스코드&lt;/h4&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
using namespace std;

const int SIZE = 100;

int parent[SIZE+1];
int level[SIZE+1];

void Set(){
    for(int i=1; i&amp;lt;=SIZE; i++){
        parent[i] = i;
        level[i] = 1;
    }
}

int Find(int u){
    
    // Root인 경우 x를 반환
    if(parent[u] == u){
        return u;
    }
    
    // 아니면 Root를 찾아감
    return parent[u] = Find(parent[u]);
}

// u와 v의 원소가 들어오면 각각의 Root 노드를 찾아주고
// 두 root노드가 같지 않다면, u의 root 노드를 v로 설정해준다
void Union(int u,int v){
    
    u = Find(u);
    v = Find(v);
    
    // root가 같다면 이미 같은 트리
    if(u == v) return;
        
    // v에 더 큰 값을 배치시키기 위함
    if(level[u] &amp;gt; level[v])
        swap(u, v);
        
    // u의 루트가 v가 되도록
    parent[u] = v;
    
    // u와 v의 깊이가 같을 때 v의 깊이를 늘려준다
    if(level[u] == level[v])
        ++level[v];
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr /&gt;
&lt;h4&gt;참고 자료&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.crocus.co.kr/683&quot;&gt;https://www.crocus.co.kr/683&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>CS/Algorithm</category>
      <author>슈퍼마리호</author>
      <guid isPermaLink="true">https://hibee.tistory.com/298</guid>
      <comments>https://hibee.tistory.com/298#entry298comment</comments>
      <pubDate>Fri, 5 Apr 2019 00:04:44 +0900</pubDate>
    </item>
  </channel>
</rss>