<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>tae0__.log</title>
        <link>https://velog.io/</link>
        <description>초보 개발자.. 매일 공부한 거 적는게 목표</description>
        <lastBuildDate>Sun, 07 Apr 2024 05:42:08 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>tae0__.log</title>
            <url>https://velog.velcdn.com/images/tae0__/profile/435f9dfe-f033-4052-92ab-7e7748b025e8/image.JPG</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. tae0__.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/tae0__" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[알고리즘] 정렬 알고리즘 (Sorting Algorithm) #2]]></title>
            <link>https://velog.io/@tae0__/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%A0%95%EB%A0%AC-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-Sorting-Algorithm-2</link>
            <guid>https://velog.io/@tae0__/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%A0%95%EB%A0%AC-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-Sorting-Algorithm-2</guid>
            <pubDate>Sun, 07 Apr 2024 05:42:08 GMT</pubDate>
            <description><![CDATA[<h2 id="✅쉘-정렬-shell-sort">✅쉘 정렬 (Shell Sort)</h2>
<ul>
<li>Donald Shell에 의해 삽입 정렬의 결점을 보안하기 위해 고안된 정렬방식</li>
<li>입력 배열을 부분 배열로 나눠 정렬하는 과정을 부분 배열의 개수를 바꾸며 이 과정을 여러번 거치는 방식</li>
<li>부분 배열의 개수를 정하기 위해 h를 설정</li>
<li>아래는 간격이 4인 쉘 정렬을 C++로 작성한 코드이다<pre><code class="language-cpp">void shellsort(int arr[], int n){
  int h, i, j, val;
  h = 1;
  do {
      h = 3 * h + 1;
  } while(h &lt; n);
  do {
      h = h / 3;
      for(i = h; i &lt; n; i++){
          val = arr[i];
          j = i;
          while (arr[j - h] &gt; val) {
              arr[j] = arr[j - h];
              j = j - h;
              if (j &lt; h - 1) {
                  break;
              }
          }
          arr[j] = val;
      }
  } while(h &gt; 1);
}</code></pre>
</li>
<li>i, j, val 등 상수 크기 메모리를 사용하므로 <strong>제자리 정렬</strong></li>
<li>크기가 같은 원소의 상대적 위치가 바뀌는 <strong>불안정한 정렬</strong></li>
</ul>
<h2 id="✅퀵-정렬-quick-sort">✅퀵 정렬 (Quick Sort)</h2>
<ul>
<li><p><strong>분할 정복 (divide and conquer) 방식</strong>의 정렬 알고리즘</p>
<ul>
<li>분할 정복 (divide and conquer): 해결할 수 없는 문제를 작은 문제로 분할해서 해결하는 방식</li>
</ul>
</li>
<li><p><strong>분할 원소 (partitioning element)</strong> 사용</p>
</li>
<li><p>배열의 양 끝으로부터 배열의 중심을 향해 동시 검색</p>
<ol>
<li>좌측 -&gt; 우측: 분할 원소보다 큰 원소를 탐색, 우측 -&gt; 좌측: 분할 원소보다 작은 원소를 탐색 후 서로 교환<ol start="2">
<li>반복하다 둘이 만나게 될 경우 탐색 종료 후 그 자리에 분할 원소 대입</li>
</ol>
</li>
</ol>
</li>
<li><p>아래는 분할 원소인 partition을 구하는 것을 C++로 작성한 코드이다</p>
<pre><code class="language-cpp">int partition(int arr[], int left, int right) {
  int part, val;
  part = left;
  val = arr[part];
  do {
      do {
          left++;
      } while (arr[left] &lt; val);

      do {
          right--;
      } while (arr[right] &gt; val);

      if (left &lt; right) {
          swap(&amp;arr[left], &amp;arr[right]);
      }
      else {
          break;
      }
  } while(1);
  arr[part] = arr[right];
  arr[right] = val;
  return right;
}</code></pre>
</li>
<li><p>아래는 퀵 정렬을 수행하는 함수를 순환 알고리즘(재귀)을 이용해 C++로 작성한 코드이다</p>
<pre><code class="language-cpp">void quicksort(int arr[], int left, int right) {
  int k;
  if(right &gt; left) {
      k = partition(arr, left, right + 1);
      quicksort(arr, left, k - 1);
      quicksort(arr, k + 1, right);
  }
}</code></pre>
</li>
<li><p>오름차순 또는 내림차순으로 정렬되어 있을 때가 최악의 경우</p>
</li>
<li><p>1번의 quicksort 호출에 의해 분할 원소 1개가 제자리를 잡고 부분 배열이 치우쳐질 경우 최악의 시간 복잡도를 갖음</p>
</li>
<li><p>최악의 시간 복잡도는 <strong>O(n^2)</strong></p>
</li>
<li><p><strong>제자리 정렬</strong>이며, 크기가 같은 원소의 상대적 위치가 바뀌는 <strong>불안정한 정렬</strong></p>
</li>
</ul>
<blockquote>
<img src = "https://velog.velcdn.com/images/tae0__/post/d57ee435-b522-46b3-b583-0f2b4dbbdf06/image.png" >
</blockquote>
<p><a href="https://good-potato.tistory.com/40">사진 출처</a></p>
<h2 id="📖참고자료">📖참고자료</h2>
<ul>
<li>대학교 ppt 교안</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[DB] 데이터베이스 시스템 (DBS)]]></title>
            <link>https://velog.io/@tae0__/DB-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EC%8B%9C%EC%8A%A4%ED%85%9C-DBS</link>
            <guid>https://velog.io/@tae0__/DB-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EC%8B%9C%EC%8A%A4%ED%85%9C-DBS</guid>
            <pubDate>Sat, 06 Apr 2024 07:44:54 GMT</pubDate>
            <description><![CDATA[<h2 id="✅데이터베이스의-구조">✅데이터베이스의 구조</h2>
<h3 id="📌스키마와-인스턴스">📌스키마와 인스턴스</h3>
<ul>
<li><strong>스키마 (Schema)</strong>: 데이터베이스에 저장되는 데이터 구조와 제약 조건을 정의한 것</li>
<li><strong>인스턴스 (Instance)</strong>: 스키마에 따라 데이터베이스에 실제로 저장된 값</li>
</ul>
<h3 id="📌3단계-데이터베이스-구조">📌3단계 데이터베이스 구조</h3>
<ul>
<li>데이터베이스를 쉽게 이해하고 이욯할 수 있도록 하나의 데이터베이스를 관점에 따라 3단계로 나눔<ol>
<li><strong>외부 단계 (External Level)</strong>: 개별 사용자 관점<ol start="2">
<li><strong>개념 단계 (Conceptual Level)</strong>: 조직 전체의 관점</li>
</ol>
</li>
<li><strong>내부 단계 (Internal Level)</strong>: 물리적인 저장 장치의 관점</li>
</ol>
</li>
<li>각 단계별 다른 <strong>추상화 (abstraction)</strong> 제공</li>
<li>내부에서 외부 단계로 갈수록 추상화 레벨 높아짐<img src = "https://velog.velcdn.com/images/tae0__/post/b582d178-60be-4057-98ff-dcfc0ac4cced/image.png" width = "60%" height = "60%">

</li>
</ul>
<h4 id="외부-단계-external-level">외부 단계 (External Level)</h4>
<ul>
<li>데이터베이스를 <strong>개별 사용자의 관점</strong>에서 이해하고 표현하는 단계</li>
<li>하나의 데이터베이스에 여러 개의 외부 스키마가 존재 가능</li>
<li><strong>외부 스키마 (External Schema)</strong><ol>
<li>외부 단계에서 사용자에게 필요한 데이터베이스를 정의한 것<ol start="2">
<li>각 사용자가 생각하는 데이터베이스의 모습(논리적 구조)으로 사용자마다 다름</li>
<li><strong>서브 스키마 (Sub Schema)</strong>라고도 표현</li>
</ol>
</li>
</ol>
</li>
</ul>
<h4 id="개념-단계-conceptual-level">개념 단계 (Conceptual Level)</h4>
<ul>
<li>데이터베이스를 <strong>조직 전체의 관점</strong>에서 이해하고 표현하는 단계</li>
<li>하나의 데이터베이스에 하나의 개념 스키마만 존재</li>
<li><strong>개념 스키마 (Conceptual Schema)</strong><ol>
<li>개념 단계에서 데이터베이스 전체의 논리적 구조를 정의한 것<ol start="2">
<li>조직 전체의 관점에서 생각하는 데이터베이스의 모습
ex) 전체 데이터베이스에 어떤 데이터가 저장되는지, 데이터들 간에 어떤 관계가 존재하고 어떤 제약조건이 있는지, 데이터에 대한 보안 정책 및 접근 권한에 대한 정의</li>
</ol>
</li>
</ol>
</li>
</ul>
<h4 id="내부-단계-internal-level">내부 단계 (Internal Level)</h4>
<ul>
<li>데이터베이스를 <strong>저장 장치의 관점</strong>에서 이해하고 표현하는 단계</li>
<li>하나의 데이터네이스에 하나의 내부 스키마만 존재</li>
<li><strong>내부 스키마 (Internal Schema)</strong><ol>
<li>저장 장치에 전체 데이터베이스가 실제로 저장되는 방법을 정의<ol start="2">
<li>물리적 저장 구조를 정의
ex) 레코드 구조, 필드 크기, 레코드 접근 경로 등..</li>
</ol>
</li>
</ol>
</li>
</ul>
<img src = "https://velog.velcdn.com/images/tae0__/post/86b206d6-fecd-4923-bbee-d0e0c96562ee/image.png" width = 80%>

