본문 바로가기

자료구조 & 알고리즘 & cs/자료구조

[TIL] 힙 - Heap

힙(Heap)이란?  

  • 완전 이진 트리(Complete Binary Tree) - 최대/최소값을 빠르게 찾기 위함
  • max heap과 min heap으로 분류 (최대값/최소값을 구하기 위한 구조)
  • 각 노드의 값 >= 해당노드의 자식노드 값 (max heap) (min heap은 반대)
  • 힙 구현시 배열 자료구조를 사용
* 완전 이진 트리 : 노드 삽입 시 가장 하단의 왼쪽 노드부터 차례대로 삽입하는 트리

힙 vs 이진 탐색 트리?
  -힙 : 최대/최소값 검색을 위한 구조
  -이진 탐색 트리 : 탐색을 위한 구조

 

힙의 인덱스 구조

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

 

힙 구현 (max heap)

1. 힙 클래스 구현

class Heap:
	def __init__(self, data):
    	self.heap_arr = list()		#일반적으로 배열로 구현
        self.heap_arr.append(None)	#루트 노드의 인덱스 번호를 1로 하기 위해 None 삽입
        self.heap_arr.append(data)

 

2. 힙 데이터 삽입(insert)

    - 데이터 삽입 시 해당 데이터의 값을 부모 노드와 비교하여 큰 경우 위로 올려주는 swap 처리를 해야한다.

    - swap_up 함수를 따로 만들어 해당 노드를 swap 처리해야하는지 판별하도록 한다.

 

def swap_up(self, ins_idx):
	if ins_idx <=1:		# 삽입한 데이터가 루트 노드인 경우 swap처리 불필요
    	return False
	
    parent_idx = ins_idx //2
    if self.heap_arr[ins_idx] > self.heap_arr[parent_idx]:
        return True
    else:
        return False
def insert(self, data):
    if len(self.heap_arr) == 0:		# 힙에 아무것도 없을 경우 초기화 과정
        self.heap_arr.append(None)
        self.heap_arr.append(data)
        return True

    self.heap_arr.append(data)
    ins_idx = len(self.heap_arr)-1	# 루트 노드 인덱스를 1로 설정하였으므로
    
    while self.swap_up(ins_idx):
        parent_idx = ins_idx//2
        self.heap_arr[ins_idx], self.heap_arr[parent_idx] = self.heap_arr[parent_idx], self.heap_arr[ins_idx]
        ins_idx = parent_idx

    return True

 

2. 힙 데이터 삭제 (pop)

    - 데이터 삭제 시 일반적으로 루트노드를 삭제한다. (최대값 or 최소값)

    - 삭제 후 가장 마지막에 추가한 노드를 root 노드로 이동한 후 자식 노드와 값을 비교하여 swap 처리한다.

    - swap_down 함수를 따로 만들어 해당 노드를 swap 처리해야하는지 판별하도록 한다.

def swap_down(self, pop_idx):
    left_idx = pop_idx*2
    right_idx = pop_idx*2+1
    
    # 노드가 존재하지 않을 때 swap 처리 불필요
    if left_idx >= len(self.heap_arr):
        return False

    # 왼쪽 자식 노드만 존재할 때
    elif right_idx >= len(self.heap_arr):
        if self.heap_arr[pop_idx] < self.heap_arr[left_idx]:
            return True
        else:
            return False

    # 왼쪽, 오른쪽 모든 노드가 존재할 때
    else:
        if self.heap_arr[left_idx] >  self.heap_arr[right_idx]
            if self.heap_arr[left_idx] > self.heap_arr[pop_idx]:
                return True
            else:
                return False
        else:
            if self.heap_arr[right_idx] > self.heap_arr[pop_idx]:
                return True
            else:
                return False
def pop(self):
    if len(self.heap_arr) <=1:		#힙에 None만 존재하거나 데이터가 존재하지 않을 경우 
        return None

    return_data = self.heap_arr[1]
    self.heap_arr[1] = self.heap_arr[-1]		#가장 마지막에 추가한 노드와 교환 후 삭제
    del self.heap_arr[-1]
    pop_idx = 1							#swap_down을 하기 위한 인덱스 설정

    while self.swap_down(pop_idx):
        left_idx = pop_idx*2
        right_idx = pop_idx*2+1

        # 왼쪽 자식 노드만 있을 경우
        if right_idx >= len(self.heap_arr):
            if self.heap_arr[pop_idx] < self.heap_arr[left_idx]:
                self.heap_arr[pop_idx],self.heap_arr[left_idx] = self.heap_arr[left_idx], self.heap_arr[pop_idx]
                pop_idx = left_idx				#인덱스 재설정   
        #모든 노드가 존재할 경우
        else:
            if self.heap_arr[left_idx] > self.heap_arr[right_idx]:
                if self.heap_arr[pop_idx] < self.heap_arr[left_idx]:
                    self.heap_arr[pop_idx],self.heap_arr[left_idx] = self.heap_arr[left_idx], self.heap_arr[pop_idx]
                    pop_idx = left_idx
            else:
                if self.heap_arr[pop_idx] < self.heap_arr[right_idx]:
                    self.heap_arr[pop_idx],self.heap_arr[right_idx] = self.heap_arr[right_idx], self.heap_arr[pop_idx]
                    pop_idx = right_idx

    return return_data			#삭제한 데이터 반환

 

 

힙의 시간복잡도는?
트리의 높이(Depth)를 h라 한다면, 최악의 경우 root에서 leaf 까지 비교하여 h = logn에 가깝다.
따라서 시간복잡도는 O(logn)

* 실행 시 50% 즉, 절반의 실행시간을 단축시킬 수 있으므로

 

 

*본 내용은 패스트 캠퍼스 강의를 참고하였습니다.

728x90

'자료구조 & 알고리즘 & cs > 자료구조' 카테고리의 다른 글

[TIL] 트리 - Tree  (0) 2023.03.06
[TIL] 해쉬 테이블 - Hash Table  (0) 2023.03.02