<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>콘트라베이스</title>
    <link>https://contrabass.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Tue, 28 Jul 2026 12:11:39 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>완성</managingEditor>
    <image>
      <title>콘트라베이스</title>
      <url>https://tistory1.daumcdn.net/tistory/5275801/attach/351a7b8e087c493d82a9e54425899cfe</url>
      <link>https://contrabass.tistory.com</link>
    </image>
    <item>
      <title>MacOS 네트워크 인터페이스(Networt Interfaces)</title>
      <link>https://contrabass.tistory.com/127</link>
      <description>&lt;h2&gt;개요&lt;/h2&gt;
&lt;p&gt;tcp 3 way handshake 과정에서 실제로 헤더에 어떤 정보가 담기는지 확인하기 위한 방법을 알아보던 중&lt;/p&gt;
&lt;p&gt;tcpdump를 통해 패킷 헤더의 내용을 확인할 수 있다는 사실을 알게되었다.&lt;/p&gt;
&lt;p&gt;그러나 tcpdump를 활용한 예시들이 전부 &amp;#39;eth0&amp;#39;이라는 네트워크 인터페이스를 통한 접근을 기본으로 하는데,&lt;/p&gt;
&lt;p&gt;내 맥북에는 그런 이름의 인터페이스가 존재하지 않았다.&lt;/p&gt;
&lt;p&gt;따라서 ifconfig(&lt;strong&gt;i&lt;/strong&gt;nter&lt;strong&gt;f&lt;/strong&gt;ace &lt;strong&gt;config&lt;/strong&gt;uration) 명령어를 통해 확인한&lt;/p&gt;
&lt;p&gt;맥북의 네트워크 인터페이스와 각각의 역할에 대해 이해한 바를 정리하는 목적으로 작성하는 글이다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;명칭과 역할&lt;/h2&gt;
&lt;p&gt;먼저, 모든 네트워크 인터페이스의 이름만을 확인하기 위해 아래와 같은 명령어를 사용할 수 있다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ ifconfig -l&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;해당 명령어를 내 터미널에 실행했을 때 실제로 출력된 결과는 아래와 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1561&quot; data-origin-height=&quot;58&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ciRbKV/btsbTupMT6K/nKvBJ6vXMwQ9DYAZ0wisi0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ciRbKV/btsbTupMT6K/nKvBJ6vXMwQ9DYAZ0wisi0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ciRbKV/btsbTupMT6K/nKvBJ6vXMwQ9DYAZ0wisi0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FciRbKV%2FbtsbTupMT6K%2FnKvBJ6vXMwQ9DYAZ0wisi0%2Fimg.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; loading=&quot;lazy&quot; width=&quot;1561&quot; height=&quot;58&quot; data-origin-width=&quot;1561&quot; data-origin-height=&quot;58&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;각 인터페이스의 자세한 정보를 확인하기 위해서는 아래의 명령어를 실행한다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ ifconfig -v [인터페이스이름]