<h3 id="📌3단계-데이터베이스-구조의-사상-또는-매핑">📌3단계 데이터베이스 구조의 사상 또는 매핑</h3>
<h4 id="스키마-사이-대응-관계">스키마 사이 대응 관계</h4>
<ul>
<li>외부/개념 사상: 외부 - 개념 스키마의 대응 관계: <strong>응용 인터페이스 (Application Interface)</strong></li>
<li>개념/내부 사상: 개념 - 내부 스키마의 대응 관계: <strong>저장 인터페이스 (Storage Interface)</strong></li>
<li>데이터베이스를 3단계 구조로 나누고 단계별로 스키마 유지, 스키마 사이 대응 관계를 정의하는 궁극적 목적 =&gt; <strong>데이터 독립성의 실현</strong></li>
</ul>
<h4 id="데이터-독립성-data-independency">데이터 독립성 (Data Independency)</h4>
<ul>
<li>하위 스키마 변경 시 상위 스키마가 영향을 받지 않는 특성</li>
<li><strong>논리적 데이터 독립성</strong><ol>
<li>개념 스키마가 변경되어도 외부 스키마 영향 X<ol start="2">
<li>개념 스키마 변경 시 외부/개념 사상만 정확히 수정하면 됨</li>
</ol>
</li>
</ol>
</li>
<li><strong>물리적 데이터 독립성</strong><ol>
<li>내부 스키마가 변경되어도 개념 스키마 영향 X<ol start="2">
<li>내부 스키마 변경 시 개념/내부 사상만 정확히 수정하면 됨</li>
</ol>
</li>
</ol>
</li>
</ul>
<h4 id="데이터-사전-data-dictionary">데이터 사전 (Data Dictionary)</h4>
<ul>
<li><strong>시스템 카탈로그 (System Catalog)</strong>라고도 함</li>
<li>데이터베이스에 저장되는 데이터에 관한 정보(메타 데이터: 데이터에 대한 데이터)를 유지하는 시스템 데이터베이스</li>
<li>정확하고 효율적인 데이터 이용을 위해 참고해야하는 <strong>스키마, 사상 정보, 다양한 제약조건</strong> 등을 저장</li>
<li>데이터베이스 관리 시스템이 스스로 생성 및 유지</li>
<li>일반 사용자도 접근 가능하지만 저장 내용만 검색 가능</li>
</ul>
<h4 id="데이터-디렉토리-data-directory">데이터 디렉토리 (Data Directory)</h4>
<ul>
<li>데이터 사전에 존재하는 데이터에 실제 접근하는 데 필요한 위치 정보를 저장하는 시스템 데이터베이스</li>
<li>일반 사용자의 접근 허용 X</li>
</ul>
<h4 id="사용자-데이터베이스-user-database">사용자 데이터베이스 (User Database)</h4>
<ul>
<li>사용자가 실제 사용하는 데이터가 저장되어있는 일반 데이터베이스</li>
</ul>
<h2 id="✅데이터베이스-사용자">✅데이터베이스 사용자</h2>
<h3 id="📌데이터베이스-사용자">📌데이터베이스 사용자</h3>
<ul>
<li>데이터베이스를 이용하기 위해 접근하는 모든 사람</li>
<li>이용 목적에 따라 데이터베이스 관리자, 최종 사용자, 응용 프로그래머로 구분<img src = "https://velog.velcdn.com/images/tae0__/post/c805b36b-d3e4-488f-9857-f4e8889943a0/image.png" width = 60% >

</li>
</ul>
<h4 id="데이터베이스-관리자-database-administrator">데이터베이스 관리자 (Database Administrator)</h4>
<ul>
<li>데이터베이스 시스템을 운영 및 관리하는 사람</li>
<li>주로 데이터 정의어, 데이터 제어어 이용</li>
</ul>
<h4 id="최종-사용자-end-user">최종 사용자 (End User)</h4>
<ul>
<li>데이터베이스에 접근해 데이터 조작 (삽입, 삭제, 수정, 검색)</li>
<li>주로 데이터 조작어 사용</li>
</ul>
<h4 id="응용-프로그래머-application-programmer">응용 프로그래머 (Application Programmer)</h4>
<ul>
<li>데이터 언어를 삽입해 응용 프로그램을 작성하는 사람</li>
<li>주로 데이터 조작어 사용</li>
</ul>
<h2 id="✅데이터-언어">✅데이터 언어</h2>
<h3 id="📌데이터-언어">📌데이터 언어</h3>
<ul>
<li>사용자 - 데이터베이스 관리 시스템 통신 수단</li>
<li>사용 목적에 따라 데이터 정의어, 데이터 조작어, 데이터 제어어로 구분<img src = "blob:https://velog.io/ad21c6d5-e631-4144-809d-e8c2b19db6ad" width = 70% >

</li>
</ul>
<h4 id="데이터-정의어-data-definition-language-ddl">데이터 정의어 (Data Definition Language; DDL)</h4>
<ul>
<li>스키마 정의, 수정, 삭제를 위해 사용</li>
</ul>
<h4 id="데이터-조작어-data-manipulation-language-dml">데이터 조작어 (Data Manipulation Language; DML)</h4>
<ul>
<li>데이터의 삽입, 삭제, 수정, 검색 등 처리를 요구하기 위해 사용</li>
<li>절차적 데이터 조작어, 비절차적 데이터 조작어로 구분<ol>
<li><strong>절차적 데이터 조작어 (Procedural DML)</strong>: 사용자가 어떤 데이터를 원하고 그 데이터를 얻기 위해 어떻게 처리해야하는지도 설명<ol start="2">
<li><strong>비절차적 데이터 조작어 (Nonprocedural DML)</strong>: 사용자가 어떤 데이터를 원하는지만 설명, 선언적 언어 (Declarative Language)라고도 함</li>
</ol>
</li>
</ol>
</li>
</ul>
<h4 id="데이터-제어어-data-control-language-dcl">데이터 제어어 (Data Control Language; DCL)</h4>
<ul>
<li>내부적으로 필요한 규칙이나 기법을 정의하기 위해 사용</li>
<li>사용 목적<ol>
<li><strong>무결성</strong>: 정확하고 유효한 데이터만 유지<ol start="2">
<li><strong>보안</strong>: 허가된 사용자에게만 권한 부여</li>
<li>회복: 장애가 발생해도 데이터 일관성 유지</li>
<li>동시성 제어: 동시 공유 지원</li>
</ol>
</li>
</ol>
</li>
</ul>
<h2 id="✅데이터베이스-관리-시스템의-구성">✅데이터베이스 관리 시스템의 구성</h2>
<h3 id="📌데이터베이스-관리-시스템">📌데이터베이스 관리 시스템</h3>
<ul>
<li>데이터베이스 관리 및 사용자 데이터 처리 요구 수행</li>
<li>주요 구성요소<ol>
<li><strong>질의 처리기 (Query Processor)</strong>: 사용자의 데이터 처리 요구를 해석 및 처리<ol start="2">
<li><strong>저장 데이터 관리자 (Stored Data Manager)</strong>: 디스크에 저장된 데이터베이스, 데이터 사전을 관리 및 접근<img src = "https://velog.velcdn.com/images/tae0__/post/759bbe19-074a-4046-9ce8-4d03d00d3210/image.png" width = 80%>

