Heap 은 완전 이진 트리에 있는 노드 중 키 값이 가장 큰 노드나 키 값이 가장 작은 노드를 찾기 위해 만들어진 자료구조이다.
Heap 은 Max Heap 과 Min Heap 이 있다.(Max Min Heap 도 있지만 생략)
Max Heap 은 부모 노드의 키값 >= 자식 노드의 키값 이면서 완전 이진 트리를 만족해야 한다.
반면 Min Heap 은 부모 노드의 키값 <= 자식 노드의 키값이면서 완전 이진 트리를 만족해야 한다.
삽입과 삭제 시에 마지막 노드가 증가, 삭제되고 노드들을 서로 교체해줘야 하며, 완전 이진 트리이므로(루트부터 마지막 노드까지는 노드가 무조건 존재) Heap 은 배열로 구현하는 게 편하다.
참고로 이진 트리를 배열로 구현하였을 때 노드의 배열 인덱스 구하는 방법은 아래와 같다.
노드의 인덱스를 i, 마지막 노드의 인덱스를 n 이라 할 때,
삽입은 마지막 노드의 다음 자리에 새로운 노드를 삽입하고, 부모 노드와 비교하여 조건에 맞게 교체하는 작업을 루트 노드까지 반복한다.
삭제는 루트 노드를 삭제하고 그 자리에 마지막 노드를 올린다. 이후 부모, 왼쪽 자식, 오른쪽 자식 노드를 비교하여 힙 조건을 만족하도록 부모를 변경해 준다. 그 다음 변경된 자식 노드를 부모로 하여 이를 자식 노드가 없을때까지 반복한다.
결과>
Heap 은 Max Heap 과 Min Heap 이 있다.(Max Min Heap 도 있지만 생략)
Max Heap 은 부모 노드의 키값 >= 자식 노드의 키값 이면서 완전 이진 트리를 만족해야 한다.
반면 Min Heap 은 부모 노드의 키값 <= 자식 노드의 키값이면서 완전 이진 트리를 만족해야 한다.
삽입과 삭제 시에 마지막 노드가 증가, 삭제되고 노드들을 서로 교체해줘야 하며, 완전 이진 트리이므로(루트부터 마지막 노드까지는 노드가 무조건 존재) Heap 은 배열로 구현하는 게 편하다.
참고로 이진 트리를 배열로 구현하였을 때 노드의 배열 인덱스 구하는 방법은 아래와 같다.
노드의 인덱스를 i, 마지막 노드의 인덱스를 n 이라 할 때,
| i의 부모 노드 | i / 2(소수점 버림) | 단, i > 1 |
| i의 왼쪽 자식 노드 |
2 * i |
단, (2 * i) <= n |
| i의 오른쪽 자식 노드 |
2 * i + 1 |
단, (2 * i + 1) <= n |
| 루트 노드 |
1 |
단, 0 < n |
삽입은 마지막 노드의 다음 자리에 새로운 노드를 삽입하고, 부모 노드와 비교하여 조건에 맞게 교체하는 작업을 루트 노드까지 반복한다.
삭제는 루트 노드를 삭제하고 그 자리에 마지막 노드를 올린다. 이후 부모, 왼쪽 자식, 오른쪽 자식 노드를 비교하여 힙 조건을 만족하도록 부모를 변경해 준다. 그 다음 변경된 자식 노드를 부모로 하여 이를 자식 노드가 없을때까지 반복한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
# Heap Implementation
# Jungtaek Lim(Heart), 2009-03-04
class HeapNode
attr_accessor :key, :value
end
class Heap
def initialize(is_max_heap)
@is_max_heap = is_max_heap
@memory = []
@last_index = 0
end
def insert_data(key, value)
node = HeapNode.new
node.key = key
node.value = value
@last_index += 1
@memory[@last_index] = node
@current_index = @last_index
@parent_index = @current_index / 2
while @parent_index != 0
if true == check_swap_by_index(@parent_index, @current_index)
swap_node(@parent_index, @current_index)
end
@current_index = @parent_index
@parent_index = @current_index / 2
end
end
def delete_data
return nil if @last_index == 0
ret_node = @memory[1]
last_node = @memory[@last_index]
@memory[1] = last_node
@last_index -= 1
current_index = 1
while current_index < @last_index
left_child_index = current_index * 2
right_child_index = current_index * 2 + 1
parent_key = @memory[current_index].key
if left_child_index > @last_index
left_key = (true == @is_max_heap ? -9999999 : 9999999)
else
left_key = @memory[left_child_index].key
end
if right_child_index > @last_index
right_key = (true == @is_max_heap ? -9999999 : 9999999)
else
right_key = @memory[right_child_index].key
end
if true == check_max_or_min(left_key, parent_key) &&
true == check_max_or_min(left_key, right_key)
swap_node(left_child_index, current_index)
current_index = left_child_index
elsif true == check_max_or_min(right_key, parent_key) &&
true == check_max_or_min(right_key, left_key)
swap_node(right_child_index, current_index)
current_index = right_child_index
else
break
end
end
return ret_node
end
def print_data
print "["
(1..@last_index).each do |i|
print "(" + @memory[i].key.to_s + "," + @memory[i].value.to_s + ")"
end
puts "]"
end
private
def check_max_or_min(key1, key2)
if @is_max_heap
return (key1 >= key2 ? true : false)
else
return (key1 <= key2 ? true : false)
end
end
def check_swap_by_index(parent_index, current_index)
if @is_max_heap
return (@memory[@parent_index].key <= @memory[@current_index].key ? true : false)
else
return (@memory[@parent_index].key >= @memory[@current_index].key ? true : false)
end
end
def swap_node(index1, index2)
temp = @memory[index1]
@memory[index1] = @memory[index2]
@memory[index2] = temp
end
end
def make_example_max_heap
heap = Heap.new(true)
heap.insert_data(8, 0)
heap.insert_data(13, 0)
heap.insert_data(10, 0)
heap.insert_data(15, 0)
heap.insert_data(19, 0)
heap.insert_data(20, 0)
return heap
end
heap = make_example_max_heap
heap.insert_data(17, 0)
heap.print_data
heap = make_example_max_heap
heap.insert_data(23, 0)
heap.print_data
heap = make_example_max_heap
heap.insert_data(14, 0)
heap.print_data
heap.delete_data
heap.print_data
|
결과>
[(20,0)(15,0)(19,0)(8,0)(13,0)(10,0)(17,0)]
[(23,0)(15,0)(20,0)(8,0)(13,0)(10,0)(19,0)]
[(20,0)(15,0)(19,0)(8,0)(13,0)(10,0)(14,0)]
[(19,0)(15,0)(14,0)(8,0)(13,0)(10,0)]
'Dev.Programming > DS/Algorithm' 카테고리의 다른 글
| 인접 리스트로 구현한 Graph - in Ruby (2) | 2009/03/16 |
|---|---|
| 인접 행렬로 구현한 Graph - in Ruby (0) | 2009/03/16 |
| Heap - in Ruby (0) | 2009/03/05 |
| Binary Search Tree - in Ruby (0) | 2009/03/04 |
| Binary Tree - in Ruby (0) | 2009/03/04 |
| Deck(Deque, Double-ended Queue) - in Ruby (0) | 2009/03/04 |