### 예시
$ ifconfig -v lo0&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;각각의 의미와 역할을 정리해보았다. 역할을 이해하는 정도의 피상적인 수준에서 작성했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-04-24 오후 9.56.24.png&quot; data-origin-width=&quot;1712&quot; data-origin-height=&quot;1086&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwiEuo/btscjllN4ui/gb0bkMPSrpFuQnHZqULeVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwiEuo/btscjllN4ui/gb0bkMPSrpFuQnHZqULeVk/img.png&quot; data-alt=&quot;출처: http://newosxbook.com/bonus/vol1ch16.html&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwiEuo/btscjllN4ui/gb0bkMPSrpFuQnHZqULeVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwiEuo%2FbtscjllN4ui%2Fgb0bkMPSrpFuQnHZqULeVk%2Fimg.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; loading=&quot;lazy&quot; width=&quot;1712&quot; height=&quot;1086&quot; data-filename=&quot;스크린샷 2023-04-24 오후 9.56.24.png&quot; data-origin-width=&quot;1712&quot; data-origin-height=&quot;1086&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: http://newosxbook.com/bonus/vol1ch16.html&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3&gt;lo0&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Lo&lt;/strong&gt;opback인터페이스. 루프백이라는 용어 자체는 전기신호나 디지털 데이터 스트림 등이 원래의 장치로 돌아가는 것을 의미하며, 주로 전송 시설의 테스트 수단으로 사용된다고 한다. TCP/IP에서 루프백은 웹서버를 띄우고 테스트할 때 자주 사용하는 127.0.0.1이라는 IP주소나 localhost라는 도메인 네임이 자기 자신(접근을 시도한 호스트)으로 되돌아 가게 해주는 역할을 한다. 이는 &amp;#39;물리적으로 존재하는 NIC(Network Interface Card)가 아니라 논리적인 인터페이스&amp;#39;이며 인터넷 프로토콜(IP)이 지원하는 기능이다.&lt;/p&gt;
&lt;p&gt;루프백 인터페이스가 동작하는 방식에대해 이해한 내용은 다음과 같다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;L7(애플리케이션)에서 주소가 포함된 데이터를 L4(TCP)로 내려주면,&lt;br&gt;TCP는 Encapsulation 후 이를 L3(IP)로 내려준다.&lt;br&gt;이 때 IP 주소가 127.0.0.1(IPv4) (또는 ::1(IPv6) 또는 도메인 이름이 localhost)이라면 해당 패킷이 NIC를 거쳐 L2로 전달되는 것이 아닌, 그대로 L4로 올려보내져서 작업을 수행한다.&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;결과적으로 TCP/IP의 lo0 루프백 인터페이스란 L2, L1와 네트워크를 거치지 않고 OS의 네트워킹 소프트웨어만을 통하며, 같은 기기에서 클라이언트와 서버가 동작할 때 통신할 수 있는 간단한 방법을 제공하는 것이 그 목적인 네트워크 인터페이스라고 할 수 있겠다.&lt;/p&gt;
&lt;h3&gt;gif0&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;G&lt;/strong&gt;eneric Tunnel &lt;strong&gt;I&lt;/strong&gt;nter&lt;strong&gt;f&lt;/strong&gt;ace&lt;/p&gt;
&lt;p&gt;네트워크의 일반적인 &lt;em&gt;터널링&lt;/em&gt; 의사 장치(pseudo-device)라고 하는데, 정확히 어떤 의미인지 잘 와닿지는 않는다.다만 &lt;a href=&quot;https://net-study.club/entry/GRE-Tunnel-Generic-Routing-Encapsulation&quot;&gt;GRE(Generic Routing Encapsulation)&lt;/a&gt;라는 프로토콜과 유사하다는 설명이 있어 이를 참고하였다. 자세한 내용은 &lt;a href=&quot;https://docs.netgate.com/pfsense/en/latest/interfaces/gif.html&quot;&gt;여기&lt;/a&gt;서 확인할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;터널링&lt;/em&gt;(Tunneling)은 해당 네트워크에서 지원하지 않는 프로토콜을 사용하여, 한 네트워크에서 다른 네트워크로 패킷을 이동시키는(전송하는) 방법이라고 한다. &lt;em&gt;&amp;#39;__지원하지 않는 프로토콜&amp;#39;&lt;/em&gt; 을 이용하기 위해 패킷을 캡슐화하는데, 여기서 말하는 캡슐화란 OSI 계층 구조의 상위 계층에서 하위 계층으로 데이터를 전달하며 일어나는 캡슐화와 같은 의미로 원본 패킷을 페이로드로 하는 새로운 패킷을 만드는 방식을 말한다. 다만 터널링에서의 캡슐화가 항상 상위-하위 계층간의 전송만을 위한 것은 아니다. 터널링은 같은 계층 간의 데이터 전송을 위해서도 캡슐화를 사용한다.&lt;/p&gt;
&lt;p&gt;GRE는 이러한 터널링 프로토콜로 암호화 없이 두 호스트 간에 트래픽을 터널링하는 수단이며, GIF는 GRE와 유사하지만 덜 범용적이고 몇가지 세부적인 특징에서 차이가 있는 프로토콜이라고 이해했다.&lt;/p&gt;
&lt;p&gt;이 부분은 네트워크에 대해 좀 더 공부해야 정확히 알 수 있을 것 같다.&lt;/p&gt;
&lt;h3&gt;stf0&lt;/h3&gt;
&lt;p&gt;6(&lt;strong&gt;s&lt;/strong&gt;ix)&lt;strong&gt;t&lt;/strong&gt;o4(&lt;strong&gt;f&lt;/strong&gt;our) tunnel interface&lt;/p&gt;
&lt;p&gt;IPv4의 캡슐화를 통해 &amp;quot;6to4&amp;quot; IPv6를 지원하는 인터페이스이다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/6to4&quot;&gt;&lt;strong&gt;6to4&lt;/strong&gt;&lt;/a&gt;는 IPv4에서 IPv6로의 마이그레이션을 위한 인터넷 전환 메커니즘이다.&lt;/p&gt;
&lt;p&gt;IPv4와 IPv6가 공존하는 동안 두 프로토콜간의 통신을 지정한 &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc3056&quot;&gt;RFC3056&lt;/a&gt;의 매커니즘을 구현하며,&lt;/p&gt;
&lt;p&gt;캡슐화를 통해 IPv4의 주소를 IPv6네트워크에서 이용할 수 있도록 바꿔준다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;423&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CJVZF/btsbT2UaTy3/u4ok4bkZBELVTWy5D4hU0K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CJVZF/btsbT2UaTy3/u4ok4bkZBELVTWy5D4hU0K/img.png&quot; data-alt=&quot;출처: By Mro - Own work, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=10461514&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CJVZF/btsbT2UaTy3/u4ok4bkZBELVTWy5D4hU0K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCJVZF%2FbtsbT2UaTy3%2Fu4ok4bkZBELVTWy5D4hU0K%2Fimg.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; loading=&quot;lazy&quot; width=&quot;487&quot; height=&quot;322&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;423&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: By Mro - Own work, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=10461514&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;stf0&lt;/strong&gt;는 이를 위한 인터페이스로, 위 그림처럼 IPv6 Island의 경계에 있는 &lt;strong&gt;6to4 라우터&lt;/strong&gt;에서 사용되는 인터페이스 이다.&lt;/p&gt;
&lt;h3&gt;anpi#(0~1)&lt;/h3&gt;
&lt;p&gt;식별자의 유래가 정확히 무엇인지, 또한 어떠한 인터페이스인지 알 수 있는 사용 예시나 설명을 찾아보았지만 확인하지 못했다.&lt;/p&gt;
&lt;p&gt;리눅스/유닉스 계열의 네트워크 인터페이스 카드(NIC)를 나타내는 인터페이스 이름 중 하나라는 것 정도만을 알 수 있었다.&lt;/p&gt;
&lt;h3&gt;en#(0~4)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;E&lt;/strong&gt;ther&lt;strong&gt;n&lt;/strong&gt;et&lt;/p&gt;
&lt;p&gt;이더넷 네트워크 인터페이스. IP를 사용하여 이더넷을 통해 인터넷과 연결하는 네트워크 인터페이스이다.&lt;/p&gt;
&lt;p&gt;내가 찾던 eth# 인터페이스와 같은 역할을 하며&lt;/p&gt;
&lt;p&gt;이더넷을 전송 매커니즘으로 사용하여 컴퓨터를 LAN(Local Area Network)에 연결한다.&lt;/p&gt;
&lt;p&gt;각각의 타입은 다음과 같았다.&lt;/p&gt;
&lt;p&gt;en0: WI-FI&lt;/p&gt;
&lt;p&gt;en1, en2: IP over Thunderbolt&lt;/p&gt;
&lt;p&gt;en3, en4: USB Ethernet&lt;/p&gt;
&lt;h3&gt;bridge0&lt;/h3&gt;
&lt;p&gt;브릿지 네트워킹 인터페이스&lt;/p&gt;
&lt;p&gt;리눅스 계열에서 제공하는 가상 네트워크 인터페이스이며 맥에서는 기본적으로 Thunderbolt 브릿지로 설정되어있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-04-24 오후 5.24.04.png&quot; data-origin-width=&quot;694&quot; data-origin-height=&quot;100&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNpcGC/btscyYot8fF/TnNBcYoh8KAdr3WOE0lJn0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNpcGC/btscyYot8fF/TnNBcYoh8KAdr3WOE0lJn0/img.png&quot; data-alt=&quot;BSD는 Berkeley Software Distribution의 약자로 버클리에서 개발한 유닉스 운영체제를 의미한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNpcGC/btscyYot8fF/TnNBcYoh8KAdr3WOE0lJn0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNpcGC%2FbtscyYot8fF%2FTnNBcYoh8KAdr3WOE0lJn0%2Fimg.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; loading=&quot;lazy&quot; width=&quot;423&quot; height=&quot;61&quot; data-filename=&quot;스크린샷 2023-04-24 오후 5.24.04.png&quot; data-origin-width=&quot;694&quot; data-origin-height=&quot;100&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;BSD는 Berkeley Software Distribution의 약자로 버클리에서 개발한 유닉스 운영체제를 의미한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;브릿지는 두 개 이상의 네트워크를 연결하고, 연결된 네트워크간에는 패킷을 전달 할 수 있다.&lt;/p&gt;
&lt;p&gt;여러 네트워크를 연결할 수 있기 때문에 다양한 작업이 가능하다.&lt;/p&gt;
&lt;p&gt;외부와 연결을 위해 항상 브릿지를 거쳐가게 하며 패킷 필터링 등을 통해 &lt;a href=&quot;https://cyuu.tistory.com/11&quot;&gt;브릿지 방화벽&lt;/a&gt;을 구축하는것도 가능하며&lt;/p&gt;
&lt;p&gt;모든 내부 네트워크를 모니터링 하기 위한 수단으로 사용하기도 한다.&lt;/p&gt;
&lt;p&gt;또 브릿지를 이용해서 하나의 장치에서 동작하는 여러 가상 머신(또는 컨테이너)이 네트워크 통신을 할 수 있다고 한다.&lt;/p&gt;
&lt;p&gt;맥에서는 브릿지를 이용해서 실제 인터페이스인 Thunderbolt를 통해 서로 다른 두 Mac 기기간의 IP 통신을 가능하게 해준다고 설명한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-04-24 오후 6.57.23.png&quot; data-origin-width=&quot;908&quot; data-origin-height=&quot;232&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pcXhp/btscaZXv7HJ/vm9RmvwZEkHRzeMHQSF0zk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pcXhp/btscaZXv7HJ/vm9RmvwZEkHRzeMHQSF0zk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pcXhp/btscaZXv7HJ/vm9RmvwZEkHRzeMHQSF0zk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpcXhp%2FbtscaZXv7HJ%2Fvm9RmvwZEkHRzeMHQSF0zk%2Fimg.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; loading=&quot;lazy&quot; width=&quot;422&quot; height=&quot;108&quot; data-filename=&quot;스크린샷 2023-04-24 오후 6.57.23.png&quot; data-origin-width=&quot;908&quot; data-origin-height=&quot;232&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;다른 네트워크 인터페이스와 다르게 member라는 프로퍼티(?)를 가지며, 기본적으로 en1, en2 두개의 인터페이스를 멤버로 하고 있는것으로 보아 두개의 물리적인 인터페이스를 이용해서 네트워크 통신이 가능하도록 구성함을 확인 할 수 있었다.&lt;/p&gt;
&lt;h3&gt;ap1&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;A&lt;/strong&gt;ccess &lt;strong&gt;P&lt;/strong&gt;oint&lt;/p&gt;
&lt;p&gt;장치(맥북)의 연결을 공유하기 위해서 장치(맥북)를 무선 호스트로 사용할 때 이용하는 인터페이스라고 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;404&quot; data-origin-height=&quot;308&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cAIuID/btscvxFFwhE/np3f2lyzqZT6AkT53gPER0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cAIuID/btscvxFFwhE/np3f2lyzqZT6AkT53gPER0/img.webp&quot; data-alt=&quot;출처: https://networkencyclopedia.com/access-point/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cAIuID/btscvxFFwhE/np3f2lyzqZT6AkT53gPER0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcAIuID%2FbtscvxFFwhE%2Fnp3f2lyzqZT6AkT53gPER0%2Fimg.webp&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; loading=&quot;lazy&quot; width=&quot;404&quot; height=&quot;308&quot; data-origin-width=&quot;404&quot; data-origin-height=&quot;308&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://networkencyclopedia.com/access-point/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;그림과 같이, 유선 LAN에 무선 스테이션이 연결할 수 있도록 _접근 가능한 지점_으로서 기능하기 때문에 Access Point라는 이름을 가진다.&lt;/p&gt;
&lt;h3&gt;awdl0&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;A&lt;/strong&gt;pple &lt;strong&gt;W&lt;/strong&gt;ireless &lt;strong&gt;D&lt;/strong&gt;irect &lt;strong&gt;L&lt;/strong&gt;ink(AWDL) 기술에서 사용되는 인터페이스이다.&lt;/p&gt;
&lt;p&gt;AirDrop, AirPlay, Handoff, Continuity 등의 Apple의 기능을 사용할 때 사용되는 애플의 자체적인 인터페이스이다.&lt;/p&gt;
&lt;h3&gt;llw0&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;L&lt;/strong&gt;ow-&lt;strong&gt;l&lt;/strong&gt;atency &lt;strong&gt;W&lt;/strong&gt;LAN Interface. Used by the Skywalk system.&lt;/p&gt;
&lt;p&gt;대기 시간이 짧은 특수한 종류의 WiFi 연결을 위한 네트워크 인터페이스라고 한다.&lt;/p&gt;
&lt;p&gt;Skywalk system??&lt;/p&gt;
&lt;p&gt;아무리 검색해도 관련 정보가 나오지 않았는데,&lt;/p&gt;
&lt;p&gt;애플의 개발자 포럼에서 &lt;a href=&quot;https://developer.apple.com/forums/thread/698130&quot;&gt;같은 궁금증을 가지는 사람이 쓴 글&lt;/a&gt;의 &lt;a href=&quot;http://newosxbook.com/bonus/vol1ch16.html&quot;&gt;답글에 작성된 링크&lt;/a&gt;를 통해 관련된 내용을 확인할 수 있었다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;...&lt;br&gt;The second is the mysterious &lt;strong&gt;Skywalk&lt;/strong&gt;, and its nexus and channel objects. This is an entire subsystem which is not only undocumented, but &lt;strong&gt;intentionally left out&lt;/strong&gt; of XNU&amp;#39;s public sources.&lt;br&gt;...&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;재밌는 얘기가 나왔다.&lt;/p&gt;
&lt;p&gt;조금 더 확인해본 바로는&lt;/p&gt;
&lt;p&gt;애플의 모든 운영체제는 Darwin이라는 운영체제를 기반으로 하고,&lt;/p&gt;
&lt;p&gt;Darwin의 커널은 XNU이며, 이 XNU의 네트워크 서브 시스템이 Skywalk라고 한다.&lt;/p&gt;
&lt;p&gt;관련 유틸인 skywalkctl(8)의 매뉴얼은 &lt;a href=&quot;https://keith.github.io/xcode-man-pages/skywalkctl.8.html&quot;&gt;여기&lt;/a&gt;서 확인 가능하다.&lt;/p&gt;
&lt;h3&gt;utun#(0~6)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;U&lt;/strong&gt;ser &lt;strong&gt;Tun&lt;/strong&gt;neling interface&lt;/p&gt;
&lt;p&gt;유저 스페이스(User space)와 커널 스페이스(Kernel space) 간의 터널링을 담당하는 가상 네트워크 인터페이스이며 VPN에 이용된다. utun0 인터페이스를 직접 언급하는 자료는 거의 없었으나, 리눅스의 tun과 유사한 역할과 기능을 지원한다고 하여 리눅스의 tun이라는 가상 네트워크 인터페이스가 어떤식으로 VPN에 이용되는지 같이 알아보았다.&lt;/p&gt;
&lt;p&gt;VPN(Virtual Private Network; 가상 사설 망)은 public 네트워크에서 패킷의 암호화 작업과 터널링을 통해 가상의 사설망을 구축하는 방법 또는 그러한 통신망이다. 가상의 사설망을 구축한다는 개념 자체는 터널링만으로도 가능 하지만, 사설망을 구축하는 의도는 외부의 공공 망과의 분리이며, 따라서 전송하는 데이터를 외부에서 확인할 수 없도록 하는 암호화 작업이 대부분 필수적이다.&lt;/p&gt;
&lt;p&gt;사이트와 사이트 간의 VPN 구성(Site-to-Site(또는 Gateway) VPN)의 경우에는 연결을 원하는 각 사이트의 게이트웨이 간에 VPN 터널을 생성한다. 같은 회사에서 물리적으로 충분히 떨어져 있는 여러 지점간의 통신을 위해 사설망을 구축하는 상황을 생각할 수 있겠다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;888&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IaKhB/btscFCGRrVx/ovVq0vU70ZFAKvsz78Kzkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IaKhB/btscFCGRrVx/ovVq0vU70ZFAKvsz78Kzkk/img.png&quot; data-alt=&quot;출처 : https://commons.wikimedia.org/wiki/File:Site-to-site_VPN-en.svg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IaKhB/btscFCGRrVx/ovVq0vU70ZFAKvsz78Kzkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIaKhB%2FbtscFCGRrVx%2FovVq0vU70ZFAKvsz78Kzkk%2Fimg.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; loading=&quot;lazy&quot; width=&quot;434&quot; height=&quot;301&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;888&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 : https://commons.wikimedia.org/wiki/File:Site-to-site_VPN-en.svg&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;개별 호스트가 사이트에 VPN 연결을 하려는 경우(Host(또는 Client)-to-Site(또는 Host-to-Gateway) VPN)에는 접속자 단위로 VPN 터널이 생성되어야 한다. 이는 원격으로 근무하는 직원이 회사의 로컬망에 접근해서 작업을 진행해야 하는 경우를 예로 들 수 있을 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;962&quot; data-origin-height=&quot;199&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sWvlV/btscGJFW5aI/n6nfHa641xX47404OOmed0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sWvlV/btscGJFW5aI/n6nfHa641xX47404OOmed0/img.png&quot; data-alt=&quot;출처 : https://www.tp-link.com/kr/blog/1268/vpn-%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8%EB%8A%94-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80%EC%9A%94-tp-link-%EA%B3%B5%EC%9C%A0%EA%B8%B0%EC%97%90-vpn-%EC%84%A4%EC%B9%98%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sWvlV/btscGJFW5aI/n6nfHa641xX47404OOmed0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsWvlV%2FbtscGJFW5aI%2Fn6nfHa641xX47404OOmed0%2Fimg.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; loading=&quot;lazy&quot; width=&quot;565&quot; height=&quot;117&quot; data-origin-width=&quot;962&quot; data-origin-height=&quot;199&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 : https://www.tp-link.com/kr/blog/1268/vpn-%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8%EB%8A%94-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80%EC%9A%94-tp-link-%EA%B3%B5%EC%9C%A0%EA%B8%B0%EC%97%90-vpn-%EC%84%A4%EC%B9%98%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Host-to-Site VPN의 경우 일반 PC의 네트워크 트래픽을 VPN Server로 전송해야 하기 때문에 VPN Client 프로그램의 설치가 필요하다. VPN Client 프로그램이 실행되면, VPN Server와의 터널을 만들고 해당 PC에서 전송하는 모든 네트워크 트래픽을 캡쳐하여 VPN 터널을 통해 VPN Server로 전송한다.&lt;/p&gt;
&lt;p&gt;네트워크 트래픽을 캡쳐한다는것은 운영체제에서 발생하는 모든 네트워크 트래픽을 가로채서 VPN 터널을 통해 전송되도록 리디렉션 해준다는 것이다. 이는 User 레벨의 어플리케이션인 VPN Client가 독단적으로 수행할 수 있는 것이 아니며, 커널과의 긴밀한 협력이 필요한 작업이다. 커널과의 협력과 동시에 터널링을 통해 VPN 터널로의 전송을 가능하게 해주는것이 바로 tun과 tap이라는 이름의 가상 네트워크 인터페이스(혹은 디바이스)이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;556&quot; data-origin-height=&quot;254&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cFQcQm/btscHMvlqGA/0caE7qR0AhSbw0knnNMtq0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cFQcQm/btscHMvlqGA/0caE7qR0AhSbw0knnNMtq0/img.png&quot; data-alt=&quot;어플리케이션과 NIC를 제외한 TCP, IP는 커널 영역에 속하는 네트워크 스택의 레이어이다. (출처 : https://d2.naver.com/helloworld/47667)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cFQcQm/btscHMvlqGA/0caE7qR0AhSbw0knnNMtq0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcFQcQm%2FbtscHMvlqGA%2F0caE7qR0AhSbw0knnNMtq0%2Fimg.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; loading=&quot;lazy&quot; width=&quot;429&quot; height=&quot;196&quot; data-origin-width=&quot;556&quot; data-origin-height=&quot;254&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;어플리케이션과 NIC를 제외한 TCP, IP는 커널 영역에 속하는 네트워크 스택의 레이어이다. (출처 : https://d2.naver.com/helloworld/47667)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;tun/tap은 리눅스에서 제공하는 가상 네트워크 인터페이스(디바이스)로서 소프트웨어적으로 구현된 가상의 네트워크 장치이다. tun은 OSI L3(Network)인터페이스의 에뮬레이션이고, tap은 L2(Data Link)인터페이스의 에뮬레이션이다.&lt;/p&gt;
&lt;p&gt;즉, tun은 3계층의 패킷을 터널링 할 수 있고 tap은 2계층의 패킷을 터널링 할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;742&quot; data-origin-height=&quot;620&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cnD7N3/btscBDsE75h/4mh1kKoWU4FEVSypA7BuYk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cnD7N3/btscBDsE75h/4mh1kKoWU4FEVSypA7BuYk/img.png&quot; data-alt=&quot;출처 : By Ikluft - Own work, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=80385349&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cnD7N3/btscBDsE75h/4mh1kKoWU4FEVSypA7BuYk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcnD7N3%2FbtscBDsE75h%2F4mh1kKoWU4FEVSypA7BuYk%2Fimg.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; loading=&quot;lazy&quot; width=&quot;393&quot; height=&quot;328&quot; data-origin-width=&quot;742&quot; data-origin-height=&quot;620&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 : By Ikluft - Own work, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=80385349&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;두 가상 장치는 전송받은 패킷을 사용자 공간(User Space)에서 실행되는 프로세스에게 전달한다. 반대로 사용자 공간의 프로세스가 tun 또는 tap으로 패킷을 전달할 수도 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;509&quot; data-origin-height=&quot;583&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GqBR4/btscCBn7L6E/M5GIGp0cCjmhLNI5XP5r2K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GqBR4/btscCBn7L6E/M5GIGp0cCjmhLNI5XP5r2K/img.png&quot; data-alt=&quot;출처 : https://tttsss77.tistory.com/235&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GqBR4/btscCBn7L6E/M5GIGp0cCjmhLNI5XP5r2K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGqBR4%2FbtscCBn7L6E%2FM5GIGp0cCjmhLNI5XP5r2K%2Fimg.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; loading=&quot;lazy&quot; width=&quot;326&quot; height=&quot;373&quot; data-origin-width=&quot;509&quot; data-origin-height=&quot;583&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 : https://tttsss77.tistory.com/235&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;정리하자면, tun은 Host-to-Site VPN에서 VPN Client가 VPN Server와의 통신을 위한 터널링에 사용되며, User Space의 어플리케이션인 VPN Client가 모든 네트워크 트래픽을 컨트롤 하기 위해 커널과 통신하는 가상 네트워크 인터페이스라고 이해할 수 있을 것 같다.&lt;/p&gt;
&lt;p&gt;아직은 실제로 VPN을 구성해본적은 없어서, 터널이 구성된 뒤 tun이 실제로 어떤 방식으로 유저-커널 사이에서 패킷을 전송하고 네트워크 트래픽을 캡쳐하는 지 등 구체적인 동작 과정을 알기 위해서는 OpenVPN을 이용한 구현을 직접 해보며 공부가 좀 더 필요할 것 같다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;.&lt;/h2&gt;
&lt;p&gt;쓰다보니 애매하게 알고있는 것들이 많이 있었다. 잘 모른는건 최대한 알아보려고 했으나 아직까지 모호한 것들이 남아있다.&lt;/p&gt;
&lt;p&gt;네트워크도 재밌는것같다.&lt;/p&gt;
&lt;hr&gt;
&lt;details&gt;
&lt;summary&gt;참고 출처&lt;/summary&gt;

&lt;p&gt;  &lt;a href=&quot;https://www.whatap.io/ko/blog/11/&quot;&gt;리눅스 네트워크 관리에 필요한 사용법 11가지 | 와탭 블로그&lt;/a&gt;&lt;br&gt;  &lt;a href=&quot;https://stackoverflow.com/questions/29958143/what-are-en0-en1-p2p-and-so-on-that-are-displayed-after-executing-ifconfig&quot;&gt;https://stackoverflow.com/questions/29958143/what-are-en0-en1-p2p-and-so-on-that-are-displayed-after-executing-ifconfig&lt;/a&gt;&lt;br&gt;  &lt;a href=&quot;https://kibbomi.tistory.com/268&quot;&gt;TCPdump 활용하기 (명령어 및 사용법)&lt;/a&gt;&lt;br&gt;  &lt;a href=&quot;https://www.juniper.net/documentation/kr/ko/software/junos/interfaces-fundamentals/topics/topic-map/loopback-interfaces.html&quot;&gt;https://www.juniper.net/documentation/kr/ko/software/junos/interfaces-fundamentals/topics/topic-map/loopback-interfaces.html&lt;/a&gt;&lt;br&gt;  &lt;a href=&quot;https://www.cloudflare.com/ko-kr/learning/network-layer/what-is-tunneling/&quot;&gt;https://www.cloudflare.com/ko-kr/learning/network-layer/what-is-tunneling/&lt;/a&gt;&lt;br&gt;  &lt;a href=&quot;https://velog.io/@koo8624/Linux-Linux-Virtual-networking-Interface&quot;&gt;https://velog.io/@koo8624/Linux-Linux-Virtual-networking-Interface&lt;/a&gt;&lt;br&gt;  &lt;a href=&quot;https://superuser.com/questions/1681992/why-the-bridge0-has-a-ethernet-port-address-it-refers-to-what&quot;&gt;https://superuser.com/questions/1681992/why-the-bridge0-has-a-ethernet-port-address-it-refers-to-what&lt;/a&gt;&lt;br&gt;  &lt;a href=&quot;https://apple.stackexchange.com/questions/394047/what-is-the-network-interface-llw0&quot;&gt;https://apple.stackexchange.com/questions/394047/what-is-the-network-interface-llw0&lt;/a&gt;&lt;br&gt;  &lt;a href=&quot;https://www.joinc.co.kr/w/Site/cloud/NetworkVirtualization/tunneling&quot;&gt;https://www.joinc.co.kr/w/Site/cloud/NetworkVirtualization/tunneling&lt;/a&gt;&lt;br&gt;  &lt;a href=&quot;http://www.joinc.co.kr%5D(https://www.joinc.co.kr/w/Site/cloud/NetworkVirtualization/tunneling)&quot;&gt;www.joinc.co.kr](https://www.joinc.co.kr/w/Site/cloud/NetworkVirtualization/tunneling)&lt;/a&gt;&lt;br&gt;  &lt;a href=&quot;https://www.geeksforgeeks.org/tunneling/&quot;&gt;https://www.geeksforgeeks.org/tunneling/&lt;/a&gt;&lt;br&gt;  &lt;a href=&quot;https://ebrary.net/26730/computer_science/remote_access_host-to-site&quot;&gt;https://ebrary.net/26730/computer_science/remote_access_host-to-site&lt;/a&gt;&lt;br&gt;  &lt;a href=&quot;https://www.joinc.co.kr/w/Site/System_management/VPN/OpenVPN&quot;&gt;https://www.joinc.co.kr/w/Site/System_management/VPN/OpenVPN&lt;/a&gt;&lt;br&gt;  &lt;a href=&quot;https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&amp;amp;blogId=rpg2003a&amp;amp;logNo=221209134202&quot;&gt;https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&amp;amp;blogId=rpg2003a&amp;amp;logNo=221209134202&lt;/a&gt;&lt;/p&gt;
&lt;/details&gt;</description>
      <category>CS/네트워크</category>
      <author>완성</author>
      <guid isPermaLink="true">https://contrabass.tistory.com/127</guid>
      <comments>https://contrabass.tistory.com/127#entry127comment</comments>
      <pubDate>Sun, 23 Apr 2023 20:02:36 +0900</pubDate>
    </item>
    <item>
      <title>[RBTree lab] ③ Erase</title>
      <link>https://contrabass.tistory.com/123</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;586&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blh2yR/btr6qN2wWcN/DDozo0zk57kr2Dlakcn8S1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blh2yR/btr6qN2wWcN/DDozo0zk57kr2Dlakcn8S1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blh2yR/btr6qN2wWcN/DDozo0zk57kr2Dlakcn8S1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fblh2yR%2Fbtr6qN2wWcN%2FDDozo0zk57kr2Dlakcn8S1%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;586&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;586&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h1 id=&quot;삭제&quot;&gt;삭제&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;노드의 삭제는 다음과 같은 과정을 거쳐서 일어난다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 삭제 대상 노드(target)를 트리에서 제거한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. RBTree의 조건에 맞게 &lt;span&gt;트리를&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;조정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 삭제 대상 노드(target)를 트리에서 제거&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;삭제 자체는 BST의 삭제와 동일하게 진행된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;주어진 target이 항상 트리 내에 존재하는,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;sentinel이 아닌&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;노드라고 할 때,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;target 노드가 제거된다는 것은&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;target의 연결 관계가 제거되고,&amp;nbsp;트리에서 &lt;span&gt;target이 차지하고 있던 위치에 다른 노드가 위치하게 되는 것을 의미한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RB Tree에서는 3가지 경우를 나누어서 노드의 삭제를 진행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. target의 오른쪽 자식이 nil인 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. target의 왼쪽 자식이 nil인 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. target의 두 자식이 모두 nil이 아닌 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1, 2번의 경우에는 각각 왼쪽, 오른쪽 자식(nil인 자식의 반대쪽 자식)이 target의 위치를 대체하게 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3번의 경우는 조금 복잡한데,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;target의 오른쪽 자식을 루트 노드로 하는 서브트리에서 가장 작은 값을 가지는 노드가 target의 위치를 대체하게 하거나,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;target의 왼쪽 자식을 루트 노드로 하는 서브트리에서 가장 큰 값을 가지는 노드가 target의 위치를 대체하게 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-03-28 오후 5.58.41.png&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;706&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bmZroL/btr6BgCJorf/5FfZEdT1r0kUQ2HxPjWHq1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bmZroL/btr6BgCJorf/5FfZEdT1r0kUQ2HxPjWHq1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bmZroL/btr6BgCJorf/5FfZEdT1r0kUQ2HxPjWHq1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbmZroL%2Fbtr6BgCJorf%2F5FfZEdT1r0kUQ2HxPjWHq1%2Fimg.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; loading=&quot;lazy&quot; width=&quot;457&quot; height=&quot;336&quot; data-filename=&quot;스크린샷 2023-03-28 오후 5.58.41.png&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;706&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 이유는, 위 그림과 같이 BST의 정의에 인한 것인데,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이진 탐색 트리에서 어떤 노드 a의 좌, 우 자식 서브트리의 노드들은 모두 a보다 작은값을 가지거나, a보다 큰 값을 가지기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RBTree 또한 BST의 일종이므로 같은 조건을 만족하고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;여기서 구현한&lt;span&gt;&amp;nbsp;규칙은 왼쪽 자식은 현재 노드보다 작은 값을, 오른쪽 자식은 현재 노드보다 큰 값을 가지도록 구현하였다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;따라서 &quot;target의 오른쪽 서브 트리에서 가장 작은 값을 가지는 노드&quot;는 바꿔 말하면 &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;&quot;target의 자손 노드 중 target보다 큰 값을 가지는 노드들 중 가장 작은값을 가지는 노드&quot;이고,&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;반대의 경우인 &quot;target의 왼쪽 서브 트리에서 가장 큰 값을 가지는 노드&quot;는&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;target의 자손 노드 중 target보다 작은 값&lt;span&gt;을 가지는 노드들&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;중 가장 큰값을 가지는 노드&quot;인 것이다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 target의 자손 노드 중 target과 가장 가까운 값을 가지는 노드를 찾아내어&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;target의 위치를 대체하기 위한 과정이라고 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2954&quot; data-origin-height=&quot;1722&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvqe1T/btr6K2xZdF2/EtfKECPHxS8Pgm3NBtjzpk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvqe1T/btr6K2xZdF2/EtfKECPHxS8Pgm3NBtjzpk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvqe1T/btr6K2xZdF2/EtfKECPHxS8Pgm3NBtjzpk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbvqe1T%2Fbtr6K2xZdF2%2FEtfKECPHxS8Pgm3NBtjzpk%2Fimg.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; loading=&quot;lazy&quot; width=&quot;682&quot; height=&quot;398&quot; data-origin-width=&quot;2954&quot; data-origin-height=&quot;1722&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 id=&quot;-구현6-transplant&quot; data-ke-size=&quot;size20&quot;&gt;  구현(6) (transPlant)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 &quot;특정 노드의 위치를 새로운 노드가 대체하는&quot; 기능이 공통적으로 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 다음과 같은 함수를 작성한다.&lt;/p&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;void trans_plant(rbtree *t, node_t *old_node, node_t *new_node) {
    if (old_node-&amp;gt;parent == t-&amp;gt;nil) {
        t-&amp;gt;root = new_node;
    } else if (old_node == old_node-&amp;gt;parent-&amp;gt;left) {
        old_node-&amp;gt;parent-&amp;gt;left = new_node;
    } else {
        old_node-&amp;gt;parent-&amp;gt;right = new_node;
    }
    new_node-&amp;gt;parent = old_node-&amp;gt;parent;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 함수의 기능은 간단하다,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부모 노드와의 관계 설정을 통해&amp;nbsp;노드 old_node의 위치를 노드 new_node로 대체한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자식 노드는 신경쓰지 않고 단지 부모노드와의 관계만을 변경하는 것이며,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;old_node와 new_node의 위치를 바꾸는 것이 아님&lt;/b&gt;을 주의해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 id=&quot;-구현6-transplant&quot; data-ke-size=&quot;size20&quot;&gt;  구현(7) (subtree_min, subtree_max)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인자로 받은 노드(cursor)를 루트노드로 하는 서브트리에서 가장 작은값 또는 가장 큰 값을 찾는 함수를 구현했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;노드를 제거하는 경우 중 두 자식 노드가 모두 nil이 아닌 경우에&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;target노드를 대체할 노드를 찾기 위해 사용된다.&lt;/p&gt;
&lt;pre id=&quot;code_1679996110636&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;node_t *subtree_min(node_t *cursor, node_t *nil) {
    node_t *min = cursor;
    while (cursor != nil) {
        min = cursor;
        cursor = cursor-&amp;gt;left;
    }
    return min;
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1679996293568&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;node_t *subtree_max(node_t *cursor, node_t *nil) {
    node_t *max = cursor;
    while (cursor != nil) {
        max = cursor;
        cursor = cursor-&amp;gt;right;
    }
    return max;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 id=&quot;-구현7-erase&quot; data-ke-size=&quot;size20&quot;&gt;  구현(8) (erase) (노드의 삭제만 구현된 형태)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 노드를 삭제하는 erase함수이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞서 이야기 한 3가지 경우를 기준으로 삭제 방법이 다른것을 확인할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1679989598783&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int rbtree_erase(rbtree *t, node_t *target) {
    node_t *y = target;
    color_t y_color = y-&amp;gt;color;

    node_t *x;
    if (target-&amp;gt;left == t-&amp;gt;nil) {
        x = target-&amp;gt;right;
        trans_plant(t, target, target-&amp;gt;right);
    } else if (target-&amp;gt;right == t-&amp;gt;nil) {
        x = target-&amp;gt;left;
        trans_plant(t, target, target-&amp;gt;left);
    } else {
        /** case 1 **/
        /** 삭제 될 target의 자리를 right subtree의 min node로 대체 **/

        // y는 right subtree의 min node
        y = subtree_min(target-&amp;gt;right, t-&amp;gt;nil);
        y_color = y-&amp;gt;color;

        // y는 BST에서 가장 작은 노드이므로 항상 왼쪽 자식이 존재하지 않음(nil)
        // 따라서, x는 y의 하나뿐인 유효한 자식 노드이거나 또는 nil이다.
        x = y-&amp;gt;right;

        if (y-&amp;gt;parent == target) {  // y가 target의 오른쪽 자식인 경우
            x-&amp;gt;parent = y;
        } else {  // 그렇지 않을 경우
            // y의 자리는 y의 오른쪽 자식(유효한 노드 또는 nil임)이 대체하게 하고,
            // target의 오른쪽 자식과의 관계를 y가 대체한다.
            trans_plant(t, y, y-&amp;gt;right);
            y-&amp;gt;right = target-&amp;gt;right;
            y-&amp;gt;right-&amp;gt;parent = y;
        }
        // 드디어 target의 부모와의 관계를 y가 대체한다.
        trans_plant(t, target, y);

        // 또한, 왼쪽 자식과의 관계 또한 대체하며
        y-&amp;gt;left = target-&amp;gt;left;
        y-&amp;gt;left-&amp;gt;parent = y;

        // target이 제거됨으로서 생기는 규칙의 위배를 막기 위해
        // y의 color를 삭제된 target의 색으로 변경한다.
        y-&amp;gt;color = target-&amp;gt;color;
    }

    free(target);

    init_nil(t-&amp;gt;nil);

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;rbtree_erase 함수에서 사용되는 주요 변수의 이름과 역할은 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;y&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;삭제 대상(target의 두 자식 노드 중 하나가 nil일 때) 또는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이동 대상(target의 두 자식 노드 모두 nil이 아닐 때)인 노드이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;x&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;y의 원래 위치로 이동하여 y를 대체할 노드이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;x는 y의 하나뿐인 유효한 자식이거나, nil이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;y_color&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;y의 원래 색상을 저장한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #333333;&quot;&gt;y_color를 저장하는 이유에 대해서&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #fcfcfc;&quot;&gt;CLRS에서는 이렇게 설명한다.&lt;/span&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;Need to save&amp;nbsp;y&amp;rsquo;s original color (in&amp;nbsp;y-original-color) to test it at the end, because if it&amp;rsquo;s black, then removing or moving&amp;nbsp;y&amp;nbsp;could cause red-black properties to be violated.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #333333;&quot;&gt;즉, &lt;span style=&quot;background-color: #fcfcfc;&quot;&gt;삭제에서 제거 또는 이동 대상인&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #fcfcfc;&quot;&gt;노드 y의 색깔이&amp;nbsp;BLACK인 경우 RBTree 특성 위반의 원인이 될 가능성이 있기 때문이며&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc;&quot;&gt;이를 이용해서 뒤이어 설명할 erase_fixup 수행 여부를 결정하기 위함이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;left subtree의 max node로 대체하는 방식의 구현은 더보기&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1679997490380&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    node_t *y = target;
    color_t y_color = y-&amp;gt;color;

    node_t *x;
    if (target-&amp;gt;left == t-&amp;gt;nil) {
        x = target-&amp;gt;right;
        trans_plant(t, target, target-&amp;gt;right);
    } else if (target-&amp;gt;right == t-&amp;gt;nil) {
        x = target-&amp;gt;left;
        trans_plant(t, target, target-&amp;gt;left);
    } else {
        /** case 2 **/
        /** 삭제 될 target의 자리를 left subtree의 max node로 대체 **/
        y = subtree_max(target-&amp;gt;left, t-&amp;gt;nil);
        y_color = y-&amp;gt;color;
        x = y-&amp;gt;left;
        if (y-&amp;gt;parent == target) {
            x-&amp;gt;parent = y;
        } else {
            trans_plant(t, y, y-&amp;gt;left);
            y-&amp;gt;left = target-&amp;gt;left;
            y-&amp;gt;left-&amp;gt;parent = y;
        }
        trans_plant(t, target, y);
        y-&amp;gt;right = target-&amp;gt;right;
        y-&amp;gt;right-&amp;gt;parent = y;
        y-&amp;gt;color = target-&amp;gt;color;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. &lt;span&gt;RBTree의 조건에 맞게&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;트리를&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;조정하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 과정이 RBTree의 모든 기능 중 가장 까다로운 부분이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;y의 원래 색에 따라,&amp;nbsp;삭제 작업이 완료된 뒤 RBTree의 조건에 맞게 노드 위치의 조정이 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;조건을 위배하는 경우: y의 원래 색 == &lt;b&gt;BLACK&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;1. y의 색이&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;RED&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;2. y의 색이&amp;nbsp;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;BLACK&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자에게 제공될 모든 operation은 RBTree의 조건을 항상 만족하는 상태에서 시작한다는 전제 하에,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;색이 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;RED&lt;/b&gt;&lt;/span&gt;인 노드를 삭제하는 경우는 RBTree의 조건을 무너뜨리지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;양쪽 자식이 모두 &lt;b&gt;BLACK&lt;/b&gt;이었을 것이기 때문에(조건 4번)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;leaf로 가는 &lt;b&gt;BLACK&lt;/b&gt;&amp;nbsp;노드의 수가 변하지 않고(조건 5번),&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 삭제로 인해 조건 4번이 깨지는 것도 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 삭제된 노드의 색깔이 &lt;b&gt;BLACK&lt;/b&gt;인 경우에는 &lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;/span&gt;조건이 무너지는 경우가 발생할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 조건을 보자&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;1. 모든 노드는&amp;nbsp;RED&amp;nbsp;또는&amp;nbsp;BLACK&lt;br /&gt;2. 루트는&amp;nbsp;BLACK&lt;br /&gt;3. 모든 리프(NIL)는&amp;nbsp;BLACK&lt;br /&gt;4. 노드가&amp;nbsp;RED&amp;nbsp;이면 그 노드의 자식은 모두&amp;nbsp;BLACK&lt;br /&gt;5. 각 노드로부터 그 노드의 자손인 리프로 가는 경로들은 모두 같은 수의&amp;nbsp;BLACK&amp;nbsp;노드를 포함해야함&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약, &lt;span style=&quot;color: #333333;&quot;&gt;y가&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;BLACK&lt;/b&gt;인 노드라면, 각 조건에 대한 위배 여부는 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;1. 문제 없음&lt;br /&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;2. y가 루트노드, x가 &lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;RED&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;인 경우 루트가&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;RED&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가 되어&lt;/span&gt;&lt;/span&gt;&amp;nbsp;위배됨&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;3. 문제 없음&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;4. x와 x의 바뀐 부모노드가 모두 &lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;RED&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;인 경우 위배됨&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;5. y를 포함하고있던 경로에서 &lt;/span&gt;&lt;b&gt;BLACK&lt;/b&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;이 1개 부족하게되어 위배됨&lt;/span&gt;&lt;/blockquote&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;2, 4, 5번에서 발생하는 문제를 모두 해결하기 위해서는&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;x를 &lt;b&gt;BLACK&lt;/b&gt;으로 바꿔주면 된다.&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2번은 경우 루트가 &lt;b&gt;BLACK&lt;/b&gt;이 되어 위배가 사라지고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3번은 부모의 다른 자식 노드는 조건에 부합할 것이고, x만 &lt;b&gt;BLACK&lt;/b&gt;이 되면 해결된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5번 또한 &lt;b&gt;BLACK&lt;/b&gt;이 하나 생겨서 괜찮다...?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5번은 안괜찮다. 언제 안괜찮냐, &lt;span style=&quot;background-color: #ffc9af;&quot;&gt;x의 색깔이 원래&amp;nbsp;&lt;b&gt;BLACK&lt;/b&gt;인 경우&lt;/span&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 경우는 5번이 위배되는 상황을 해결하지 못한다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;이중 흑색 노드&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 상황을 일반화 하여 해결하기 위한 개념적인 도구로서, &lt;b&gt;이중 흑색 노드&lt;/b&gt;(doubly black node)가 등장한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 2, 4, 5번 조건이 위배되는 상황을 해결하기 위해 'x의 색을 &lt;b&gt;BLACK&lt;/b&gt;으로 &quot;&lt;i&gt;바꿔준다&lt;/i&gt;&quot;' 고 하였는데,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 'x에게 &lt;b&gt;extra BLACK&lt;/b&gt;을 &quot;&lt;i&gt;추가한다&lt;/i&gt;&quot;'고 바꿔 표현해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때,&lt;b&gt; extra BLACK&lt;/b&gt;이 &lt;i&gt;추가&lt;/i&gt;된 노드의 색(상태)은 둘 중 하나이다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;1.&amp;nbsp;&lt;b&gt;doubly&lt;/b&gt; &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;BLACK&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;2.&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;RED&lt;/b&gt;&lt;/span&gt; &amp;amp;&amp;nbsp;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;BLACK&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;652&quot; data-origin-height=&quot;392&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkeE5d/btr6DKR9ZTz/KIM47PmJXBE20x3xzF96VK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkeE5d/btr6DKR9ZTz/KIM47PmJXBE20x3xzF96VK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkeE5d/btr6DKR9ZTz/KIM47PmJXBE20x3xzF96VK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkeE5d%2Fbtr6DKR9ZTz%2FKIM47PmJXBE20x3xzF96VK%2Fimg.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; loading=&quot;lazy&quot; width=&quot;652&quot; height=&quot;392&quot; data-origin-width=&quot;652&quot; data-origin-height=&quot;392&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;x의 색이 &lt;b&gt;doubly&lt;/b&gt;&lt;b&gt;&amp;nbsp;BLACK&amp;nbsp;&lt;/b&gt;또는 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;RED&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;&amp;amp;&lt;/b&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;BLACK&lt;/b&gt;이 되면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;y를 포함하던 경로에서 &lt;b&gt;BLACK&lt;/b&gt;이 하나 부족한 상황이 생기지 않게되고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5번 조건이 위배되는 상황은 사라지지만 1번 조건&amp;nbsp;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;&quot;&lt;/b&gt;&lt;/span&gt;모든 노드는&amp;nbsp;&lt;b&gt;BLACK&amp;nbsp;&lt;/b&gt;&lt;span&gt;또는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;&lt;span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;RED&lt;/span&gt;&quot;&lt;/span&gt;&lt;/b&gt;를 어기게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 해결하기 위해&amp;nbsp;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;x의 색이&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;RED&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&amp;nbsp;&lt;span style=&quot;color: #333333;&quot;&gt;&amp;amp;&lt;/span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;BLACK &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 되거나&amp;nbsp;&lt;/span&gt;또는 &lt;span style=&quot;background-color: #dddddd;&quot;&gt;x가&amp;nbsp;루트 노드&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 될 때까지&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;extra BLACK&lt;/b&gt;을 트리의 위로 이동시킨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약&amp;nbsp;&lt;span style=&quot;color: #333333;&quot;&gt;x의 색이&amp;nbsp;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;RED&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;&amp;amp;&lt;/b&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;BLACK&lt;/b&gt;이라면, 색을 &lt;b&gt;BLACK&lt;/b&gt;으로 바꾸고,&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;x가 루트 노드라면 &lt;b&gt;extra BLACK&lt;/b&gt;을 제거한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;extra BLACK&lt;/b&gt;을 트리의 위로 이동시키기 위해&amp;nbsp;x와 x의 형제노드인 w가 정의된다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;x는 항상 루트가 아닌 &lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;doubly BLACK&lt;/span&gt;&lt;/b&gt;&amp;nbsp;노드이다.&lt;br /&gt;w는 x의 형제 노드이며,&amp;nbsp;nil이 될 수 없다(x의 부모 노드에서 조건 5번 위배)&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;x가 왼쪽 자식인지, 오른쪽 자식인지에 따라 2가지 경우가 존재하고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;w의 색에 따라서 4가지 경우가 존재하여 총 8가지의 경우가 존재하여, 각 경우에 대한 해결 방법이 다르다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;x가 왼쪽 자식인 경우의 4가지 케이스만을 예로 들면, 다음과 같다.&lt;/p&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1640&quot; data-origin-height=&quot;1014&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BT8js/btr6EUgjagH/pdOL4umwXk12W7oflsUQDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BT8js/btr6EUgjagH/pdOL4umwXk12W7oflsUQDk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BT8js/btr6EUgjagH/pdOL4umwXk12W7oflsUQDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBT8js%2Fbtr6EUgjagH%2FpdOL4umwXk12W7oflsUQDk%2Fimg.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; loading=&quot;lazy&quot; width=&quot;1640&quot; height=&quot;1014&quot; data-origin-width=&quot;1640&quot; data-origin-height=&quot;1014&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 각 경우에 대해 알아보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Case 1&lt;/b&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1568&quot; data-origin-height=&quot;438&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ceh8HF/btr6JnVnzap/arn6OBWjrQkCX4dW1EqUiK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ceh8HF/btr6JnVnzap/arn6OBWjrQkCX4dW1EqUiK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ceh8HF/btr6JnVnzap/arn6OBWjrQkCX4dW1EqUiK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fceh8HF%2Fbtr6JnVnzap%2Farn6OBWjrQkCX4dW1EqUiK%2Fimg.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; loading=&quot;lazy&quot; width=&quot;1568&quot; height=&quot;438&quot; data-origin-width=&quot;1568&quot; data-origin-height=&quot;438&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;먼저, x의 부모노드의 색을 RED로, w의 색을 BLACK으로 바꿔준다.&lt;/p&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1558&quot; data-origin-height=&quot;378&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GjTmt/btr6GWqhCFD/K4Ycb6z9fLrOAqCKeTBnkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GjTmt/btr6GWqhCFD/K4Ycb6z9fLrOAqCKeTBnkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GjTmt/btr6GWqhCFD/K4Ycb6z9fLrOAqCKeTBnkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGjTmt%2Fbtr6GWqhCFD%2FK4Ycb6z9fLrOAqCKeTBnkk%2Fimg.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; loading=&quot;lazy&quot; width=&quot;1558&quot; height=&quot;378&quot; data-origin-width=&quot;1558&quot; data-origin-height=&quot;378&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음, x의 부모를 중심으로 left rotate를 진행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 상태에서 x의 new w는 rotate전의 w의 자식노드 중 하나이므로, 무조건 BLACK이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 w가 BLACK인 경우들을 확인해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Case 2&lt;/b&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1322&quot; data-origin-height=&quot;306&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/enALMv/btr6NYO4ZsH/Z12n3zcJu8Vwkbxgcc9vS0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/enALMv/btr6NYO4ZsH/Z12n3zcJu8Vwkbxgcc9vS0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/enALMv/btr6NYO4ZsH/Z12n3zcJu8Vwkbxgcc9vS0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FenALMv%2Fbtr6NYO4ZsH%2FZ12n3zcJu8Vwkbxgcc9vS0%2Fimg.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; loading=&quot;lazy&quot; width=&quot;1322&quot; height=&quot;306&quot; data-origin-width=&quot;1322&quot; data-origin-height=&quot;306&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;x가 가지고있던 extra BLACK을&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;w의 색을 RED로 바꾸고,&amp;nbsp;x가 x의 부모를 가르키도록 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Case 3&lt;/b&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1516&quot; data-origin-height=&quot;368&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/N46IS/btr6NXvUBiC/gkFsdwlWEaINKmCdNR7CJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/N46IS/btr6NXvUBiC/gkFsdwlWEaINKmCdNR7CJk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/N46IS/btr6NXvUBiC/gkFsdwlWEaINKmCdNR7CJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FN46IS%2Fbtr6NXvUBiC%2FgkFsdwlWEaINKmCdNR7CJk%2Fimg.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; loading=&quot;lazy&quot; width=&quot;1516&quot; height=&quot;368&quot; data-origin-width=&quot;1516&quot; data-origin-height=&quot;368&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;w의 색을 BLACK으로, w의 왼쪽 자식의 색을 RED로 만들어준다.&lt;/p&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1638&quot; data-origin-height=&quot;402&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bP8phA/btr6NvzAGbV/RtQeZGJpmHV307tS8yep9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bP8phA/btr6NvzAGbV/RtQeZGJpmHV307tS8yep9k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bP8phA/btr6NvzAGbV/RtQeZGJpmHV307tS8yep9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbP8phA%2Fbtr6NvzAGbV%2FRtQeZGJpmHV307tS8yep9k%2Fimg.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; loading=&quot;lazy&quot; width=&quot;1638&quot; height=&quot;402&quot; data-origin-width=&quot;1638&quot; data-origin-height=&quot;402&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음, w를 기준으로 right rotate를 진행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 w는 BLAKC이며 오른쪽 자식이 RED인 상태가 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막 케이스를 확인하자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Case 4&lt;/b&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1658&quot; data-origin-height=&quot;404&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnqsSC/btr6NuVi4xZ/WiJakFxqgZIeZDIVYLxamk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnqsSC/btr6NuVi4xZ/WiJakFxqgZIeZDIVYLxamk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnqsSC/btr6NuVi4xZ/WiJakFxqgZIeZDIVYLxamk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnqsSC%2Fbtr6NuVi4xZ%2FWiJakFxqgZIeZDIVYLxamk%2Fimg.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; loading=&quot;lazy&quot; width=&quot;1658&quot; height=&quot;404&quot; data-origin-width=&quot;1658&quot; data-origin-height=&quot;404&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;w의 색을 x의 부모 노드의 색으로 만들어주고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;w의 왼쪽 자식의 색을 BLACK으로 만들어준다.&lt;/p&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1638&quot; data-origin-height=&quot;390&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/W5W60/btr6GqeZqQU/YSYXMBywQCGECmCVGuQYB1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/W5W60/btr6GqeZqQU/YSYXMBywQCGECmCVGuQYB1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/W5W60/btr6GqeZqQU/YSYXMBywQCGECmCVGuQYB1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FW5W60%2Fbtr6GqeZqQU%2FYSYXMBywQCGECmCVGuQYB1%2Fimg.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; loading=&quot;lazy&quot; width=&quot;1638&quot; height=&quot;390&quot; data-origin-width=&quot;1638&quot; data-origin-height=&quot;390&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;그 뒤, x의 부모 노드를 기준으로 left rotate 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;h4 id=&quot;-구현7-erase&quot; data-ke-size=&quot;size20&quot;&gt;  구현(7) (erase-fixup)&lt;/h4&gt;
&lt;pre id=&quot;code_1679989763854&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void rbtree_erase_fixup(rbtree *t, node_t *cursor) {
    while (cursor != t-&amp;gt;root &amp;amp;&amp;amp; cursor-&amp;gt;color == RBTREE_BLACK) {
        if (cursor == cursor-&amp;gt;parent-&amp;gt;left) {
            node_t *sibling_node = cursor-&amp;gt;parent-&amp;gt;right;
            if (sibling_node-&amp;gt;color == RBTREE_RED) {
                sibling_node-&amp;gt;color = RBTREE_BLACK;
                cursor-&amp;gt;parent-&amp;gt;color = RBTREE_RED;
                left_rotate(t, cursor-&amp;gt;parent);
                sibling_node = cursor-&amp;gt;parent-&amp;gt;right;
            }
            if (sibling_node-&amp;gt;left-&amp;gt;color == RBTREE_BLACK &amp;amp;&amp;amp; sibling_node-&amp;gt;right-&amp;gt;color == RBTREE_BLACK) {
                sibling_node-&amp;gt;color = RBTREE_RED;
                cursor = cursor-&amp;gt;parent;
            } else {
                if (sibling_node-&amp;gt;right-&amp;gt;color == RBTREE_BLACK) {
                    sibling_node-&amp;gt;left-&amp;gt;color = RBTREE_BLACK;
                    sibling_node-&amp;gt;color = RBTREE_RED;
                    right_rotate(t, sibling_node);
                    sibling_node = cursor-&amp;gt;parent-&amp;gt;right;
                }
                sibling_node-&amp;gt;color = cursor-&amp;gt;parent-&amp;gt;color;
                cursor-&amp;gt;parent-&amp;gt;color = RBTREE_BLACK;
                sibling_node-&amp;gt;right-&amp;gt;color = RBTREE_BLACK;
                left_rotate(t, cursor-&amp;gt;parent);
                cursor = t-&amp;gt;root;
            }
        } else {
            node_t *sibling_node = cursor-&amp;gt;parent-&amp;gt;left;
            if (sibling_node-&amp;gt;color == RBTREE_RED) {
                sibling_node-&amp;gt;color = RBTREE_BLACK;
                cursor-&amp;gt;parent-&amp;gt;color = RBTREE_RED;
                right_rotate(t, cursor-&amp;gt;parent);
                sibling_node = cursor-&amp;gt;parent-&amp;gt;left;
            }
            if (sibling_node-&amp;gt;left-&amp;gt;color == RBTREE_BLACK &amp;amp;&amp;amp; sibling_node-&amp;gt;right-&amp;gt;color == RBTREE_BLACK) {
                sibling_node-&amp;gt;color = RBTREE_RED;
                cursor = cursor-&amp;gt;parent;
            } else {
                if (sibling_node-&amp;gt;left-&amp;gt;color == RBTREE_BLACK) {
                    sibling_node-&amp;gt;right-&amp;gt;color = RBTREE_BLACK;
                    sibling_node-&amp;gt;color = RBTREE_RED;
                    left_rotate(t, sibling_node);
                    sibling_node = cursor-&amp;gt;parent-&amp;gt;left;
                }
                sibling_node-&amp;gt;color = cursor-&amp;gt;parent-&amp;gt;color;
                cursor-&amp;gt;parent-&amp;gt;color = RBTREE_BLACK;
                sibling_node-&amp;gt;left-&amp;gt;color = RBTREE_BLACK;
                right_rotate(t, cursor-&amp;gt;parent);
                cursor = t-&amp;gt;root;
            }
        }
    }
    cursor-&amp;gt;color = RBTREE_BLACK;
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>CS/자료구조</category>
      <category>cs</category>
      <category>RBTreelab</category>
      <category>자료구조</category>
      <author>완성</author>
      <guid isPermaLink="true">https://contrabass.tistory.com/123</guid>
      <comments>https://contrabass.tistory.com/123#entry123comment</comments>
      <pubDate>Tue, 28 Mar 2023 16:43:32 +0900</pubDate>
    </item>
    <item>
      <title>[RBTree lab] ② Insert</title>
      <link>https://contrabass.tistory.com/122</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;586&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NaLdf/btr6x9qmMtt/L9EF8rXxqdw7ibmf9PnYKK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NaLdf/btr6x9qmMtt/L9EF8rXxqdw7ibmf9PnYKK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NaLdf/btr6x9qmMtt/L9EF8rXxqdw7ibmf9PnYKK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNaLdf%2Fbtr6x9qmMtt%2FL9EF8rXxqdw7ibmf9PnYKK%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;586&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;586&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h1 id=&quot;삽입insert&quot;&gt;삽입(insert)&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;insert 자체는 BST와 동일하게 진행되고,&lt;br /&gt;insert 이후 RB트리를 유지시키기 위한 fix up이 진행된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 insert부터 확인해보자.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;1655&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/l4E3S/btr6ssRhGzm/FpBJCxzq7D1zIl4KKZMB11/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/l4E3S/btr6ssRhGzm/FpBJCxzq7D1zIl4KKZMB11/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l4E3S/btr6ssRhGzm/FpBJCxzq7D1zIl4KKZMB11/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl4E3S%2Fbtr6ssRhGzm%2FFpBJCxzq7D1zIl4KKZMB11%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;1655&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;1655&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Root node부터 시작해서,&lt;br /&gt;현재 insert하려는 new_node의 key값과 만나는 node의 key값을 비교한 뒤&lt;br /&gt;new_node의 key값이 더 작다면 왼쪽으로, 크다면 오른쪽으로 내려간다.&lt;br /&gt;더 이상 내려갈 수 없을 때(nil을 만날 때) 그 위치가 new_node가 삽입 될 위치이다.&lt;/p&gt;
&lt;h4 id=&quot;다만&quot; data-ke-size=&quot;size20&quot;&gt;다만,&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RB 트리의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;1번 조건&lt;/b&gt;에 따라, 모든 node는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;RED&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;또는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;BLACK&lt;/b&gt;의 색을 가져야 하는데,&lt;br /&gt;새로 insert되는 node의 색은 항상&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;RED&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;로 고정된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 RB Tree의 조건 5번을 위배하지 않기 위함이다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;5. 각 노드로부터 그 노드의 자손인 리프로 가는 경로들은 모두 같은 수의&amp;nbsp;BLACK&amp;nbsp;노드를 포함해야한다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 추가되는 node의 색이&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;BLACK&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;이라면,&lt;br /&gt;어떤 node에서 출발해서 leaf로 갈 때,&lt;br /&gt;추가된 node로 가는 경로의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;BLACK&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;노드 개수가 다른 경로보다 1개 더 많아질 것이고,&lt;br /&gt;이는 조건 5번을 위배한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 Insert되는 node의 색은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;RED&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;로 고정된다.&lt;/p&gt;
&lt;h3 id=&quot;-구현4-insert&quot; data-ke-size=&quot;size23&quot;&gt;  구현(4) (Insert)&lt;/h3&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;node_t *rbtree_insert(rbtree *t, const key_t key) {
    // rbtree에 저장할 new_node 생성
    node_t *new_node = create_new_node(key, t-&amp;gt;nil);

    // insert 위치 탐색
    node_t *parent_node = t-&amp;gt;nil;
    node_t *cursor = t-&amp;gt;root;
    while (cursor != t-&amp;gt;nil) {
        parent_node = cursor;
        if (new_node-&amp;gt;key &amp;lt; cursor-&amp;gt;key) {
            cursor = cursor-&amp;gt;left;
        } else {
            cursor = cursor-&amp;gt;right;
        }
    }

    // new_node와 parent_node의 자식-부모 관계 설정
    new_node-&amp;gt;parent = parent_node;
    if (parent_node == t-&amp;gt;nil) {			// 1. parent_node가 nil인 경우 (newNode가 root)
        t-&amp;gt;root = new_node;
    } else if (new_node-&amp;gt;key &amp;lt; parent_node-&amp;gt;key) {	// 2. new_node가 parent_node의 왼쪽 자식 노드인 경우
        parent_node-&amp;gt;left = new_node;
    } else {						// 3. new_node가 parent_node의 오른쪽 자식 노드인 경우
        parent_node-&amp;gt;right = new_node;
    }

    // rbtree 복구
    rbtree_insert_fixup(t, new_node);

    // 생성 후 insert한 노드의 pointer를 반환
    return new_node;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;삽입-후-복구&quot; data-ke-size=&quot;size26&quot;&gt;삽입 후 복구&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;insert&lt;/b&gt;가 완료된 후, RBTREE의 특성을 복구하기 위한&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;insert_fixup&lt;/b&gt;이 수행된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 노드를 기준으로&lt;span&gt;&amp;nbsp;&lt;/span&gt;삼촌&lt;span&gt;&amp;nbsp;&lt;/span&gt;노드를 정의하게 되는데&lt;br /&gt;관계도는 아래와 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;661&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dhxMsK/btr6pesBPeY/Mz1CvAKTlOrBTEd6Wip8KK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dhxMsK/btr6pesBPeY/Mz1CvAKTlOrBTEd6Wip8KK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dhxMsK/btr6pesBPeY/Mz1CvAKTlOrBTEd6Wip8KK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdhxMsK%2Fbtr6pesBPeY%2FMz1CvAKTlOrBTEd6Wip8KK%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;1080&quot; height=&quot;661&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;661&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그림처럼, 부모 노드의 형제 노드를&lt;span&gt;&amp;nbsp;&lt;/span&gt;삼촌이라고 부를 예정이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;insert_fixup&lt;/b&gt;이 진행되는 경우는 총 6가지로, 아래 그림과 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;1104&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kJmHR/btr6tWLuEEj/muu0Hgtta48jWr8rUsTCA0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kJmHR/btr6tWLuEEj/muu0Hgtta48jWr8rUsTCA0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kJmHR/btr6tWLuEEj/muu0Hgtta48jWr8rUsTCA0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkJmHR%2Fbtr6tWLuEEj%2Fmuu0Hgtta48jWr8rUsTCA0%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;1104&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;1104&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 id=&quot;왜-경우가-6가지일까&quot; data-ke-size=&quot;size23&quot;&gt;왜 경우가 6가지일까&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조건을 다시 보자.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;1. 모든 노드는&amp;nbsp;RED&amp;nbsp;또는&amp;nbsp;BLACK&lt;br /&gt;2. 루트는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;BLACK&lt;br /&gt;&lt;/b&gt;3. 모든 리프(NIL)는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;BLACK&lt;br /&gt;&lt;/b&gt;4. 노드가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;RED&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;이면 그 노드의 자식은 모두&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;BLACK&lt;br /&gt;&lt;/b&gt;5. 각 노드로부터 그 노드의 자손인 리프로 가는 경로들은 모두 같은 수의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;BLACK&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;노드를 포함해야함&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;insert된 node인 x(x의 color는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;RED&lt;/span&gt;&lt;/b&gt;)에 의해&lt;br /&gt;RBTREE의 특성이 위배될 수 있는 상황이 존재한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조건 1, 3, 5는 insert에 의해 위배되지 않는다.&lt;br /&gt;&lt;b&gt;조건 2, 4는 위배 될 수 있다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 조건이 위배되는 경우 모두 x가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;RED&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;이기 때문이며, 각각의 경우는&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;조건 2가 위배되는 경우: x가 루트인 경우&lt;/li&gt;
&lt;li&gt;조건 4가 위배되는 경우: x의 부모가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;RED&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;인 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인 상태일 때 위배된다.&lt;/p&gt;
&lt;h4 id=&quot;조건-2가-위배되는-경우x가-루트인-경우&quot; data-ke-size=&quot;size20&quot;&gt;조건 2가 위배되는 경우(x가 루트인 경우)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;x의 color를&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;BLACK&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;으로 바꿔준다.&lt;/p&gt;
&lt;h4 id=&quot;조건-4가-위배되는-경우x의-부모가-red인-경우&quot; data-ke-size=&quot;size20&quot;&gt;조건 4가 위배되는 경우(x의 부모가 RED인 경우)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;는 2가지 경우로 구분된다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. x의 부모 노드가 조부모 노드의 왼쪽 자식일 경우&lt;br /&gt;2. x의 부모 노드가 조부모 노드의 오른쪽 자식일 경우&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 2가지의 각 경우는, 또다시 아래와 같은 3가지 경우로 구분된다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;1). x의 삼촌 노드가&amp;nbsp;RED인 경우&lt;br /&gt;2). x의 삼촌 노드가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;BLACK&lt;/b&gt;이면서 x가 오른쪽 자식인 경우&lt;br /&gt;3). x의 삼촌 노드가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;BLACK&lt;/b&gt;이면서 x가 왼쪽 자식인 경우&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 먼저 구분된 2가지 경우와 각 경우에서 또 3가지 경우가 존재하므로,&lt;br /&gt;총 6가지 경우에 대한 판단과 각 경우의 해소(RBTREE를 유지 시키는)방법이 존재한다.&lt;/p&gt;
&lt;h3 id=&quot;-구현5-insert-fix-up&quot; data-ke-size=&quot;size23&quot;&gt;  구현(5) (insert fix up)&lt;/h3&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;void rbtree_insert_fixup(rbtree *t, node_t *cursor) {
    // 종료 조건: cursor 부모 노드의 color (RBTREE_BLACK or RBTREE_RED)
    while (cursor-&amp;gt;parent-&amp;gt;color == RBTREE_RED) {
        // 분기 1: cursor 부모 노드의 위치 (left child or right child)
        if (cursor-&amp;gt;parent == cursor-&amp;gt;parent-&amp;gt;parent-&amp;gt;left) {
            node_t *uncle = cursor-&amp;gt;parent-&amp;gt;parent-&amp;gt;right;
            // 분기 2: cursor 삼촌 노드(uncle)의 color (RBTREE_BLACK or RBTREE_RED)
            if (uncle-&amp;gt;color == RBTREE_RED) {
                cursor-&amp;gt;parent-&amp;gt;color = RBTREE_BLACK;
                uncle-&amp;gt;color = RBTREE_BLACK;
                cursor-&amp;gt;parent-&amp;gt;parent-&amp;gt;color = RBTREE_RED;
                cursor = cursor-&amp;gt;parent-&amp;gt;parent;
            } else {
                // 분기 3: cursor의 위치 (left child or right child)
                if (cursor == cursor-&amp;gt;parent-&amp;gt;right) {
                    cursor = cursor-&amp;gt;parent;
                    left_rotate(t, cursor);
                }
                cursor-&amp;gt;parent-&amp;gt;color = RBTREE_BLACK;
                cursor-&amp;gt;parent-&amp;gt;parent-&amp;gt;color = RBTREE_RED;
                right_rotate(t, cursor-&amp;gt;parent-&amp;gt;parent);
            }
        } else {
            node_t *uncle = cursor-&amp;gt;parent-&amp;gt;parent-&amp;gt;left;
            if (uncle-&amp;gt;color == RBTREE_RED) {
                cursor-&amp;gt;parent-&amp;gt;color = RBTREE_BLACK;
                uncle-&amp;gt;color = RBTREE_BLACK;
                cursor-&amp;gt;parent-&amp;gt;parent-&amp;gt;color = RBTREE_RED;
                cursor = cursor-&amp;gt;parent-&amp;gt;parent;
            } else {
                if (cursor == cursor-&amp;gt;parent-&amp;gt;left) {
                    cursor = cursor-&amp;gt;parent;
                    right_rotate(t, cursor);
                }
                cursor-&amp;gt;parent-&amp;gt;color = RBTREE_BLACK;
                cursor-&amp;gt;parent-&amp;gt;parent-&amp;gt;color = RBTREE_RED;
                left_rotate(t, cursor-&amp;gt;parent-&amp;gt;parent);
            }
        }
    }
    t-&amp;gt;root-&amp;gt;color = RBTREE_BLACK;
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>CS/자료구조</category>
      <category>cs</category>
      <category>RBTreelab</category>
      <category>자료구조</category>
      <author>완성</author>
      <guid isPermaLink="true">https://contrabass.tistory.com/122</guid>
      <comments>https://contrabass.tistory.com/122#entry122comment</comments>
      <pubDate>Tue, 28 Mar 2023 16:23:49 +0900</pubDate>
    </item>
    <item>
      <title>[RBTree lab] ① 개요, Rotate</title>
      <link>https://contrabass.tistory.com/121</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;586&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b88oHI/btr6pE5LIxi/POov4j53XJp9AEIlR21iQ0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b88oHI/btr6pE5LIxi/POov4j53XJp9AEIlR21iQ0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b88oHI/btr6pE5LIxi/POov4j53XJp9AEIlR21iQ0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb88oHI%2Fbtr6pE5LIxi%2FPOov4j53XJp9AEIlR21iQ0%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;586&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;586&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h1 id=&quot;rbtreered-black-tree&quot;&gt;RBTree(Red Black Tree)&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RB트리는&lt;br /&gt;전체 트리의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;높이를&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;lo&lt;span&gt;g&lt;/span&gt;&lt;/span&gt;&lt;span&gt;N&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(&lt;span&gt;&lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;N&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;은 노드의 개수) 으로 유지&lt;/b&gt;하는&lt;br /&gt;&lt;b&gt;&lt;a href=&quot;https://ko.wikipedia.org/wiki/%EC%9D%B4%EC%A7%84_%ED%83%90%EC%83%89_%ED%8A%B8%EB%A6%AC&quot;&gt;이진 탐색 트리&lt;/a&gt;&lt;/b&gt;이다.&lt;/p&gt;
&lt;h1 id=&quot;rbtree의-5가지-조건&quot;&gt;RBTREE의 5가지 조건&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;1. 모든 노드는&amp;nbsp;RED&amp;nbsp;또는&amp;nbsp;BLACK&lt;br /&gt;2. 루트는&amp;nbsp;BLACK&lt;br /&gt;3. 모든 리프(NIL)는&amp;nbsp;BLACK&lt;br /&gt;4. 노드가&amp;nbsp;RED&amp;nbsp;이면 그 노드의 자식은 모두&amp;nbsp;BLACK&lt;br /&gt;5. 각 노드로부터 그 노드의 자손인 리프로 가는 경로들은 모두 같은 수의&amp;nbsp;BLACK&amp;nbsp;노드를 포함해야함&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 노드는 자신의 부모, 왼쪽 자식, 오른쪽 자식의 정보와&lt;br /&gt;노드 자신의 key값을 가지고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구현을 용이하게 하기 위해&lt;span&gt;&amp;nbsp;sentinel&lt;/span&gt;&amp;nbsp;node를 이용하는데,&lt;br /&gt;sentinel&amp;nbsp;node는 부모와 자식 정보를 가지지 않고&lt;br /&gt;색깔이 항상&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;BLACK&lt;/b&gt;인 node로 정의한다.&lt;/p&gt;
&lt;h3 id=&quot;-구현1-노드-rb트리&quot; data-ke-size=&quot;size23&quot;&gt;  구현(1) (노드, RB트리)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;노드와 트리의 정보를 갖게 될 구조체는 다음과 같이 구현했다.&lt;/p&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;typedef enum { RBTREE_RED,
               RBTREE_BLACK } color_t;

typedef int key_t;

typedef struct node_t {
    color_t color;
    key_t key;
    struct node_t *parent, *left, *right;
} node_t;

typedef struct {
    node_t *root;
    node_t *nil;  // for sentinel
} rbtree;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;h3 id=&quot;node_t&quot; data-ke-size=&quot;size23&quot;&gt;node_t&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;node_t는 RB트리의 노드 구조체이다.&lt;br /&gt;자기 자신의 포인터 변수를 갖는 구조체를 '자기 참조 구조체' 라고 하며,&lt;br /&gt;자기 참조 구조체가 갖는 자기 자신 타입의 포인터 멤버를 링크(link)라고 한다.&lt;br /&gt;node_t는 자기 참조 구조체이고,&lt;br /&gt;*parent,&lt;span&gt;&amp;nbsp;&lt;/span&gt;*left,&lt;span&gt;&amp;nbsp;&lt;/span&gt;*right는 링크이다.&lt;/p&gt;
&lt;h4 id=&quot;멤버&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;멤버&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;color_t color&lt;span&gt;&amp;nbsp;&lt;/span&gt;: 노드의 색(RBTREE_RED,&lt;span&gt;&amp;nbsp;&lt;/span&gt;RBTREE_BLACK)&lt;br /&gt;key_t key&lt;span&gt;&amp;nbsp;&lt;/span&gt;: 노드의 Key값(int)&lt;br /&gt;struct node_t *parent, *left, *right&lt;br /&gt;: 순서대로, 노드의 부모 노드, 왼쪽 자식 노드, 오른쪽 자식 노드&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;h3 id=&quot;rbtree&quot; data-ke-size=&quot;size23&quot;&gt;rbtree&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;rbtree는 RB트리 구조체이다.&lt;/p&gt;
&lt;h4 id=&quot;멤버-1&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;멤버&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;node_t *root&lt;span&gt;&amp;nbsp;&lt;/span&gt;: rbtree의 root 노드. 초기값은&lt;span&gt;&amp;nbsp;&lt;/span&gt;nil&lt;br /&gt;node_t *nil&lt;span&gt;&amp;nbsp;&lt;/span&gt;: &amp;nbsp;sentinel 노드.&lt;br /&gt;한 노드의 자식 또는 부모가 존재하지 않으면&lt;span&gt;&amp;nbsp;&lt;/span&gt;nil로 채운다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id=&quot;rb-tree를-복구하기-위한-방법&quot;&gt;RB Tree를 복구하기 위한 방법&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Insert&lt;/b&gt;와&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Delete&lt;/b&gt;는 트리를 수정한다.&lt;br /&gt;이는 원래 트리를 RB트리의 조건에 위배되는 상태로 만들 수 있다.&lt;br /&gt;따라서,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Insert&lt;/b&gt;와&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Delete&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;이후에는 RB트리를 복구시키는 과정이 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;복구를 위해 트리를 일부 수정해주어야 하고,&lt;br /&gt;수정에 공통적으로 사용되는 2가지 방법이 존재한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나는 노드의 연결 정보를 변경시키는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;회전&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;이고,&lt;br /&gt;다른 하나는 노드의 색을 바꿔주는 방법이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 방법 모두 이진 탐색 트리의 특성을 보전한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 가지 방법 중 색을 바꿔주는 것은&lt;br /&gt;말 그대로 &lt;b&gt;각 노드의 색을 조건에 맞게 변경해주는 것&lt;/b&gt;으로&lt;br /&gt;이후에 RB트리가 복구 되는 과정에서 조건에 맞게 진행될 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;회전&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;또한 복구 과정에서 조건에 맞게 사용되나,&lt;br /&gt;우선&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;회전&lt;/b&gt;이라는 것이 어떤 일이 일어나는 과정인지 알아볼 필요가 있다.&lt;/p&gt;
&lt;h2 id=&quot;회전rotate&quot; data-ke-size=&quot;size26&quot;&gt;회전(Rotate)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;우회전(Right-Rotate)&lt;/b&gt;과&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;좌회전(Left-Rotate)&lt;/b&gt;이 있다.&lt;/p&gt;
&lt;h3 id=&quot;왜-할까&quot; data-ke-size=&quot;size23&quot;&gt;왜 할까?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RB 트리는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;높이를&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;lo&lt;span&gt;g&lt;/span&gt;&lt;/span&gt;&lt;span&gt;N&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(&lt;span&gt;&lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;N&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;은 노드의 개수) 으로 유지&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;시키는&lt;br /&gt;이진 탐색 트리라고 설명했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RB 트리에 node를 삽입하거나, 기존의 node를 삭제하는 것은&lt;br /&gt;트리 한쪽이 치우쳐지는 형태의 불균형을 초래하고,&lt;br /&gt;이는 이 불균형을 존재하지 않도록 강제하는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;RB 트리의 5가지 조건&lt;/b&gt;(혹은 특성)을 위배하는 상황으로 이어진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 node의 삽입/삭제로 인해&lt;br /&gt;root노드 기준 좌/우 subTree 중 한 쪽의 길이가 상대적으로 짧아진 tree를 생각해보자,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좌우의 균형을 다시 맞춰주기 위해서, 아래처럼 간단한 방법을 생각해 볼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;946&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qBzSa/btr6ANf81Bw/3TrP48NaWvY4UJQ9YpnGm0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qBzSa/btr6ANf81Bw/3TrP48NaWvY4UJQ9YpnGm0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qBzSa/btr6ANf81Bw/3TrP48NaWvY4UJQ9YpnGm0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqBzSa%2Fbtr6ANf81Bw%2F3TrP48NaWvY4UJQ9YpnGm0%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;946&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;946&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;길이가 긴 subtree의 root node 레벨을 올려주어, 전체 트리의 좌/우 서브트리의 높이를 맞춰주는 것이다.&lt;br /&gt;위 그림은 단순한 예시이고, 실제로 Rotate는 저런식으로 동작하지는 않는다(양 subtree의 크기나 Rotate 이후의 형태도 맞지 않다.).&lt;br /&gt;다만 Rotate를 하는 목적에 대한 직관적인 설명은 될 수 있을 것이다.&lt;/p&gt;
&lt;h3 id=&quot;해도-될까&quot; data-ke-size=&quot;size23&quot;&gt;해도 될까?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Rotate가 RB 트리의 불균형을 조정하기 위한 방법이라면,&lt;br /&gt;최소한 RB 트리가 되기 위한 전제인 &quot;이진 탐색 트리&quot;인 상태를 깨뜨려서는 안 될 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래에 Left Rotate와 Right Rotate의 과정을 그려놓았다.&lt;br /&gt;각 과정에서 어떤 방식으로 이진 탐색 트리의 특성을 유지 시키면서&lt;br /&gt;Rotate를 가능하게 하는지 확인해 볼 수 있다.&lt;/p&gt;
&lt;h3 id=&quot;해보자&quot; data-ke-size=&quot;size23&quot;&gt;해보자&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드나 설명을 보면 부분적으로는 이해가 되는데,&lt;br /&gt;전체 과정이 그려지지를 않아서&lt;br /&gt;그냥 진짜로 그림을 그려보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 혹시 몰라서 적어둔&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;그림의 이해를 위한 설명&lt;/b&gt;이다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회전이 진행되며 두 Node의 사이의 간선이 변경되는 과정을 코드와 그림으로 표현했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 Node는&lt;span&gt;&amp;nbsp;&lt;/span&gt;부모,&lt;span&gt;&amp;nbsp;&lt;/span&gt;왼쪽 자식,&lt;span&gt;&amp;nbsp;&lt;/span&gt;오른쪽 자식의 정보를 가지고 있고,&lt;br /&gt;간선의 방향은 정보를 가진 Node에서 그 정보에 해당하는 Node로 향한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를들어, Node A에서 Node B로 향하는(A에서 출발한 화살표가 B에 꽂힌) 간선이 존재할 때,&lt;br /&gt;Node A는&lt;span&gt;&amp;nbsp;&lt;/span&gt;부모&lt;span&gt;&amp;nbsp;&lt;/span&gt;또는&lt;span&gt;&amp;nbsp;&lt;/span&gt;왼쪽 자식&lt;span&gt;&amp;nbsp;&lt;/span&gt;또는&lt;span&gt;&amp;nbsp;&lt;/span&gt;오른쪽 자식&lt;span&gt;&amp;nbsp;&lt;/span&gt;중 하나의 관계로서&lt;br /&gt;Node B의 정보를 가지고 있다는 의미이다.&lt;br /&gt;(Node A가 Node B의 정보를 가지고 있다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 단계에서 변경된 간선에 대해&lt;br /&gt;변경 이전의 간선은 빨간 점선으로,&lt;br /&gt;변경 이후의 간선은 파란 실선으로 그렸으며&lt;br /&gt;변경 이후의 간선으로 생긴 새롭게 연결된 Node와의 관계를&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&lt;b&gt;P&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;= 부모&lt;br /&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&lt;b&gt;Left&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;= 왼쪽 자식&lt;br /&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&lt;b&gt;Right&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;= 오른쪽 자식&lt;br /&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&lt;b&gt;Child&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;= 자식(좌/우 구분을 따로 표현하지 않음)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;와 같이 표시했다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;우회전right-rotate&quot; data-ke-size=&quot;size23&quot;&gt;우회전(Right-Rotate)&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;565&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dcmrEu/btr6pFjhpWK/8zhTuk4bK65kJzKbB8cNOK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dcmrEu/btr6pFjhpWK/8zhTuk4bK65kJzKbB8cNOK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dcmrEu/btr6pFjhpWK/8zhTuk4bK65kJzKbB8cNOK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdcmrEu%2Fbtr6pFjhpWK%2F8zhTuk4bK65kJzKbB8cNOK%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;565&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;565&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왼쪽이 right rotate 이전의 상태,&lt;br /&gt;오른쪽이 right rotate 이후의 상태이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;989&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Vlzwb/btr6BfKgoTZ/yvHqveORkuAUmmTI4Yvyfk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Vlzwb/btr6BfKgoTZ/yvHqveORkuAUmmTI4Yvyfk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Vlzwb/btr6BfKgoTZ/yvHqveORkuAUmmTI4Yvyfk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVlzwb%2Fbtr6BfKgoTZ%2FyvHqveORkuAUmmTI4Yvyfk%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;989&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;989&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;right rotate 과정을 단계로 구분지어 표현했다.&lt;br /&gt;하나의 단계마다 하나의 Node가 가지는&lt;span&gt;&amp;nbsp;&lt;/span&gt;부모&lt;span&gt;&amp;nbsp;&lt;/span&gt;또는&lt;span&gt;&amp;nbsp;&lt;/span&gt;왼쪽 자식&lt;span&gt;&amp;nbsp;&lt;/span&gt;또는&lt;span&gt;&amp;nbsp;&lt;/span&gt;오른쪽 자식&lt;span&gt;&amp;nbsp;&lt;/span&gt;의 정보가 수정된다.&lt;/p&gt;
&lt;h4 id=&quot;-1번-단계에서&quot; data-ke-size=&quot;size20&quot;&gt;  1번 단계에서&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Node&lt;span&gt;&amp;nbsp;&lt;/span&gt;x&lt;span&gt;&amp;nbsp;&lt;/span&gt;에서 위쪽(빈 곳)으로 연결된 간선은&lt;span&gt;&amp;nbsp;&lt;/span&gt;x와&lt;span&gt;&amp;nbsp;&lt;/span&gt;x의 부모 노드가 연결된 간선이다.&lt;br /&gt;이후 단계가 진행되면서,&lt;br /&gt;마찬가지로 위쪽의 빈 곳을 향하는 간선은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;회전 전의&lt;span&gt;&amp;nbsp;&lt;/span&gt;x의 부모 노드&lt;/b&gt;와 연결된 간선이다.&lt;/p&gt;
&lt;h4 id=&quot;-1번-2번-단계에서&quot; data-ke-size=&quot;size20&quot;&gt;  1번, 2번 단계에서&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;x와&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;beta;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;는&lt;span&gt;&amp;nbsp;&lt;/span&gt;부모-왼쪽자식&lt;span&gt;&amp;nbsp;&lt;/span&gt;관계를 갖게된다.&lt;/p&gt;
&lt;h4 id=&quot;-3번-4번-단계에서&quot; data-ke-size=&quot;size20&quot;&gt;  3번, 4번 단계에서&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;y와&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;회전 전의 x의 부모 노드&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;는&lt;span&gt;&amp;nbsp;&lt;/span&gt;자식-부모&lt;span&gt;&amp;nbsp;&lt;/span&gt;관계를 갖게된다.&lt;br /&gt;(4번의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&lt;b&gt;Child&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;라고 표시된 간선과, 5번의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&lt;b&gt;Right&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;라고 표시된 간선에 의해)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 회전 전의&lt;span&gt;&amp;nbsp;&lt;/span&gt;x와&lt;span&gt;&amp;nbsp;&lt;/span&gt;x의 부모 노드 사이의 관계를 그대로 대체하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;y가&lt;span&gt;&amp;nbsp;&lt;/span&gt;x의 자리를 차지할 때&lt;br /&gt;x와&lt;span&gt;&amp;nbsp;&lt;/span&gt;x의 부모와의 관계를 그대로 가져가야 하기 하기 때문에,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;y가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;회전 전의 x의 부모 노드&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;의 왼쪽 자식이 되는지, 오른쪽 자식이 되는지는&lt;br /&gt;x가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;회전 전의 x의 부모 노드&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;의 왼쪽 자식이었는지, 오른쪽 자식이었는지 여부를 그대로 따라간다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회전 전의 상태에서,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;x가&lt;span&gt;&amp;nbsp;&lt;/span&gt;x의 부모 노드의 왼쪽 자식이었다면,&lt;br /&gt;4단계의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&lt;b&gt;Child&lt;/b&gt;&lt;/span&gt;라는 표현은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&lt;b&gt;Left&lt;/b&gt;&lt;/span&gt;가 될 것이고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;x가&lt;span&gt;&amp;nbsp;&lt;/span&gt;x의 부모 노드의 오른쪽 자식이었다면,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&lt;b&gt;Right&lt;/b&gt;&lt;/span&gt;가 될 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(&lt;span&gt;&amp;nbsp;&lt;/span&gt;x가 root 였다면,&lt;span&gt;&amp;nbsp;&lt;/span&gt;y는 root가 된다. )&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id=&quot;-5번-6번-단계에서&quot; data-ke-size=&quot;size20&quot;&gt;  5번, 6번 단계에서&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원래는 부모였던 node&lt;span&gt;&amp;nbsp;&lt;/span&gt;x와&lt;br /&gt;원래는 왼쪽 자식이었던 node&lt;span&gt;&amp;nbsp;&lt;/span&gt;y의&lt;br /&gt;부모-자식&lt;span&gt;&amp;nbsp;&lt;/span&gt;관계의 역전이 일어난다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;y는&lt;span&gt;&amp;nbsp;&lt;/span&gt;x를 자신의 오른쪽 자식으로 두고,&lt;br /&gt;x는&lt;span&gt;&amp;nbsp;&lt;/span&gt;y를 자신의 부모로 둔다.&lt;/p&gt;
&lt;h3 id=&quot;-구현2-right-rotate&quot; data-ke-size=&quot;size23&quot;&gt;  구현(2) (right rotate)&lt;/h3&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;void right_rotate(rbtree *t, node_t *x) {
    node_t *y = x-&amp;gt;left;
    x-&amp;gt;left = y-&amp;gt;right;
    if (y-&amp;gt;right != t-&amp;gt;nil) {
        y-&amp;gt;right-&amp;gt;parent = x;
    }
    y-&amp;gt;parent = x-&amp;gt;parent;
    if (x-&amp;gt;parent == t-&amp;gt;nil) {
        t-&amp;gt;root = y;
    } else if (x == x-&amp;gt;parent-&amp;gt;left) {
        x-&amp;gt;parent-&amp;gt;left = y;
    } else {
        x-&amp;gt;parent-&amp;gt;right = y;
    }
    y-&amp;gt;right = x;
    x-&amp;gt;parent = y;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;좌회전left-rotate&quot; data-ke-size=&quot;size23&quot;&gt;좌회전(Left-Rotate)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;right rotate의 과정과 대칭이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;538&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ed5K8Q/btr6C2jeLKE/nDH2AKGJHOVUN7pteyPTe1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ed5K8Q/btr6C2jeLKE/nDH2AKGJHOVUN7pteyPTe1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ed5K8Q/btr6C2jeLKE/nDH2AKGJHOVUN7pteyPTe1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fed5K8Q%2Fbtr6C2jeLKE%2FnDH2AKGJHOVUN7pteyPTe1%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;538&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;538&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;989&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eLJX90/btr6oIUWnGf/klkojKl5UdzvKybgVwpKXk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eLJX90/btr6oIUWnGf/klkojKl5UdzvKybgVwpKXk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eLJX90/btr6oIUWnGf/klkojKl5UdzvKybgVwpKXk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeLJX90%2Fbtr6oIUWnGf%2FklkojKl5UdzvKybgVwpKXk%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;989&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;989&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;과정이 right rotate와 완벽하게 대칭이기 때문에, 부연 설명은 적지 않았다.&lt;/p&gt;
&lt;h3 id=&quot;-구현3-left-rotate&quot; data-ke-size=&quot;size23&quot;&gt;  구현(3) (left rotate)&lt;/h3&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;void left_rotate(rbtree *t, node_t *x) {
    node_t *y = x-&amp;gt;right;
    x-&amp;gt;right = y-&amp;gt;left;
    if (y-&amp;gt;left != t-&amp;gt;nil) {
        y-&amp;gt;left-&amp;gt;parent = x;
    }
    y-&amp;gt;parent = x-&amp;gt;parent;
    if (x-&amp;gt;parent == t-&amp;gt;nil) {
        t-&amp;gt;root = y;
    } else if (x == x-&amp;gt;parent-&amp;gt;left) {
        x-&amp;gt;parent-&amp;gt;left = y;
    } else {
        x-&amp;gt;parent-&amp;gt;right = y;
    }
    y-&amp;gt;left = x;
    x-&amp;gt;parent = y;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;rotate&quot; data-ke-size=&quot;size23&quot;&gt;rotate&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전체 과정을 보았다면, 이진 탐색 트리에서 한 노드의 각 자식들이 가지는 특성은 그대로 유지된다는 사실을 확인 할 수 있을 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Left Rotate&lt;/b&gt;를 예로 들면,&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;beta;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는&lt;span&gt;&amp;nbsp;&lt;/span&gt;y의 왼쪽 자식에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;x의 오른쪽 자식이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;y의 왼쪽 자식이었던&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;beta;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 대소관계는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;&amp;le;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;beta;&lt;/span&gt;&lt;span&gt;&amp;le;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;이었을 것이고,&lt;br /&gt;이는&lt;span&gt;&amp;nbsp;&lt;/span&gt;x의 오른쪽 자식인&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;beta;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;&amp;le;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;beta;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;이어야 한다는 조건을 항상 만족한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;x와&lt;span&gt;&amp;nbsp;&lt;/span&gt;y의&lt;span&gt;&amp;nbsp;&lt;/span&gt;부모-자식관계가 변경 가능한 것도 마찬가지이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;y가&lt;span&gt;&amp;nbsp;&lt;/span&gt;x의 오른쪽 자식일 때의&lt;span&gt;&amp;nbsp;&lt;/span&gt;x,&lt;span&gt;&amp;nbsp;&lt;/span&gt;y의 대소관계 (&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;&amp;le;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;) 와&lt;br /&gt;x가&lt;span&gt;&amp;nbsp;&lt;/span&gt;y의 왼쪽 자식일 때의&lt;span&gt;&amp;nbsp;&lt;/span&gt;x,&lt;span&gt;&amp;nbsp;&lt;/span&gt;y의 대소관계 (&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;&amp;le;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;) 는 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇기 때문에 rotate는 &quot;이진 탐색 트리&quot;의 특성을 유지한 채로 node를 회전시킬 수 있다.&lt;/p&gt;</description>
      <category>CS/자료구조</category>
      <category>cs</category>
      <category>RBTreelab</category>
      <category>자료구조</category>
      <author>완성</author>
      <guid isPermaLink="true">https://contrabass.tistory.com/121</guid>
      <comments>https://contrabass.tistory.com/121#entry121comment</comments>
      <pubDate>Tue, 28 Mar 2023 16:19:12 +0900</pubDate>
    </item>
    <item>
      <title>[2023 (상반기) Dev-Matching : 백엔드] 코딩 테스트 후기</title>
      <link>https://contrabass.tistory.com/120</link>
      <description>&lt;h1 id=&quot;환경&quot;&gt;환경&lt;/h1&gt;
&lt;h2 id=&quot;규정&quot; data-ke-size=&quot;size26&quot;&gt;규정&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;외부 IDE 사용 불가, 인터넷 검색/오픈북 참고 불가&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1276&quot; data-origin-height=&quot;972&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cEOXdB/btr5RZ2JPEH/YWFRgiJ7M96tK2UCPV5qg1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cEOXdB/btr5RZ2JPEH/YWFRgiJ7M96tK2UCPV5qg1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cEOXdB/btr5RZ2JPEH/YWFRgiJ7M96tK2UCPV5qg1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcEOXdB%2Fbtr5RZ2JPEH%2FYWFRgiJ7M96tK2UCPV5qg1%2Fimg.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; loading=&quot;lazy&quot; width=&quot;1276&quot; height=&quot;972&quot; data-origin-width=&quot;1276&quot; data-origin-height=&quot;972&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 올해 처음 데브 매칭을 신청했지만,&lt;br /&gt;작년 하반기 후기들을 보니 규정이 조금 더 엄격해진 것 같다.&lt;br /&gt;작년에는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;인터넷 검색 및 오픈북 참고&lt;/b&gt;가 가능했고,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;외부 IDE 사용 또한 가능&lt;/b&gt;했지만&lt;br /&gt;올해에는 이 두가지 항목이 테스트 이행 중&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;위반 행동&lt;/b&gt;으로 바뀌었다.&lt;/p&gt;
&lt;h2 id=&quot;응시-환경&quot; data-ke-size=&quot;size26&quot;&gt;응시 환경&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;화면 공유 + 화상 감독&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;화면 공유로 현재 화면을 공유한다. 구글 미트에서 사용하는 전체 화면 공유 기능과 동일하다.&lt;/li&gt;
&lt;li&gt;테스트를 진행하는 동안 응시자의 얼굴, 허벅지, 모니터, 키보드 등이 나오는 화면을 실시간으로 공유해야 한다. 지원 시 안내되는 모바일 어플리케이션을 설치하고 안내 방법을 확인하면 쉽게 할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1 id=&quot;코딩-테스트&quot;&gt;코딩 테스트&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;언어 : 파이썬 사용&lt;br /&gt;문제 : 알고리즘 3문제 + SQL 1문제&lt;br /&gt;결과 : 3솔(알고리즘 3)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;1번-자료구조-이용-구현&quot; data-ke-size=&quot;size26&quot;&gt;1번: 자료구조 이용, 구현&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 해당 문제에서 요구하는 정해가 이것인지는 잘 모르겠지만,&lt;br /&gt;일단 돌아가게 구현하자는 생각으로 자료구조를 적절히 이용해서 풀었다.&lt;br /&gt;예상하던 1번 문제의 수준 보다는 생각이 필요한 문제였고, 시간을 많이 썼다.&lt;/p&gt;
&lt;h2 id=&quot;2번-완전-탐색&quot; data-ke-size=&quot;size26&quot;&gt;2번: 완전 탐색&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;경우의 수를 구하는 문제였고, DFS를 이용한 완전 탐색으로 풀었다.&lt;br /&gt;중간에 인자를 잘못 넘겨주는 실수를 해서 조금 해맸다..&lt;/p&gt;
&lt;h2 id=&quot;3번-dp-메모이제이션&quot; data-ke-size=&quot;size26&quot;&gt;3번: DP, 메모이제이션&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마찬가지로 경우의 수를 구하는 문제였다.&lt;br /&gt;처음에는 2번과 마찬가지로 완전 탐색으로 구현했지만 예제 입력을 제외하고는 시간 초과가 발생했다.&lt;br /&gt;생각을 조금 더 해보니 이전에 계산한 경우의 수를 이용해서 현재의 경우의 수를 계산할 수 있었고,&lt;br /&gt;DP 테이블을 이용해서 풀었다.&lt;br /&gt;발상의 전환이 조금 필요한 문제였던것 같다.&lt;/p&gt;</description>
      <category>기록/후기</category>
      <category>데브매칭</category>
      <category>코딩테스트</category>
      <category>프로그래머스</category>
      <author>완성</author>
      <guid isPermaLink="true">https://contrabass.tistory.com/120</guid>
      <comments>https://contrabass.tistory.com/120#entry120comment</comments>
      <pubDate>Sun, 26 Mar 2023 11:31:22 +0900</pubDate>
    </item>
  </channel>
</rss>