</li>
</ol>
</li>
</ol>
</li>
</ul>
<h2 id="📖참고자료">📖참고자료</h2>
<ul>
<li>대학교 ppt 교안</li>
<li>데이터베이스 개론 2판 김연희저자 </li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[DB] 데이터베이스 관리 시스템 (DBMS)]]></title>
            <link>https://velog.io/@tae0__/DB-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EA%B4%80%EB%A6%AC-%EC%8B%9C%EC%8A%A4%ED%85%9C-DBMS</link>
            <guid>https://velog.io/@tae0__/DB-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EA%B4%80%EB%A6%AC-%EC%8B%9C%EC%8A%A4%ED%85%9C-DBMS</guid>
            <pubDate>Mon, 01 Apr 2024 12:32:20 GMT</pubDate>
            <description><![CDATA[<h2 id="✅데이터베이스-관리-시스템-등장-배경">✅데이터베이스 관리 시스템 등장 배경</h2>
<h3 id="📌파일-시스템">📌파일 시스템</h3>
<ul>
<li>데이터를 파일로 관리하기 위해 파일을 생성, 삭제, 수정, 검색하는 기능을 제공하는 SW</li>
<li>응용 프로그램 마다 필요 데이터를 별도 파일로 관리
<img src="https://velog.velcdn.com/images/tae0__/post/cc8cbd71-5bbf-4691-b01c-a70970f89ef9/image.png" alt=""></li>
<li>파일 시스템의 문제점</li>
</ul>
<ol>
<li>같은 내용의 데이터가 여러 파일에 중복 저장 -&gt; <strong>데이터 중복성</strong>
&gt;&gt; 데이터의 <strong>일관성</strong>과 <strong>무결성</strong>(데이터의 정확성 보장 X)을 유지하기 어려움</li>
<li>응용 프로그램이 데이터 파일에 종속적 -&gt; <strong>데이터 종속성</strong>
&gt;&gt; 사용하는 파일의 구조를 변경하면 응용 프로그램도 함께 변경해야 함</li>
<li>데이터 파일에 대한 동시 공유, 보안, 회복기능이 부족
&gt;&gt; 데이터 중복 가능성 문제
&gt;&gt; 파일 수정 중 장애 발생 시 회복 불가</li>
</ol>
<h2 id="✅데이터베이스-관리-시스템의-정의">✅데이터베이스 관리 시스템의 정의</h2>
<h3 id="📌데이터베이스-관리-시스템-dbms">📌데이터베이스 관리 시스템 (DBMS)</h3>
<h4 id="정의">정의</h4>
<ul>
<li>파일시스템의 문제를 해결하기 위해 제시된 SW</li>
<li>필요 데이터를 데이터베이스에 통합해 저장 및 관리</li>
<li>데이터를 가진 쪽을 <strong>서버(server)</strong>, 외부에서 데이터를 요청하는 쪽을 <strong>클라이언트(client)</strong>라 칭함</li>
<li>DBMS 서버가 파일을 다루며 데이터의 일관성 유지, 복구, 동시 접근 제어 등 기능을 수행</li>
<li>데이터의 중복을 줄이고 표준화해 무결성 유지</li>
</ul>
<h4 id="데이터베이스-관리-시스템에서의-데이터-관리">데이터베이스 관리 시스템에서의 데이터 관리</h4>
<p><img src="https://velog.velcdn.com/images/tae0__/post/13de412d-3540-465f-860e-0557d69714ff/image.png" alt=""></p>
<h4 id="데이터베이스-관리-시스템의-주요-기능">데이터베이스 관리 시스템의 주요 기능</h4>
<ul>
<li><strong>정의 기능</strong>: 데이터베이스 구조를 정의하거나 수정 가능</li>
<li><strong>조작 기능</strong>: 데이터를 삽입, 삭제, 수정, 검색하는 연산 가능</li>
<li><strong>제어 기능</strong>: 데이터를 항상 정확하고 안전하게 유지 가능</li>
</ul>
<h4 id="파일-시스템과-dbms의-비교">파일 시스템과 DBMS의 비교</h4>
<img src = "https://velog.velcdn.com/images/tae0__/post/64d555d0-8b2f-426d-b6f9-c6294a7eb35c/image.png" width = 80%>

<img src = "https://velog.velcdn.com/images/tae0__/post/e3a3b6d4-6d47-4e14-9eed-bf170180b516/image.png">

<h4 id="dbms의-단점">DBMS의 단점</h4>
<ul>
<li>비용이 많이 듦<ol>
<li>운영체제와 함께 설치됨<ol start="2">
<li>DBMS 설치로 인한 구매비용 증가</li>
<li>동시 접속자 허용 수에 따라 가격 증가</li>
</ol>
</li>
</ol>
</li>
<li>백업과 회복이 복잡함<ol>
<li>데이터의 양이 많아 구조가 복잡함<ol start="2">
<li>다수의 사용자의 동시 공유로 인한 장애 발생 시 원인파악이 어려움</li>
<li>백업이 요구됨 </li>
</ol>
</li>
</ol>
</li>
<li>중앙 집중 관리로 인한 취약점이 존재<ol>
<li>모든 데이터가 데이터베이스에 통합되어 DBMS에 집중되어있음</li>
</ol>
</li>
</ul>
<h4 id="dbms의-기능">DBMS의 기능</h4>
<ul>
<li><strong>데이터 정의(Definition)</strong>: 데이터의 구조를 정의하고 구조에 대한 삭제 및 변경 기능을 수행</li>
<li><strong>데이터 조작(Manipulation)</strong>: 데이터 조작 SW가 요청하는 데이터의 삽입, 수정, 삭제 작업을 지원</li>
<li><strong>데이터 추출(Retrieval)</strong>: 사용자가 조회하는 데이터 또는 응용 프로그램의 데이터 추출</li>
<li><strong>데이터 제어(Control)</strong>: 데이터베이스 사용자를 생성하고 모니터링하며 접근 제어 (백업과 회복, 동시성 제어 등 기능 지원)</li>
</ul>
<h4 id="dbms의-발전-과정">DBMS의 발전 과정</h4>
<ul>
<li><p>1세대: 네트워크 DBMS, 계층 DBMS
  &gt; <strong>네트워크 DBMS</strong>: 데이터베이스를 그래프 형태로 구성
  ex) IDS (Integrated Data Store)
  &gt; <strong>계층 DBMS</strong>: 데이터베이스를 트리형태로 구성
  ex) IMS (Information Management System)
  <img src="https://velog.velcdn.com/images/tae0__/post/6f18a23d-198e-4cb2-8d8e-aada88342689/image.png" alt=""></p>
