yooniiverse
개발 블로그
yooniiverse
전체 방문자
오늘
어제
  • 분류 전체보기
    • 운영체제
    • 네트워크
    • ~2023.02
      • 외부교육
      • 대외활동
      • 스터디
      • 동아리
      • TIL
      • IT지식
      • 기타
      • 트러블 슈팅
      • 프로그래밍
      • Python
      • Java
      • JS
      • DB(SQL)
      • JSP
      • Spring
      • 기술면접
      • 자바
      • 코딩테스트
      • 자료구조
      • 알고리즘
      • 백준 문제풀이
      • 인공지능
      • 머신러닝
      • 프로젝트
      • 안드로이드 앱개발
      • 웹개발
      • 웹 서비스
      • 웹퍼블리싱
      • Node.js 백엔드 개발
      • CS
      • 1일 1CS지식
      • 운영체제
      • 네트워크
      • 데이터베이스
      • 정보처리기사
      • 도서 리뷰
      • 개발 관련 도서
      • 기타 도서

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
yooniiverse

개발 블로그

힙(Heap)
~2023.02/자료구조

힙(Heap)

2022. 4. 2. 20:32

1. 힙(Heap) 이란?


  • 힙 : 데이터에서 최댓값과 최솟값을 빠르게 찾기 위해 고안된 완전 이진 트리(Complete Binary Tree)
    • 완전 이진 트리 : 노드를 삽입할 때 최하단 왼쪽 노드부터 차례대로 삽입하는 트리

  • 힙을 사용하는 이유
    • 배열에 데이터를 넣고, 최댓값과 최솟값을 찾으려면 O(n)이 걸림
    • 이에 반해, 힙에 데이터를 넣고, 최대값과 최솟값을 찾으면, O(logn) 이 걸림
    • 우선순위 큐와 같이 최대값 또는 최솟값을 빠르게 찾아야 하는 자료구조 및 알고리즘 구현 등에 활용됨

 

 

2. 힙(Heap) 구조


  • 힙은 최대값을 구하기 위한 구조 (최대 힙, Max Heap) 와, 최솟값을 구하기 위한 구조 (최소 힙, Min Heap) 로 분류할 수 있음
  • 힙은 다음과 같이 두 가지 조건을 가지고 있는 자료구조임
    1. 각 노드의 값은 해당 노드의 자식 노드가 가진 값보다 크거나 같다. (최대 힙의 경우)
      • 최소 힙의 경우는 각 노드의 값은 해당 노드의 자식 노드가 가진 값보다 크거나 작음
    2. 완전 이진 트리 형태를 가짐

 

[힙과 이진 탐색 트리의 공통점과 차이점]

  • 공통점 : 힙과 이진 탐색 트리는 모두 이진 트리임
  • 차이점 :
    • 힙은 각 노드의 값이 자식 노드보다 크거나 같음 (Max Heap의 경우)
    • 이진 탐색 트리는 왼쪽 자식 노드의 값이 가장 작고, 그다음 부모 노드, 그 다음 오른쪽 자식 값이 가장 큼
    • 힙은 이진 탐색 트리의 조건인 자식 노드에서 작은 값은 왼쪽, 큰 값은 오른쪽이라는 조건은 없음
      • 힙의 왼쪽 및 오른쪽 자식 노드의 값은 오른쪽이 클 수도 있고, 왼쪽이 클 수도 있음
  • 이진 탐색 트리는 탐색을 위한 구조, 힙은 최대/최솟값 검색을 위한 구조 중 하나로 이해하면 됨

 

 

3. 힙(Heap) 동작


  • 데이터를 힙 구조에 삽입, 삭제하는 과정을 그림을 통해 선명하게 이해하기

https://visualgo.net/en/heap

 

Binary Heap (Priority Queue) - VisuAlgo

VisuAlgo is free of charge for Computer Science community on earth. If you like VisuAlgo, the only "payment" that we ask of you is for you to tell the existence of VisuAlgo to other Computer Science students/instructors that you know =) via Facebook/Twitte

visualgo.net

 

[힙에 데이터 삽입하기 - 기본 동작]

  • 힙은 완전 이진 트리이므로, 삽입할 노드는 기본적으로 왼쪽 최하단부 노드부터 채워지는 형태로 삽입

 