</li>
<li><p>2세대: 관계형 DBMS
&gt; <strong>관계형 DBMS</strong>: 데이터 베이스를 테이블 형태로 구성
ex) 오라클 (oracle), MySQL 등
<img src="https://velog.velcdn.com/images/tae0__/post/0b1c6c0f-19e7-41c0-922c-9a66e8bdd533/image.png" alt=""></p>
</li>
<li><p>3세대: 객체지향 DBMS, 객체관계 DBMS
&gt; <strong>객체지향 DBMS</strong>: 객체를 이용해 데이터베이스 구성
ex) 오투(O2), 온투스(ONTOS), 젬스톤(GemStone)
&gt; <strong>객체관계 DBMS</strong>: 객체형 DBMS + 관계형 DBMS</p>
</li>
<li><p>4세대: NoSQL, NewSQL DBMS</p>
<ol>
<li>Not only SQL</li>
<li>비정형이면서 방대한 데이터를 저장하기 적합함</li>
<li><strong>NoSQL DBMS</strong>는 비정형 데이터를 처리하는데 적합하고 확장성이 뛰어남
&gt; 안정성과 일관성 유지를 위해 복잡한 기능을 포기했으며 데이터 구조를 미리 정해두지 않는 유연성을 가짐</li>
<li><strong>NewSQL DBMS</strong>는 관계 DBMS의 장점과 NoSQL의 확장성 및 유연성을 합친 DBMS -&gt; ex) 구글 스패너 등<h2 id="📖참고자료">📖참고자료</h2>
</li>
</ol>
</li>
<li><p>MySQL로 배우는 데이터베이스 개론과 실습 저자 박우창</p>
</li>
<li><p>데이터베이스 개론 2판 저자 김연희</p>
</li>
<li><p>대학교 ppt 교안</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘] 정렬 알고리즘(Sorting Algorithm) #1]]></title>
            <link>https://velog.io/@tae0__/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-1.-%EC%84%A0%ED%83%9D-%EC%A0%95%EB%A0%ACSelection-Sort</link>
            <guid>https://velog.io/@tae0__/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-1.-%EC%84%A0%ED%83%9D-%EC%A0%95%EB%A0%ACSelection-Sort</guid>
            <pubDate>Sun, 31 Mar 2024 10:25:35 GMT</pubDate>
            <description><![CDATA[<h2 id="✅선택-정렬-selection-sort">✅선택 정렬 (Selection Sort)</h2>
<ul>
<li>가장 작은 원소부터 가장 큰 원소로 오름차순 순서대로 원소를 재배치 시키며 배열을 정렬하는 방식</li>
</ul>
<ol>
<li>정렬할 n개의 데이터가 배열 arr에 저장되어있다고 가정 </li>
<li>n개의 key 중 가장 작은 것을 찾아 첫번째 key인 arr[0]과 자리바꿈</li>
<li>남아있는 원소들 중에 가장 작은 키를 찾아 그 원소와 arr[1]의 자리를 바꿈</li>
<li>k번째 단계에서는 남아있는 (n - k + 1)개의 key 중 가장 작은 것을 찾아 arr[k - 1]과 자리바꿈</li>
<li>위 단계를 n - 1번 반복</li>
</ol>
<ul>
<li>k번째 단계에서는 항상 <strong>(n - k)회</strong>의 비교를 수행하므로, (n - 1) + (n - 2) + ... + 1 이므로 <strong>n(n - 1) / 2 의 시간 복잡도</strong>를 가진다. 따라서, 평균 및 최악의 시간 복잡도는 <strong>O(n^2)</strong>이 된다. </li>
<li>아래는 C++로 작성한 선택 정렬 함수이다.</li>
</ul>
<pre><code class="language-cpp">void selectionsort(int arr[], int n){
    int i, j, MinIndex;
    for(i = 0; i &lt; n - 1; i++){
        MinIndex = i;
        for(j = MinIndex + 1; j &lt; n; j++){
            if(arr[MinIndex] &gt; arr[j]){
                 MinIndex = j;
            }
        }
        if(MinIndex != i){
            swap(&amp;arr[i], &amp;arr[MinIndex]);
        }
    }
}</code></pre>
<ul>
<li>i, j, MinIndex 등 상수 크기의 메모리를 사용하므로 <strong>제자리 정렬</strong></li>
<li>안정성: <strong>불안정한 정렬</strong></li>
</ul>
<hr>
<h2 id="✅버블-정렬-bubble-sort">✅버블 정렬 (Bubble Sort)</h2>
<ul>
<li>좌측서부터 우측으로 이동하며 인접한 두 개의 원소를 서로 비교하고 좌측의 원소가 더 크면 우측의 원소와 교환되는 방식</li>
</ul>
<ol>
<li>정렬할 n개의 데이터가 배열 arr에 저장되어있다 가정</li>
<li>한 번 완료되었을 때 n개의 원소 중 가장 큰 원소가 우측 끝인 n-1 인덱스에 존재</li>
<li>0번째 인덱스부터 n-2번째 인덱스까지 차례로 검색 후 완료되면 2번째로 큰 원소가 n-2번째 인덱스에 존재</li>
<li>위 단계들 반복</li>
</ol>
<ul>
<li>역순으로 정렬된 배열일 경우 최악의 시간복잡도를 가진다.</li>
<li>1번째 일때 n-1번 비교, 2번째일 때 n-2번 비교, k번째일때 n-k번 비교하기 때문에, (n-1) + (n-2) ... + 1 = n(n-1)/2이므로 <strong>O(n^2)</strong>의 시간복잡도를 가지게 된다.</li>
<li>아래는 C++로 작성한 버블 정렬 함수이다.</li>
</ul>
<pre><code class="language-cpp">void bubblesort(int arr[], int n){
       for(int i = 0; i &lt; n; i++){
           for(int j = 1; j &lt; n - i; j++){
               if(arr[j - 1] &gt; arr[j]){
                   swap(&amp;arr[j - 1], &amp;arr[j]);
            }
        }    
    }
}</code></pre>
<ul>
<li>i, j 등 상수 크기의 메모리를 사용하므로 <strong>제자리 정렬</strong></li>
<li>안정성: <strong>안정된 정렬</strong></li>
</ul>
<hr>
<h2 id="✅삽입-정렬-insertion-sort">✅삽입 정렬 (Insertion Sort)</h2>
<ul>
<li>앞에서부터 하나씩 순서를 맞춰나가는 방식</li>
</ul>
<ol>
<li>정렬할 n개의 데이터가 배열 arr에 저장되어있다 가정</li>
<li>k번째 단계일 때, 배열 맨 처음 k-1개의 key들(0 ~ k-2 인덱스에 존재하는 원소들)은 이미 정렬되어있음.</li>
<li>k-1번째 인덱스 원소 값을 0 ~ k-2 인덱스 원소들의 값들과 비교해 적절한 위치에 삽입해 0 ~ k-1번째 인덱스의 값들이 정렬되도록 함</li>
</ol>
<p>※ 인덱스 값이 배열 내 최소 값인 경우 arr[1]과 비교 후 멈추지 않고 다시 arr[0]과 비교되려하기 때문에 이를 막기 위해 arr[0]에는 배열의 최소 값보다도 더 작은 값을 추가로 저장하면, 실제 자료들은 1 ~ n번 인덱스에 저장됨</p>
<ul>
<li>비교 횟수가 원소들의 순서에 민감</li>
<li>이미 정렬되어 있을 경우, <strong>최선의 경우</strong>로 시간복잡도는 <strong>O(n)</strong>을 가짐</li>
<li>역순으로 정렬되어 있을 경우는 <strong>최악의 경우</strong>로 시간복잡도는 <strong>O(n^2)</strong>을 가짐
(k번째 키 삽입 시 k번의 비교를 수행하므로 2 + 3 + ... +n = n(n+1)/2 - 1)</li>
<li><strong>평균 시간 복잡도</strong> 또한 <strong>O(n^2)</strong>을 가짐</li>
<li>아래는 C++로 작성한 삽입 정렬 함수이다.<pre><code class="language-cpp">void insertionsort(int arr[], int n){
     int i, j, val;
  for(i = 2; i &lt;= n; i++){
         val = arr[i];
      j = i;
      while(arr[j - 1] &gt; val){
            arr[j] = arr[j - 1];
          j--;
      }
      arr[j] = val;
  }   
}</code></pre>
</li>
<li>i, j, val 등 상수 크기 메모리를 사용하므로 <strong>제자리 정렬</strong></li>
<li>인접한 원소 값과 비교하면서 자신의 값과 같은 값이 나올 경우 바꾸지 않으므로 <strong>안정된 정렬</strong></li>
</ul>
<h2 id="📖참고자료">📖참고자료</h2>
<ul>
<li>대학교 ppt 교안</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[DB] 데이터베이스 기본 개념]]></title>
            <link>https://velog.io/@tae0__/DB-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EA%B8%B0%EB%B3%B8-%EA%B0%9C%EB%85%90</link>
            <guid>https://velog.io/@tae0__/DB-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EA%B8%B0%EB%B3%B8-%EA%B0%9C%EB%85%90</guid>
            <pubDate>Sun, 31 Mar 2024 08:58:28 GMT</pubDate>
            <description><![CDATA[<h2 id="✅-데이터베이스의-필요성">✅ 데이터베이스의 필요성</h2>
<ul>
<li><p>** 데이터 (Data)**
현실세계에서 단순히 관찰하거나 측정해 수집한 사실이나 값</p>
</li>
<li><p>** 정보 (Information)**
의사 결정에 유용히 활용할 수 있도록 데이터를 처리한 결과물</p>
</li>
<li><p>** 정보 처리 (Information Processing)**
데이터에서 정보를 추출하는 과정 또는 방법</p>
</li>
<li><p>** 정보 시스템 (Information System)**
데이터를 수집해 저장해뒀다가 필요할 때 유용한 정보를 만들어주는 수단</p>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/tae0__/post/ff3b92b7-b4a4-4df8-9e68-7a4fac38b868/image.png" alt=""></p>
<h3 id="데이터베이스-database">데이터베이스 (Database)</h3>
<ul>
<li>정보 시스템 내부에서 데이터를 저장하고 있다가 필요할 때 제공하는 역할을 담당</li>
</ul>
<h2 id="✅-데이터베이스의-정의와-특징">✅ 데이터베이스의 정의와 특징</h2>
<h3 id="📌데이터베이스의-정의">📌데이터베이스의 정의</h3>
<ul>
<li>특정 조직의 여러 사용자가 공유해 사용할 수 있도록 통합해서 저장한 운영데이터의 집합</li>
</ul>
<p><img src="https://velog.velcdn.com/images/tae0__/post/3cd31981-cfdd-43aa-96b7-24d048c62d9f/image.png" alt=""></p>
<ul>
<li><p><strong>통합데이터 (integrated data)</strong>
최소의 중복과 통제 가능한 중복만 허용한 데이터</p>
</li>
<li><p><strong>공유데이터 (shared data)</strong>
특정 조직의 여러 사용자가 함께 소유 및 이용할 수 있는 데이터</p>
</li>
<li><p><strong>저장데이터 (stored data)</strong>
컴퓨터가 접근할 수 있는 매체에 저장된 데이터</p>
</li>
<li><p><strong>운영데이터 (operational data)</strong>
조직의 주요 기능을 수행하기 위해 지속적으로 필요한 데이터</p>
</li>
</ul>
<h3 id="📌데이터베이스의-특징">📌데이터베이스의 특징</h3>
<p><img src="https://velog.velcdn.com/images/tae0__/post/09294a06-e62a-4ea2-ba90-cb77ab7784ff/image.png" alt=""></p>
<ul>
<li><p><strong>실시간 접근성 (real-time accessibility)</strong>
사용자의 데이터 요구에 실시간으로 응답</p>
</li>
<li><p><strong>계속 변화 (continuous evolution)</strong>
데이터의 계속되는 삽입, 삭제, 수정을 통해 현재의 정확한 데이터를 유지</p>
</li>
<li><p><strong>동시에 공유 가능 (concurrent sharing)</strong>
서로다른 데이터의 동시 사용뿐 아니라 같은 데이터의 동시 사용 또한 지원</p>
</li>
<li><p><strong>내용기반 참조 (content reference)</strong>
데이터가 저장된 주소나 위치가 아닌 내용 참조</p>
</li>
</ul>
<h2 id="✅데이터와-데이터베이스">✅데이터와 데이터베이스</h2>
<p><strong>1. 정형 데이터 (structured data)</strong></p>
<ul>
<li>구조화된 데이터 (미리 정해진 구조에 따라 저장된 데이터)</li>
<li>ex) 엑셀 스프레드시트, 관계 데이터베이스 테이블 </li>
</ul>
<p><strong>2. 반정형 데이터 (semi-structured data)</strong></p>
<ul>
<li>구조에 따라 저장된 데이터이나 데이터 내용 안에 구조에 대한 설명이 함께 존재하는 데이터</li>
<li>구조 파악을 위한 파싱(parsing) 과정이 필요</li>
<li>보통 파일형태로 저장됨</li>
<li>ex) HTML, XML, JSON문서나 웹 로그, 센서 데이터 등</li>
</ul>
<p><strong>3. 비정형 데이터 (unstructured data)</strong></p>
<ul>
<li>정해진 구조 없이 저장된 데이터</li>
<li>ex) 소셜 데이터의 텍스트, 영상, 이미지 등과 같은 멀티미디어 데이터</li>
</ul>
<h2 id="📖참고자료">📖참고자료</h2>
<ul>
<li>데이터베이스 개론 2판 김연희 저</li>
<li>대학교 ppt 교안</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 9375번: 패션왕 신해빈 [C++]]]></title>
            <link>https://velog.io/@tae0__/%EB%B0%B1%EC%A4%80-9375%EB%B2%88-%ED%8C%A8%EC%85%98%EC%99%95-%EC%8B%A0%ED%95%B4%EB%B9%88-C</link>
            <guid>https://velog.io/@tae0__/%EB%B0%B1%EC%A4%80-9375%EB%B2%88-%ED%8C%A8%EC%85%98%EC%99%95-%EC%8B%A0%ED%95%B4%EB%B9%88-C</guid>
            <pubDate>Sat, 13 Jan 2024 07:58:07 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<blockquote>
<p><a href="https://www.acmicpc.net/problem/9375">백준 9375번</a>
해빈이는 패션에 매우 민감해서 한번 입었던 옷들의 조합을 절대 다시 입지 않는다. 예를 들어 오늘 해빈이가 안경, 코트, 상의, 신발을 입었다면, 다음날은 바지를 추가로 입거나 안경대신 렌즈를 착용하거나 해야한다. 해빈이가 가진 의상들이 주어졌을때 과연 해빈이는 알몸이 아닌 상태로 며칠동안 밖에 돌아다닐 수 있을까?</p>
</blockquote>
<h3 id="입력">입력</h3>
<blockquote>
<p>첫째 줄에 테스트 케이스가 주어진다. 테스트 케이스는 최대 100이다.
*
각 테스트 케이스의 첫째 줄에는 해빈이가 가진 의상의 수 n(0 ≤ n ≤ 30)이 주어진다.
*
다음 n개에는 해빈이가 가진 의상의 이름과 의상의 종류가 공백으로 구분되어 주어진다. 같은 종류의 의상은 하나만 입을 수 있다.</p>
</blockquote>
<blockquote>
<p>모든 문자열은 1이상 20이하의 알파벳 소문자로 이루어져있으며 같은 이름을 가진 의상은 존재하지 않는다.</p>
</blockquote>
<h3 id="출력">출력</h3>
<blockquote>
<p>각 테스트 케이스에 대해 해빈이가 알몸이 아닌 상태로 의상을 입을 수 있는 경우를 출력하시오.</p>
</blockquote>
<h2 id="문제-분석">문제 분석</h2>
<p>수학적 지식인 조합에 대해서 생각이 제일 먼저 났고, 이를 어떻게 코드로 작성할지 고민을 많이 했다. 고민해 보니 map 자료구조를 사용하고, 어떤 의상을 입는지 저장하지 않고 몇개의 종류가 있는지만 알면 경우의 수를 쉽게 출력할 수 있다 판단하였다. 따라서, map 자료구조에서 사용하는 타입은 어디에 사용하는 의상인지 알 수 있게할 string 타입과 이 의상이 몇개가 있는지 알기 위한 int타입을 사용한다. </p>
<p>예를 들어서 모자 3개와 상의 2개가 있다할 경우, 모자에서는 (쓰지 않는 경우, 모자1, 모자2, 모자3) 총 4개의 경우의 수가 나오며, 상의에서는 (입지 않는 경우, 상의1, 상의2) 총 3개의 경우의 수가 존재하게 된다. 위 두 경우의 수를 곱하고 알몸일 경우의 수인 1을 빼면 결과가 나오게 된다.</p>
<h2 id="제출코드">제출코드</h2>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;string&gt;
#include &lt;map&gt;

using namespace std;

int main(void) {
    int test, clothes;
    string what, where;
    cin &gt;&gt; test;

    for (int i = 0; i &lt; test; i++) {
        cin &gt;&gt; clothes;
        map&lt;string, int&gt; clothing;

        for (int j = 0; j &lt; clothes; j++) {
            cin &gt;&gt; what &gt;&gt; where;
            clothing[where]++;
        }
        int sum = 1;
        for (auto a : clothing) {
            sum *= (a.second + 1);
        }
        cout &lt;&lt; sum - 1 &lt;&lt; &quot;\n&quot;;
    }
    return 0;
}</code></pre>
<p><img src="https://velog.velcdn.com/images/tae0__/post/b7a95a60-6c8b-4b57-9b6d-57e132947c02/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 17219번: 비밀번호 찾기 [C++]]]></title>
            <link>https://velog.io/@tae0__/%EB%B0%B1%EC%A4%80-17219%EB%B2%88-%EB%B9%84%EB%B0%80%EB%B2%88%ED%98%B8-%EC%B0%BE%EA%B8%B0-C</link>
            <guid>https://velog.io/@tae0__/%EB%B0%B1%EC%A4%80-17219%EB%B2%88-%EB%B9%84%EB%B0%80%EB%B2%88%ED%98%B8-%EC%B0%BE%EA%B8%B0-C</guid>
            <pubDate>Thu, 04 Jan 2024 04:25:13 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<blockquote>
<p><a href="https://www.acmicpc.net/problem/17219">백준 17219번</a>
2019 HEPC - MAVEN League의 &quot;비밀번호 만들기&quot;와 같은 방식으로 비밀번호를 만든 경민이는 한 가지 문제점을 발견하였다. 비밀번호가 랜덤으로 만들어져서 기억을 못 한다는 것이었다! 그래서 경민이는 메모장에 사이트의 주소와 비밀번호를 저장해두기로 했다. 하지만 컴맹인 경민이는 메모장에서 찾기 기능을 활용하지 못하고 직접 눈으로 사이트의 주소와 비밀번호를 찾았다. 메모장에 저장된 사이트의 수가 늘어나면서 경민이는 비밀번호를 찾는 일에 시간을 너무 많이 쓰게 되었다. 이를 딱하게 여긴 문석이는 경민이를 위해 메모장에서 비밀번호를 찾는 프로그램을 만들기로 결심하였다! 문석이를 도와 경민이의 메모장에서 비밀번호를 찾아주는 프로그램을 만들어보자.</p>
</blockquote>
<h3 id="입력">입력</h3>
<blockquote>
<p>첫째 줄에 저장된 사이트 주소의 수 N(1 ≤ N ≤ 100,000)과 비밀번호를 찾으려는 사이트 주소의 수 M(1 ≤ M ≤ 100,000)이 주어진다.</p>
</blockquote>
<blockquote>
<p>두번째 줄부터 N개의 줄에 걸쳐 각 줄에 사이트 주소와 비밀번호가 공백으로 구분되어 주어진다. 사이트 주소는 알파벳 소문자, 알파벳 대문자, 대시(&#39;-&#39;), 마침표(&#39;.&#39;)로 이루어져 있고, 중복되지 않는다. 비밀번호는 알파벳 대문자로만 이루어져 있다. 모두 길이는 최대 20자이다.</p>
</blockquote>
<blockquote>
<p>N+2번째 줄부터 M개의 줄에 걸쳐 비밀번호를 찾으려는 사이트 주소가 한줄에 하나씩 입력된다. 이때, 반드시 이미 저장된 사이트 주소가 입력된다.</p>
</blockquote>
<h3 id="출력">출력</h3>
<blockquote>
<p>첫 번째 줄부터 M개의 줄에 걸쳐 비밀번호를 찾으려는 사이트 주소의 비밀번호를 차례대로 각 줄에 하나씩 출력한다.</p>
</blockquote>
<h2 id="문제-분석">문제 분석</h2>
<p>사이트 주소와 비밀번호를 key와 value 쌍으로 가지는 map을 사용하면 쉽게 풀 수 있을 것이라 생각했다. find 함수를 통해서 사이트 주소를 찾고, 그 사이트에 맞는 비밀번호를 출력하면 문제가 해결된다.</p>
<h2 id="코드">코드</h2>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;string&gt;
#include &lt;map&gt;

using namespace std;

map&lt;string, string&gt; pass;

int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(NULL);

    int n, m;
    string site, password, isSite;
    cin &gt;&gt; n &gt;&gt; m;

    for (int i = 0; i &lt; n; i++) {
        cin &gt;&gt; site &gt;&gt; password;
        pass.insert({ site, password });
    }

    for (int i = 0; i &lt; m; i++) {
        cin &gt;&gt; isSite;
        if (pass.find(isSite) != pass.end()) {
            cout &lt;&lt; pass.find(isSite)-&gt;second &lt;&lt; &quot;\n&quot;;
        }
    }
    return 0;
}</code></pre>
<p><img src="https://velog.velcdn.com/images/tae0__/post/6e4f6539-e095-4aa1-8cf3-aff2a7afd26e/image.png" alt="">
코드 정답!!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 1764번: 듣보잡 [C++]]]></title>
            <link>https://velog.io/@tae0__/%EB%B0%B1%EC%A4%80-1764%EB%B2%88-%EB%93%A3%EB%B3%B4%EC%9E%A1-C</link>
            <guid>https://velog.io/@tae0__/%EB%B0%B1%EC%A4%80-1764%EB%B2%88-%EB%93%A3%EB%B3%B4%EC%9E%A1-C</guid>
            <pubDate>Wed, 03 Jan 2024 05:49:42 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<blockquote>
<p><a href="https://www.acmicpc.net/problem/1764">백준 1764번</a>
김진영이 듣도 못한 사람의 명단과, 보도 못한 사람의 명단이 주어질 때, 듣도 보도 못한 사람의 명단을 구하는 프로그램을 작성하시오.</p>
</blockquote>
<h3 id="입력">입력</h3>
<blockquote>
<p>첫째 줄에 듣도 못한 사람의 수 N, 보도 못한 사람의 수 M이 주어진다. 이어서 둘째 줄부터 N개의 줄에 걸쳐 듣도 못한 사람의 이름과, N+2째 줄부터 보도 못한 사람의 이름이 순서대로 주어진다. 이름은 띄어쓰기 없이 알파벳 소문자로만 이루어지며, 그 길이는 20 이하이다. N, M은 500,000 이하의 자연수이다.</p>
</blockquote>
<blockquote>
<p>듣도 못한 사람의 명단에는 중복되는 이름이 없으며, 보도 못한 사람의 명단도 마찬가지이다.</p>
</blockquote>
<h3 id="출력">출력</h3>
<blockquote>
<p>듣보잡의 수와 그 명단을 사전순으로 출력한다.</p>
</blockquote>
<h2 id="문제-분석">문제 분석</h2>
<p>듣도 못한 사람의 배열, 보도 못한 사람의 배열을 만들고 이 두 배열에서 겹치는 사람의 수와 이름을 사전순으로 출력하는 문제이다. N과 M이 50만 이하의 자연수이므로 이중 for문을 쓴다면 시간 초과가 날 것이 분명하다고 생각했다. 그래서 생각한 것이 출력 또한 사전순으로 출력하기 때문에, 입력받은 이름들을 저장한 배열들을 사전순으로 정렬하고, 이분탐색을 사용한다면 시간복잡도가 훨씬 줄어들어 시간 내에 실행이 가능하다고 생각했다. </p>
<h2 id="작성-코드">작성 코드</h2>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;string&gt;
#include &lt;vector&gt;
#include &lt;algorithm&gt;