[힙에 데이터 삽입하기 - 삽입할 데이터가 힙의 데이터보다 클 경우 (Max Heap의 예)]

  • 먼저 삽입된 데이터는 완전 이진 트리 구조에 맞추어, 최하단부 왼쪽 노드부터 채워짐
  • 채워진 노드 위치에서, 부모 노드보다 값이 클 경우, 부모 노드와 위치를 바꿔주는 작업을 반복함 (swap)

 

[힙의 데이터 삭제하기 (Max Heap의 예)]

  • 보통 삭제는 최상단 노드 (root 노드) 를 삭제하는 것이 일반적임
    • 힙의 용도는 최대값 또는 최소값을 root 노드에 놓아서, 최대값과 최소값을 바로 꺼낼 수 있도록 하는 것임
  • 상단의 데이터 삭제시, 가장 최하단부 왼쪽에 위치한 노드 (일반적으로 가장 마지막에 추가한 노드) 를 root 노드로 이동
  • root 노드의 값이 child node 보다 작을 경우, root 노드의 child node 중 가장 큰 값을 가진 노드와 root 노드 위치를 바꿔주는 작업을 반복함 (swap)

 

 

4. 힙(Heap) 구현


[힙과 배열]

  • 일반적으로 힙 구현시 배열 자료구조를 활용함
  • 배열은 인덱스가 0번부터 시작하지만, 힙 구현의 편의를 위해, root 노드 인덱스 번호를 1로 지정하면, 구현이 좀 더 수월함
    • 부모 노드 인덱스 번호 = 자식 노드 인덱스 번호 // 2
    • 왼쪽 자식 노드 인덱스 번호 = 부모 노드 인덱스 번호 * 2
    • 오른쪽 자식 노드 인덱스 번호 = 부모 노드 인덱스 번호 * 2 + 1

 

[힙 클래스 구현1]

 

[힙 클래스 구현2 - insert1]

  • 인덱스 번호는 1번부터 시작하도록 변경

 

[힙 클래스 구현3 - insert2]

  • 삽입한 노드가 부모 노드의 값보다 클 경우, 부모 노드와 삽입한 노드 위치를 바꿈
  • 삽입한 노드가 루트 노드가 되거나, 부모 노드보다 값이 작거나 같을 경우까지 반복
class Heap:
  def __init__(self, data):
    self.heap_array = list()
    self.heap_array.append(None)
    self.heap_array.append(data)

  def move_up(self, inserted_idx):
    if inserted_idx <= 1:
      return False

    parent_idx = inserted_idx // 2
    if self.heap_array[inserted_idx] > self.heap_array[parent_idx]:
      return True
    else:
      return False

  def insert(self, data):
    if len(self.heap_array) == 0:
      self.heap_array.append(None)
      self.heap_array.append(data)
      return True

    self.heap_array.append(data)

    inserted_idx = len(self.heap_array) - 1

    while self.move_up(inserted_idx):
      parent_idx = inserted_idx // 2
      self.heap_array[inserted_idx], self.heap_array[parent_idx] = self.heap_array[parent_idx], self.heap_array[inserted_idx]
      inserted_idx = parent_idx

    return True
heap = Heap(15)
heap.insert(10)
heap.insert(8)
heap.insert(5)
heap.insert(4)
heap.insert(20)
heap.heap_array
[None, 20, 10, 15, 5, 4, 8]

 

[특정 노드의 관련 노드 위치 알아내기]

  • 부모 노드 인덱스 번호 = 자식 노드 인덱스 번호 // 2
  • 왼쪽 자식 노드 인덱스 번호 = 부모 노드 인덱스 번호 * 2
  • 오른쪽 자식 노드 인덱스 번호 = 부모 노드 인덱스 번호 * 2 + 1

 

 

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

스택(Stack)  (0) 2022.04.02
알고리즘 복잡도 표현 기법  (0) 2022.02.25
큐(Queue)  (0) 2022.01.15
해쉬(Hash)  (0) 2022.01.11
배열  (0) 2021.11.26
    '~2023.02/자료구조' 카테고리의 다른 글
    • 스택(Stack)
    • 알고리즘 복잡도 표현 기법
    • 큐(Queue)
    • 해쉬(Hash)
    yooniiverse
    yooniiverse

    티스토리툴바