using namespace std;

vector&lt;string&gt; notListen;
vector&lt;string&gt; notSee;
vector&lt;string&gt; notSeenLis;

int main(void) {
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    int n, m, cnt = 0;
    string name;
    cin &gt;&gt; n &gt;&gt; m;
    for (int i = 0; i &lt; n; i++) {
        cin &gt;&gt; name;
        notListen.push_back(name);
    }

    for (int i = 0; i &lt; m; i++) {
        cin &gt;&gt; name;
        notSee.push_back(name);
    }
    sort(notListen.begin(), notListen.end());
    sort(notSee.begin(), notSee.end());

    if (notListen.size() &gt; notSee.size()) {
        for (int i = 0; i &lt; m; i++) {
            if (binary_search(notListen.begin(), notListen.end(), notSee[i])) {
                notSeenLis.push_back(notSee[i]);
                cnt++;
            }
        }
    }
    else {
        for (int i = 0; i &lt; n; i++) {
            if (binary_search(notSee.begin(), notSee.end(), notListen[i])) {
                notSeenLis.push_back(notListen[i]);
                cnt++;
            }
        }
    }
    cout &lt;&lt; cnt &lt;&lt; &quot;\n&quot;;

    for (int i = 0; i &lt; notSeenLis.size(); i++) {
        cout &lt;&lt; notSeenLis[i] &lt;&lt; &quot;\n&quot;;
    }
    return 0;
}</code></pre>
<p><img src="https://velog.velcdn.com/images/tae0__/post/10a80895-8fa8-4a8e-b707-a6c5eeb1b98e/image.png" alt="">
코드는 정답!!
if-else 문으로 듣도 못한 배열의 크기와 보도 못한 배열의 크기를 나눠준 이유는 실행 시간을 더 줄여주기 위해 for문을 더 적게 돌도록함에 있어서 이렇게 작성했다.</p>
<h3 id="아쉬운-점">아쉬운 점</h3>
<p>cnt를 사용하지 않고 notSeenLis 배열의 사이즈를 출력해줘도 괜찮았을 것 같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 1620번: 나는야 포켓몬 마스터 이다솜 [C++]]]></title>
            <link>https://velog.io/@tae0__/%EB%B0%B1%EC%A4%80-1620%EB%B2%88-%EB%82%98%EB%8A%94%EC%95%BC-%ED%8F%AC%EC%BC%93%EB%AA%AC-%EB%A7%88%EC%8A%A4%ED%84%B0-%EC%9D%B4%EB%8B%A4%EC%86%9C-C</link>
            <guid>https://velog.io/@tae0__/%EB%B0%B1%EC%A4%80-1620%EB%B2%88-%EB%82%98%EB%8A%94%EC%95%BC-%ED%8F%AC%EC%BC%93%EB%AA%AC-%EB%A7%88%EC%8A%A4%ED%84%B0-%EC%9D%B4%EB%8B%A4%EC%86%9C-C</guid>
            <pubDate>Wed, 03 Jan 2024 05:03:02 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<blockquote>
<p><a href="https://www.acmicpc.net/problem/1620">백준 1620번</a></p>
</blockquote>
<h3 id="입력">입력</h3>
<blockquote>
<p>첫째 줄에는 도감에 수록되어 있는 포켓몬의 개수 N이랑 내가 맞춰야 하는 문제의 개수 M이 주어져. N과 M은 1보다 크거나 같고, 100,000보다 작거나 같은 자연수인데, 자연수가 뭔지는 알지? 모르면 물어봐도 괜찮아. 나는 언제든지 질문에 답해줄 준비가 되어있어.
둘째 줄부터 N개의 줄에 포켓몬의 번호가 1번인 포켓몬부터 N번에 해당하는 포켓몬까지 한 줄에 하나씩 입력으로 들어와. 포켓몬의 이름은 모두 영어로만 이루어져있고, 또, 음... 첫 글자만 대문자이고, 나머지 문자는 소문자로만 이루어져 있어. 아참! 일부 포켓몬은 마지막 문자만 대문자일 수도 있어. 포켓몬 이름의 최대 길이는 20, 최소 길이는 2야. 그 다음 줄부터 총 M개의 줄에 내가 맞춰야하는 문제가 입력으로 들어와. 문제가 알파벳으로만 들어오면 포켓몬 번호를 말해야 하고, 숫자로만 들어오면, 포켓몬 번호에 해당하는 문자를 출력해야해. 입력으로 들어오는 숫자는 반드시 1보다 크거나 같고, N보다 작거나 같고, 입력으로 들어오는 문자는 반드시 도감에 있는 포켓몬의 이름만 주어져. 그럼 화이팅!!!</p>
</blockquote>
<h3 id="출력">출력</h3>
<blockquote>
<p>첫째 줄부터 차례대로 M개의 줄에 각각의 문제에 대한 답을 말해줬으면 좋겠어!!!. 입력으로 숫자가 들어왔다면 그 숫자에 해당하는 포켓몬의 이름을, 문자가 들어왔으면 그 포켓몬의 이름에 해당하는 번호를 출력하면 돼. 그럼 땡큐~</p>
</blockquote>
<h2 id="문제-분석">문제 분석</h2>
<p>포켓몬 이름을 물어볼 경우 포켓몬 번호가 출력되도록 하며, 번호를 물어볼 경우 포켓몬 이름을 출력하도록 만드는 문제로, (key, value)쌍을 사용하는 자료구조인 map을 사용하게 된다면 쉽게 풀 수 있다고 생각했다. key값으로는 포켓몬의 이름, value 값으로는 포켓몬 번호를 저장하면 된다. 입력이 또한 최대 10만개가 나올 수 있으므로 스트림 동기화도 꺼주면 시간 초과도 나지 않을 것이다. </p>
<h2 id="코드">코드</h2>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;string&gt;
#include &lt;map&gt;
#include &lt;vector&gt;

using namespace std;

map&lt;string, int&gt; pokemon;
vector&lt;string&gt; pokemonName;

int main(void) {
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    int n, m;
    string name, quiz;
    cin &gt;&gt; n &gt;&gt; m;

    for (int i = 0; i &lt; n; i++) {
        cin &gt;&gt; name;
        pokemon.insert({ name, (i + 1) });
        pokemonName.push_back(name);
    }

    for (int i = 0; i &lt; m; i++) {
        cin &gt;&gt; quiz;
        if (isdigit(quiz[0])) {
            cout &lt;&lt; pokemonName[stoi(quiz) - 1] &lt;&lt; &quot;\n&quot;;
        }
        else {
            cout &lt;&lt; pokemon.find(quiz)-&gt;second &lt;&lt; &quot;\n&quot;;
        }
    }
    return 0;
}</code></pre>
<p><img src="https://velog.velcdn.com/images/tae0__/post/bdc42d04-4b13-4356-8c30-b150d0d80139/image.png" alt="">
코드 정답!!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 11723번: 집합 [C++]]]></title>
            <link>https://velog.io/@tae0__/%EB%B0%B1%EC%A4%80-11723%EB%B2%88-%EC%A7%91%ED%95%A9-C</link>
            <guid>https://velog.io/@tae0__/%EB%B0%B1%EC%A4%80-11723%EB%B2%88-%EC%A7%91%ED%95%A9-C</guid>
            <pubDate>Mon, 01 Jan 2024 05:58:23 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<blockquote>
<p><a href="https://www.acmicpc.net/problem/11723">백준 11723번</a>
비어있는 공집합 S가 주어졌을 때, 아래 연산을 수행하는 프로그램을 작성하시오.</p>
</blockquote>
<blockquote>
<ul>
<li>add x: S에 x를 추가한다. (1 ≤ x ≤ 20) S에 x가 이미 있는 경우에는 연산을 무시한다.</li>
</ul>
</blockquote>
<ul>
<li>remove x: S에서 x를 제거한다. (1 ≤ x ≤ 20) S에 x가 없는 경우에는 연산을 무시한다.</li>
<li>check x: S에 x가 있으면 1을, 없으면 0을 출력한다. (1 ≤ x ≤ 20)</li>
<li>toggle x: S에 x가 있으면 x를 제거하고, 없으면 x를 추가한다. (1 ≤ x ≤ 20)</li>
<li>all: S를 {1, 2, ..., 20} 으로 바꾼다.</li>
<li>empty: S를 공집합으로 바꾼다.</li>
</ul>
<h2 id="입력">입력</h2>
<blockquote>
<p>26
add 1
add 2
check 1
check 2
check 3
remove 2
check 1
check 2
toggle 3
check 1
check 2
check 3
check 4
all
check 10
check 20
toggle 10
remove 20
check 10
check 20
empty
check 1
toggle 1
check 1
toggle 1
check 1</p>
</blockquote>
<h2 id="출력">출력</h2>
<blockquote>
<p>1
1
0
1
0
1
0
1
0
1
1
0
0
0
1
0</p>
</blockquote>
<h2 id="문제-분석">문제 분석</h2>
<p>위 여러 연산들을 수행하는 프로그램을 작성하는 문제로, 가장 처음 생각나는 게 벡터라서 벡터로 문제를 해결하려 했다. 더해서, 수행할 연산과 숫자를 문자열로 입력 받고, substr을 이용해서 띄어쓰기를 기준으로 앞 문자열과 뒷 문자열을 분리해 앞 문자열의 문자열을 통해서 어떤 연산을 할 것인지와 뒷 문자열을 숫자로 변환시켜 어떤 수를 연산에 이용할 것인지 나누었다. all과 empty같은 경우 띄어쓰기와 숫자 없이 문자열만 나오기 때문에 if문을 이용해서 띄어쓰기가 나오는지 나오지 않는지 구분하면 쉽게 해결 가능할 것 같다.</p>
<h2 id="처음-작성한-코드">처음 작성한 코드</h2>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;string&gt;

using namespace std;

vector&lt;int&gt; set;

void add(int num) {
    bool isNum = false;
    for (int i = 0; i &lt; set.size(); i++) {
        if (num == set[i]) {
            isNum = true;
            break;
        }
    }
    if (!isNum) {
        set.push_back(num);
    }
}

void remove(int num) {
    bool isNum = false;
    int index;
    for (int i = 0; i &lt; set.size(); i++) {
        if (num == set[i]) {
            isNum = true;
            index = i;
            break;
        }
    }
    if (isNum) {
        set.erase(set.begin() + index);
    }
}

void check(int num) {
    bool isNum = false;
    for (int i = 0; i &lt; set.size(); i++) {
        if (num == set[i]) {
            isNum = true;
            break;
        }
    }
    if (isNum) {
        cout &lt;&lt; 1 &lt;&lt; &quot;\n&quot;;
    }
    else {
        cout &lt;&lt; 0 &lt;&lt; &quot;\n&quot;;
    }
}

void toggle(int num) {
    bool isNum = false;
    for (int i = 0; i &lt; set.size(); i++) {
        if (num == set[i]) {
            isNum = true;
            break;
        }
    }
    if (isNum) {
        remove(num);
    }
    else {
        add(num);
    }
}

void all() {
    set.clear();
    for (int i = 1; i &lt;= 20; i++) {
        set.push_back(i);
    }
}

void empty() {
    set.clear();
}

int main(void) {
    int test, number;
    string str, order;

    cin &gt;&gt; test;
    cin.ignore();
    for (int i = 0; i &lt; test; i++) {
        getline(cin, str);

        if (str.find(&quot; &quot;) != -1) {
            order = str.substr(0, str.find(&quot; &quot;));
            number = stoi(str.substr(str.find(&quot; &quot;) + 1, str.length()));
        }
        else {
            order = str;
        }

        if (order == &quot;add&quot;) {
            add(number);
        }
        else if (order == &quot;remove&quot;) {
            remove(number);
        }
        else if (order == &quot;check&quot;) {
            check(number);
        }
        else if (order == &quot;toggle&quot;) {
            toggle(number);
        }
        else if (order == &quot;all&quot;) {
            all();
        }
        else if (order == &quot;empty&quot;) {
            empty();
        }
    }
}</code></pre>
<p><img src="https://velog.velcdn.com/images/tae0__/post/3968b5ec-ec35-4a46-8910-0ba42b01f0f9/image.png" alt="">
실행 했을 때 결과는 정확히 나왔었는데 시간 초과가 났다... for문에서 시간 초과가 발생했는지 생각했지만 2중 for문을 사용하지 않았기 때문에 시간복잡도가 O(n)으로 시간이 그렇게 길어질 것이라 생각하지 않았다... 설마 입출력에서 시간을 잡아먹나 싶어 C++과 C의 표준 스트림 동기화를 끄는 코드를 추가해보았다</p>
<h2 id="수정한-코드">수정한 코드</h2>
<pre><code class="language-C++">#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;string&gt;

using namespace std;

vector&lt;int&gt; set;

void add(int num) {
    bool isNum = false;
    for (int i = 0; i &lt; set.size(); i++) {
        if (num == set[i]) {
            isNum = true;
            break;
        }
    }
    if (!isNum) {
        set.push_back(num);
    }
}

void remove(int num) {
    bool isNum = false;
    int index;
    for (int i = 0; i &lt; set.size(); i++) {
        if (num == set[i]) {
            isNum = true;
            index = i;
            break;
        }
    }
    if (isNum) {
        set.erase(set.begin() + index);
    }
}

void check(int num) {
    bool isNum = false;
    for (int i = 0; i &lt; set.size(); i++) {
        if (num == set[i]) {
            isNum = true;
            break;
        }
    }
    if (isNum) {
        cout &lt;&lt; 1 &lt;&lt; &quot;\n&quot;;
    }
    else {
        cout &lt;&lt; 0 &lt;&lt; &quot;\n&quot;;
    }
}

void toggle(int num) {
    bool isNum = false;
    for (int i = 0; i &lt; set.size(); i++) {
        if (num == set[i]) {
            isNum = true;
            break;
        }
    }
    if (isNum) {
        remove(num);
    }
    else {
        add(num);
    }
}

void all() {
    set.clear();
    for (int i = 1; i &lt;= 20; i++) {
        set.push_back(i);
    }
}

void empty() {
    set.clear();
}

int main(void) {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    int test, number;
    string str, order;

    cin &gt;&gt; test;
    cin.ignore();
    for (int i = 0; i &lt; test; i++) {
        getline(cin, str);

        if (str.find(&quot; &quot;) != -1) {
            order = str.substr(0, str.find(&quot; &quot;));
            number = stoi(str.substr(str.find(&quot; &quot;) + 1, str.length()));
        }
        else {
            order = str;
        }

        if (order == &quot;add&quot;) {
            add(number);
        }
        else if (order == &quot;remove&quot;) {
            remove(number);
        }
        else if (order == &quot;check&quot;) {
            check(number);
        }
        else if (order == &quot;toggle&quot;) {
            toggle(number);
        }
        else if (order == &quot;all&quot;) {
            all();
        }
        else if (order == &quot;empty&quot;) {
            empty();
        }
    }
}</code></pre>
<p><img src="https://velog.velcdn.com/images/tae0__/post/8d9182b9-77a4-4e33-8e34-354c361ac25a/image.png" alt="">
C++과 C의 표준 스트림 동기화 때문에 입출력에서 시간을 잡아먹었던 것 같다... 코드 수정하니까 정답!!
(※ 더해서, endl은 개행에 더해서 내부 버퍼도 비워주기 때문에 &quot;\n&quot;보다 속도가 느리기 때문에 &quot;\n&quot;을 사용하는 것도 속도 향상에 도움이 된다.)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 1012번: 유기농 배추 [C++]]]></title>
            <link>https://velog.io/@tae0__/%EB%B0%B1%EC%A4%80-1012%EB%B2%88-%EC%9C%A0%EA%B8%B0%EB%86%8D-%EB%B0%B0%EC%B6%94-C</link>
            <guid>https://velog.io/@tae0__/%EB%B0%B1%EC%A4%80-1012%EB%B2%88-%EC%9C%A0%EA%B8%B0%EB%86%8D-%EB%B0%B0%EC%B6%94-C</guid>
            <pubDate>Mon, 01 Jan 2024 04:39:13 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<blockquote>
<p><a href="https://www.acmicpc.net/problem/1012">백준 1012번</a>
차세대 영농인 한나는 강원도 고랭지에서 유기농 배추를 재배하기로 하였다. 농약을 쓰지 않고 배추를 재배하려면 배추를 해충으로부터 보호하는 것이 중요하기 때문에, 한나는 해충 방지에 효과적인 배추흰지렁이를 구입하기로 결심한다. 이 지렁이는 배추근처에 서식하며 해충을 잡아 먹음으로써 배추를 보호한다. 특히, 어떤 배추에 배추흰지렁이가 한 마리라도 살고 있으면 이 지렁이는 인접한 다른 배추로 이동할 수 있어, 그 배추들 역시 해충으로부터 보호받을 수 있다. 한 배추의 상하좌우 네 방향에 다른 배추가 위치한 경우에 서로 인접해있는 것이다.</p>
</blockquote>
<blockquote>
<p>한나가 배추를 재배하는 땅은 고르지 못해서 배추를 군데군데 심어 놓았다. 배추들이 모여있는 곳에는 배추흰지렁이가 한 마리만 있으면 되므로 서로 인접해있는 배추들이 몇 군데에 퍼져있는지 조사하면 총 몇 마리의 지렁이가 필요한지 알 수 있다. 예를 들어 배추밭이 아래와 같이 구성되어 있으면 최소 5마리의 배추흰지렁이가 필요하다. 0은 배추가 심어져 있지 않은 땅이고, 1은 배추가 심어져 있는 땅을 나타낸다.
<img src="https://velog.velcdn.com/images/tae0__/post/fb10396a-e740-4dc6-ad91-adca5f76bb2d/image.png" alt=""></p>
</blockquote>
<h2 id="문제-분석">문제 분석</h2>
<p> 2차원 배열에 저장되어있는 배추 위치를 이용해 인접한 곳에 배추가 존재하는지 탐색해 문제를 해결할 수 있다 판단해서 그래프 탐색 방식인 DFS를 이용했다. </p>
<h2 id="처음-제출한-코드">처음 제출한 코드</h2>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;algorithm&gt;

using namespace std;
int n, m, k;
int ground[51][51] = { 0, };
bool visited[51][51];

int dirX[4] = { 0,0,1,-1 }; 
int dirY[4] = { 1,-1,0,0 };

void dfs(int y, int x) {
    for (int i = 0; i &lt; 4; i++) {
        int nextX = x + dirX[i];
        int nextY = y + dirY[i];

        if (nextY &lt; 0 || nextY &gt;= n || nextX&lt; 0 || nextX &gt;= m) {
            continue;
        }
        if (ground[nextY][nextX] &amp;&amp; !visited[nextY][nextX]) {
            visited[nextY][nextX] = true;
            dfs(nextY, nextX);
        }
    }
}

int main(void) {
    int test, p1, p2;
    cin &gt;&gt; test;

    for (int i = 0; i &lt; test; i++) {
        int cnt = 0;
        cin &gt;&gt; m &gt;&gt; n &gt;&gt; k;
        for (int j = 0; j &lt; k; j++) {
            cin &gt;&gt; p1 &gt;&gt; p2;
            ground[p2][p1] = 1;
        }

        for (int l = 0; l &lt; n; l++) {
            for (int h = 0; h &lt; m; h++) {
                if (ground[l][h] == 1 &amp;&amp; !visited[l][h]) {
                    dfs(l, h);
                    cnt++;
                }
            }
        }
        cout &lt;&lt; cnt &lt;&lt; &quot;\n&quot;;
    }
}</code></pre>
<p><img src="https://velog.velcdn.com/images/tae0__/post/5bb231c2-abec-4120-9a02-5222af06bc13/image.png" alt="">
틀렸다고 뜬다... 왜 틀렸을까 고민해 보니 test를 여러번 했다 가정했을 때, 전역으로 설정한 visited와 ground 2차원 배열을 다시 쓸 텐데 다시 쓸 때 초기화를 시켜주지 않았었다...😅
아래는 visited와 ground를 fill 함수를 이용해서 다시 사용할 때 초기화를 시켜주고 사용하도록 구현한 코드이다.</p>
<h2 id="수정한-코드">수정한 코드</h2>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;algorithm&gt;

using namespace std;
int n, m, k;
int ground[51][51] = { 0, };
bool visited[51][51];

int dirX[4] = { 0,0,1,-1 }; 
int dirY[4] = { 1,-1,0,0 }; 

void dfs(int y, int x) {
    for (int i = 0; i &lt; 4; i++) {
        int nextX = x + dirX[i];
        int nextY = y + dirY[i];

        if (nextY &lt; 0 || nextY &gt;= n || nextX&lt; 0 || nextX &gt;= m) {
            continue;
        }
        if (ground[nextY][nextX] &amp;&amp; !visited[nextY][nextX]) {
            visited[nextY][nextX] = true;
            dfs(nextY, nextX);
        }
    }
}

int main(void) {
    int test, p1, p2;
    cin &gt;&gt; test;

    for (int i = 0; i &lt; test; i++) {
        int cnt = 0;
        cin &gt;&gt; m &gt;&gt; n &gt;&gt; k;
        for (int j = 0; j &lt; k; j++) {
            cin &gt;&gt; p1 &gt;&gt; p2;
            ground[p2][p1] = 1;
        }

        for (int l = 0; l &lt; n; l++) {
            for (int h = 0; h &lt; m; h++) {
                if (ground[l][h] == 1 &amp;&amp; !visited[l][h]) {
                    dfs(l, h);
                    cnt++;
                }
            }
        }
        cout &lt;&lt; cnt &lt;&lt; &quot;\n&quot;;

        for (int l = 0; l &lt; n; l++) {
            fill(ground[l], ground[l] + m, 0);
            fill(visited[l], visited[l] + m, false);
        }
    }
}</code></pre>
<p><img src="https://velog.velcdn.com/images/tae0__/post/d91fd53c-afac-433a-b8cf-343fd254d5ef/image.png" alt="">
2차원 배열들을 초기화 시켜주는 코드를 추가하니 정답!</p>
<h3 id="헷갈렸던-부분">헷갈렸던 부분</h3>
<p>2차원 배열에서는 첫 번째 인덱스가 보편적으로 <strong>행</strong>을 의미하며, 두 번째 인덱스가 <strong>열</strong>을 의미하기 때문에 y좌표를 첫 번째 인덱스에 할당하고, x좌표를 두 번째 인덱스에 할당한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 2606번: 바이러스 [C++]]]></title>
            <link>https://velog.io/@tae0__/%EB%B0%B1%EC%A4%80-2606%EB%B2%88-%EB%B0%94%EC%9D%B4%EB%9F%AC%EC%8A%A4-C</link>
            <guid>https://velog.io/@tae0__/%EB%B0%B1%EC%A4%80-2606%EB%B2%88-%EB%B0%94%EC%9D%B4%EB%9F%AC%EC%8A%A4-C</guid>
            <pubDate>Sun, 31 Dec 2023 05:13:15 GMT</pubDate>
            <description><![CDATA[<h2 id="문제-설명">문제 설명</h2>
<p><a href="https://www.acmicpc.net/problem/2606">백준 2606: 바이러스</a></p>
<blockquote>
<p> 신종 바이러스인 웜 바이러스는 네트워크를 통해 전파된다. 한 컴퓨터가 웜 바이러스에 걸리면 그 컴퓨터와 네트워크 상에서 연결되어 있는 모든 컴퓨터는 웜 바이러스에 걸리게 된다.
<img src="https://velog.velcdn.com/images/tae0__/post/67cd357c-74d7-4436-b1d6-7300e580edaa/image.png" alt="">
  예를 들어 7대의 컴퓨터가 &lt;그림 1&gt;과 같이 네트워크 상에서 연결되어 있다고 하자. 1번 컴퓨터가 웜 바이러스에 걸리면 웜 바이러스는 2번과 5번 컴퓨터를 거쳐 3번과 6번 컴퓨터까지 전파되어 2, 3, 5, 6 네 대의 컴퓨터는 웜 바이러스에 걸리게 된다. 하지만 4번과 7번 컴퓨터는 1번 컴퓨터와 네트워크상에서 연결되어 있지 않기 때문에 영향을 받지 않는다.
  어느 날 1번 컴퓨터가 웜 바이러스에 걸렸다. 컴퓨터의 수와 네트워크 상에서 서로 연결되어 있는 정보가 주어질 때, 1번 컴퓨터를 통해 웜 바이러스에 걸리게 되는 컴퓨터의 수를 출력하는 프로그램을 작성하시오.</p>
</blockquote>
<h2 id="문제-분석">문제 분석</h2>
<p> 바이러스가 걸린 컴퓨터와 연결된 컴퓨터는 바이러스에 걸리게 되며, 1번 컴퓨터에 의해 바이러스가 걸리는 컴퓨터의 수를 출력하는 문제이다. 여러 갈래로 컴퓨터들이 연결되어 있으므로 그래프 관련 문제라 생각했고, 1번 컴퓨터에 의해 바이러스가 걸린 컴퓨터 수를 출력하는 문제이므로 DFS 방식, BFS 방식 모두 사용 가능하다 판단해서 인접 행렬을 이용한 그래프와 재귀를 이용한 DFS 방식을 사용했다.</p>
<h2 id="처음-작성한-코드">처음 작성한 코드</h2>
<pre><code class="language-cpp">#include &lt;iostream&gt;

using namespace std;

int computer[101][101] = { 0, };
bool virus[101];
int com, edges, cnt = 0;

void dfs(int v) {
    virus[v] = true;

    for (int i = 0; i &lt; com; i++) {
        if (!virus[i] &amp;&amp; computer[v][i] == 1) {
            dfs(i);
            cnt++;
        }
    }
}

int main(void) {
    int c1, c2;
    cin &gt;&gt; com &gt;&gt; edges;

    for (int i = 0; i &lt; edges; i++) {
        cin &gt;&gt; c1 &gt;&gt; c2;
        computer[c1][c2] = 1;
        computer[c2][c1] = 1;
    }

    dfs(1);
    cout &lt;&lt; cnt;
}</code></pre>
<p><img src="https://velog.velcdn.com/images/tae0__/post/007b2f06-c015-42f3-8220-a22b010e33c6/image.png" alt="">
위 코드가 틀린 이유를 계속 찾다가 dfs 함수 내부 for문의 조건식이 이상하다는 것을 알았다. 예를 들어서, com이 7로 입력되었을 경우, 컴퓨터1 ~ 컴퓨터7까지 존재하는 것인데 나는 컴퓨터0 ~ 컴퓨터6까지 반복문을 돌리고 있었던 것이다... </p>
<p>아래는 수정한 코드이다</p>
<h2 id="수정한-코드">수정한 코드</h2>
<pre><code>#include &lt;iostream&gt;

using namespace std;

int computer[101][101] = { 0, };
bool virus[101];
int com, edges, cnt = 0;

void dfs(int v) {
    virus[v] = true;

    for (int i = 1; i &lt;= com; i++) {
        if (!virus[i] &amp;&amp; computer[v][i] == 1) {
            dfs(i);
            cnt++;
        }
    }
}

int main(void) {
    int c1, c2;
    cin &gt;&gt; com &gt;&gt; edges;

    for (int i = 0; i &lt; edges; i++) {
        cin &gt;&gt; c1 &gt;&gt; c2;
        computer[c1][c2] = 1;
        computer[c2][c1] = 1;
    }

    dfs(1);
    cout &lt;&lt; cnt;
}</code></pre><p><img src="https://velog.velcdn.com/images/tae0__/post/1ebe54b1-5d84-498e-bfd7-3fb136d087ba/image.png" alt=""></p>
]]></description>
        </item>
    </channel>
</rss>