update and rebuild at 9.21

This commit is contained in:
yenru0 committed 2025-09-22 03:19:55 +09:00
1 parent 37341eaafe
commit eeaa48e9de
12 files changed
+679 -9

No files matched your search

BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
-5
View File
@@ -1,9 +1,4 @@
# Review 1
<style>
html {
-webkit-print-color-adjust: exact;
}
</style>
* Hajin Ju, 2024062806
+1 -1
View File
@@ -1,4 +1,4 @@
# Review 1
# Review 2
* Hajin Ju, 2024062806
+85
View File
@@ -0,0 +1,85 @@
# Review 3
* Hajin Ju, 2024062806
## Problem 1
Write `O` if an entry is true or `X` otherwise.
### Solution 1
| | $$O(n \lg n)$$ | $$\Omega(n \lg n)$$ | $$\Theta(n\lg n)$$ |
| :-----------: | :------------: | :-----------------: | :----------------: |
| $$\lg n$$ | O | X | X |
| $$n$$ | O | X | X |
| $$n \lg n$$ | O | O | O |
| $$n \lg^2 n$$ | X | O | X |
| $$n^2$$ | X | O | X |
## Problem 2
Show $3n + 1 = O(n^2)$ by the definition of $O$.
### Solution 2
A function $f(n) = O(g(n))$ if there exist constants $c\geq 0$ and $n_0\geq 0$, s.t.
$$n \geq n_0 \Rightarrow \leq |f(n)| \leq c |g(n)|$$
---
let $g(n) = n^2$
let $f(n) = 3n+1$
suppose $c=4,\, n_0 = 1$
and then, for all $n \geq 1 \to |3n+1| \leq 4n^2$
therefore, $3n+1 = O(n^2)$ by the above definition.
## Problem 3
Write asymptotic notations that satisfy each relation and explain why.
1. Transitivity
2. Reflexivity
3. Symmetry
### Solution 3
1. Transitivity
* $O$ is transitive
because $f(n) = O(g(n))$ and $g(n) = O(h(n))$ implies $f(n) = O(h(n))$
there must exists $n_0\geq 0$, s.t. $n \geq n_0 \Rightarrow f(n) \leq c_0 g(n) \leq c_1 c_0 h(n)$
* $\Omega$ is transitive
because $f(n) = \Omega(g(n))$ and $g(n) = \Omega(h(n))$ implies $f(n) = \Omega(h(n))$
there must exists $n_0\geq 0$, s.t. $n \geq n_0 \Rightarrow f(n) \geq c_0g(n) \geq c_1 c_0 h(n)$
* $\Theta$ is transitive
because $f(n) = \Theta(g(n))$ and $g(n) = \Theta(h(n))$ implies $f(n) = \Theta(h(n))$
$$f(n) = O(h(n)) \land f(n) = \Omega(h(n))$$
2. Reflexivity
* $O$ is reflexive
because $f(n) = O(f(n))$ where $c=1$
* $\Omega$ is reflexive
because $f(n) = \Omega(f(n))$ where $c=1$
* $\Theta$ is reflexive
* because $f(n) = \Theta(f(n))$
3. Symmetry
* $O$ is **not** symmetric
because $f(n) = O(g(n))$ does not imply $g(n) = O(g(n))$
for example, $n = O(n^2)$ cannot imply $n^2 = O(n)$
* $\Omega$ is **not** symmetric
because $f(n) = \Omega(g(n))$ does not imply $g(n) = \Omega(g(n))$
for example, $n^2 = \Omega(n)$ cannot imply $n = \Omega(n^2)$
* $\Theta$ is symmetric
because $f(n) = \Theta(g(n))$ implies $g(n) = \Theta(g(n))$
+68
View File
@@ -0,0 +1,68 @@
# Review 4-1
* Hajin Ju, 2024062806
## Problem 1
Show that the solution of $T(n) = 2T(\lfloor n / 2 \rfloor) + n $ is $O(n \lg n)$ by the substitution method. (Show the inductive step only.)
### Solution 1
* inductive step
$$T(n) \leq c n \lg n, \quad (\text{for some}\; c > 0,\, n > n_0)$$
We can assume the hypothesis($T(n) = O(n\lg n)$) holds for all positive int smaller than $n$.
then,
$$T(\lfloor n / 2 \rfloor) \leq c \lfloor n / 2 \rfloor \lg {\lfloor n / 2 \rfloor} \leq c (n / 2) \lg ( n / 2)\\= c(n/2)(\lg n - \lg 2)$$
$$\begin{align*}
T(n) &= 2T(\lfloor n / 2 \rfloor) + n \leq cn(\lg n - \lg 2) + n\\
&=cn\lg n - cn \lg 2 + n\\
&=cn \lg - cn + n\\
&\leq cn\lg n
\end{align*}$$
therefore, $T(n) = O(n \lg n)$
## Problem 2
Use a recursion tree to determine a good asymptotic upper bound on the recurrence $T(n) = 3T(\lfloor n / 4 \rfloor) + \theta(n^2)$.
### Solution 2
```mermaid
flowchart TD
A["$$T(n):\;cn^2$$"] --> B1["$$T(n/4):\;cn^2/16$$"];
A --> B2["$$T(n/4):\;cn^2/16$$"];
A --> B3["$$T(n/4):\;cn^2/16$$"];
subgraph L0[ ]
A
end
subgraph L1[ ]
B1
B2
B3
end
```
* level 0
* $cn^2$
* level 1
* $\frac{3}{16}cn^2$
* level $k$
* $(\frac{3}{16})^k cn^2$
* level $\log_4 n$
* $n^{\log_4 3}$
therefore, total cost is
$$\begin{align*}
T(n) &= \sum^{\log_4 n - 1}_{i = 0}(\frac{3}{16})^i cn^2 + \Theta(n^{\log_4 3})\\
&< \sum^{\infty}_{i = 0}(\frac{3}{16})^i cn^2 + \Theta(n^{\log_4 3})\\
&=\frac{16}{13}cn^2 +\Theta(n^{\log_4 3}) = O(n^2)
\end{align*}
$$
+32
View File
@@ -0,0 +1,32 @@
# Review 4-2
* Hajin Ju, 2024062806
## Problem 1
Guess the solution to the recurrence $T(n) = T(n/3) + T(2n/3) + cn$, where $c$ is constant, is $\Theta(n\lg n) by applealing to a recursion tree.$
### Solution 1
* level 0
$\Sigma = cn$
* level 1
$\Sigma = cn/3 + 2cn/3 = cn$
* level 2
$\Sigma = cn/9 + 2cn/9 + 2cn/9 + 4cn/9 = cn$
* level k
$\Sigma = cn$
* level h
$\Sigma = cn$
The shortest depth $n\to 1$ is $h = \lg_{3/2}{n}$
The longest depth $n\to 1$ is $h = \lg_{3}{n}$
so $T(n) = \text{depth} * cn$ and
$cn \lg_{3/2}{n} \leq T(n) \leq cn \lg_{3}{n} $
therefore $T(n) = \Theta(n\lg n)$
+478
View File
@@ -0,0 +1,478 @@
# Review 5
* Hajin Ju, 2024062806
## Problem 1
Illustrate the operation of `HEAPSORT` on the array $A = \set{5, 13, 2, 25, 7, 17, 20, 8, 4}$
### Solution 1
* BUILD-MAX-HEAP
```python { cmd, output='html' hide }
from bs4 import BeautifulSoup
import math
# --- SVG 생성을 위한 설정값 ---
CONFIG = {
'canvas_padding': 10,
'node_radius': 12,
'font_size': 10,
'x_spacing': 30, # 형제 노드 간 최소 수평 간격
'y_spacing': 40, # 세대 간 수직 간격
'stroke_width': 1.5,
'colors': {
'node_border': '#aaa',
'node_bg': '#fff',
'node_text': '#333',
'line': '#ccc',
'active_border': '#c0392b',
'active_bg': '#f2d7d5',
}
}
def calculate_positions(arr):
"""2-Pass 알고리즘을 사용하여 노드 좌표를 계산합니다."""
positions = {}
if not arr:
return {}, 0, 0
initial_y = CONFIG['canvas_padding'] + CONFIG['node_radius']
# 1단계: In-order 순회로 겹치지 않는 초기 x 좌표 할당
x_next = 0
def assign_initial_x(i):
nonlocal x_next
if i >= len(arr) or arr[i] is None:
return
assign_initial_x(2 * i + 1) # 왼쪽 서브트리
y = int(math.log2(i + 1)) * CONFIG['y_spacing'] + initial_y
positions[i] = (x_next, y)
x_next += CONFIG['x_spacing']
assign_initial_x(2 * i + 2) # 오른쪽 서브트리
assign_initial_x(0)
# 2단계: Post-order 순회로 부모 노드를 자식들의 중앙으로 재조정
def center_parents(i):
if i >= len(arr) or arr[i] is None:
return
left_child, right_child = 2 * i + 1, 2 * i + 2
center_parents(left_child)
center_parents(right_child)
has_left = left_child < len(arr) and left_child in positions
has_right = right_child < len(arr) and right_child in positions
# 자식이 있는 경우에만 부모 위치 조정
if has_left and has_right:
# 자식이 둘 다 있으면 그 중앙으로 이동
left_x = positions[left_child][0]
right_x = positions[right_child][0]
positions[i] = ((left_x + right_x) / 2, positions[i][1])
elif has_left and not has_right:
# 왼쪽 자식만 있으면 그 위로 이동
positions[i] = (positions[left_child][0], positions[i][1])
elif not has_left and has_right:
# 오른쪽 자식만 있으면 그 위로 이동
positions[i] = (positions[right_child][0], positions[i][1])
center_parents(0)
# 맨 왼쪽 노드가 잘리지 않도록 전체 트리 이동
if not positions: return {}, 0, 0
min_x = min(p[0] for p in positions.values())
x_shift = 0
if min_x < CONFIG['canvas_padding'] + CONFIG['node_radius']:
x_shift = -min_x + CONFIG['canvas_padding'] + CONFIG['node_radius']
shifted_positions = {i: (x + x_shift, y) for i, (x, y) in positions.items()}
max_x = max(p[0] for p in shifted_positions.values())
max_y = max(p[1] for p in shifted_positions.values())
canvas_width = max_x + CONFIG['canvas_padding'] + CONFIG['node_radius']
canvas_height = max_y + CONFIG['canvas_padding'] + CONFIG['node_radius']
return shifted_positions, canvas_width, canvas_height
def create_single_tree_svg(soup, step_data):
# (이전과 동일, 변경 없음)
arr = step_data.get('heap', [])
highlighted = step_data.get('highlighted', set())
positions, width, height = calculate_positions(arr)
svg = soup.new_tag('svg', attrs={'width': width, 'height': height, 'xmlns': "http://www.w3.org/2000/svg"})
for i in range(len(arr)):
if i not in positions: continue
px, py = positions[i]
left_child, right_child = 2 * i + 1, 2 * i + 2
if left_child < len(arr) and left_child in positions:
cx, cy = positions[left_child]
svg.append(soup.new_tag('line', attrs={'x1': px, 'y1': py, 'x2': cx, 'y2': cy, 'stroke': CONFIG['colors']['line'], 'stroke-width': CONFIG['stroke_width']}))
if right_child < len(arr) and right_child in positions:
cx, cy = positions[right_child]
svg.append(soup.new_tag('line', attrs={'x1': px, 'y1': py, 'x2': cx, 'y2': cy, 'stroke': CONFIG['colors']['line'], 'stroke-width': CONFIG['stroke_width']}))
for i, val in enumerate(arr):
if i not in positions: continue
x, y = positions[i]
is_active = i in highlighted
svg.append(soup.new_tag('circle', attrs={'cx': x, 'cy': y, 'r': CONFIG['node_radius'], 'stroke': CONFIG['colors']['active_border'] if is_active else CONFIG['colors']['node_border'], 'stroke-width': CONFIG['stroke_width'], 'fill': CONFIG['colors']['active_bg'] if is_active else CONFIG['colors']['node_bg']}))
svg.append(soup.new_tag('text', attrs={'x': x, 'y': y, 'font-family': 'monospace', 'font-size': CONFIG['font_size'], 'text-anchor': 'middle', 'dominant-baseline': 'central', 'fill': CONFIG['colors']['node_text'], 'font-weight': 'bold' if is_active else 'normal'}))
svg.find_all('text')[-1].string = str(val)
return svg
def create_heap_visualization_div(steps_data):
# (이전과 동일, 변경 없음)
soup = BeautifulSoup("", "html.parser")
wrapper_div = soup.new_tag("div")
style = soup.new_tag("style")
style.string = """.heap-svg-flow { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; justify-content: flex-start; } .heap-svg-flow .arrow { font-size: 24px; color: #555; }"""
wrapper_div.append(style)
flow_container = soup.new_tag("div", attrs={"class": "heap-svg-flow"})
wrapper_div.append(flow_container)
for i, step in enumerate(steps_data):
svg_tree = create_single_tree_svg(soup, step)
flow_container.append(svg_tree)
if i < len(steps_data) - 1:
arrow = soup.new_tag("div", attrs={"class": "arrow"})
arrow.string = "→"
flow_container.append(arrow)
return wrapper_div.prettify()
# --- 🚀 메인 실행 부분 ---
if __name__ == "__main__":
MANUAL_STEPS = [
{"heap": [5, 13, 2, 25, 7, 17, 20, 8, 4], "highlighted": set()},
{"heap": [5, 13, 2, 25, 7, 17, 20, 8, 4], "highlighted": {8, 7, 3}},
{"heap": [5, 13, 20, 25, 7, 17, 2, 8, 4], "highlighted": {2, 5, 6}},
{"heap": [5, 25, 20, 13, 7, 17, 2, 8, 4], "highlighted": {1, 3, 4, 7, 8}},
{"heap": [25, 13, 20, 8, 7, 17, 2, 5, 4], "highlighted": {0, 1, 2, 3, 4, 5, 6, 7, 8}},
]
html_output = create_heap_visualization_div(MANUAL_STEPS)
print(html_output)
```
* EXTRACT-MAX
```python { cmd, output='html' hide }
from bs4 import BeautifulSoup
import math
# --- SVG 생성을 위한 설정값 ---
CONFIG = {
'canvas_padding': 10,
'node_radius': 12,
'font_size': 10,
'x_spacing': 30, # 형제 노드 간 최소 수평 간격
'y_spacing': 40, # 세대 간 수직 간격
'stroke_width': 1.5,
'colors': {
'node_border': '#aaa',
'node_bg': '#fff',
'node_text': '#333',
'line': '#ccc',
'active_border': '#c0392b',
'active_bg': '#f2d7d5',
}
}
def calculate_positions(arr):
"""2-Pass 알고리즘을 사용하여 노드 좌표를 계산합니다."""
positions = {}
if not arr:
return {}, 0, 0
initial_y = CONFIG['canvas_padding'] + CONFIG['node_radius']
# 1단계: In-order 순회로 겹치지 않는 초기 x 좌표 할당
x_next = 0
def assign_initial_x(i):
nonlocal x_next
if i >= len(arr) or arr[i] is None:
return
assign_initial_x(2 * i + 1) # 왼쪽 서브트리
y = int(math.log2(i + 1)) * CONFIG['y_spacing'] + initial_y
positions[i] = (x_next, y)
x_next += CONFIG['x_spacing']
assign_initial_x(2 * i + 2) # 오른쪽 서브트리
assign_initial_x(0)
# 2단계: Post-order 순회로 부모 노드를 자식들의 중앙으로 재조정
def center_parents(i):
if i >= len(arr) or arr[i] is None:
return
left_child, right_child = 2 * i + 1, 2 * i + 2
center_parents(left_child)
center_parents(right_child)
has_left = left_child < len(arr) and left_child in positions
has_right = right_child < len(arr) and right_child in positions
# 자식이 있는 경우에만 부모 위치 조정
if has_left and has_right:
# 자식이 둘 다 있으면 그 중앙으로 이동
left_x = positions[left_child][0]
right_x = positions[right_child][0]
positions[i] = ((left_x + right_x) / 2, positions[i][1])
elif has_left and not has_right:
# 왼쪽 자식만 있으면 그 위로 이동
positions[i] = (positions[left_child][0], positions[i][1])
elif not has_left and has_right:
# 오른쪽 자식만 있으면 그 위로 이동
positions[i] = (positions[right_child][0], positions[i][1])
center_parents(0)
# 맨 왼쪽 노드가 잘리지 않도록 전체 트리 이동
if not positions: return {}, 0, 0
min_x = min(p[0] for p in positions.values())
x_shift = 0
if min_x < CONFIG['canvas_padding'] + CONFIG['node_radius']:
x_shift = -min_x + CONFIG['canvas_padding'] + CONFIG['node_radius']
shifted_positions = {i: (x + x_shift, y) for i, (x, y) in positions.items()}
max_x = max(p[0] for p in shifted_positions.values())
max_y = max(p[1] for p in shifted_positions.values())
canvas_width = max_x + CONFIG['canvas_padding'] + CONFIG['node_radius']
canvas_height = max_y + CONFIG['canvas_padding'] + CONFIG['node_radius']
return shifted_positions, canvas_width, canvas_height
def create_single_tree_svg(soup, step_data):
# (이전과 동일, 변경 없음)
arr = step_data.get('heap', [])
highlighted = step_data.get('highlighted', set())
positions, width, height = calculate_positions(arr)
svg = soup.new_tag('svg', attrs={'width': width, 'height': height, 'xmlns': "http://www.w3.org/2000/svg"})
for i in range(len(arr)):
if i not in positions: continue
px, py = positions[i]
left_child, right_child = 2 * i + 1, 2 * i + 2
if left_child < len(arr) and left_child in positions:
cx, cy = positions[left_child]
svg.append(soup.new_tag('line', attrs={'x1': px, 'y1': py, 'x2': cx, 'y2': cy, 'stroke': CONFIG['colors']['line'], 'stroke-width': CONFIG['stroke_width']}))
if right_child < len(arr) and right_child in positions:
cx, cy = positions[right_child]
svg.append(soup.new_tag('line', attrs={'x1': px, 'y1': py, 'x2': cx, 'y2': cy, 'stroke': CONFIG['colors']['line'], 'stroke-width': CONFIG['stroke_width']}))
for i, val in enumerate(arr):
if i not in positions: continue
x, y = positions[i]
is_active = i in highlighted
svg.append(soup.new_tag('circle', attrs={'cx': x, 'cy': y, 'r': CONFIG['node_radius'], 'stroke': CONFIG['colors']['active_border'] if is_active else CONFIG['colors']['node_border'], 'stroke-width': CONFIG['stroke_width'], 'fill': CONFIG['colors']['active_bg'] if is_active else CONFIG['colors']['node_bg']}))
svg.append(soup.new_tag('text', attrs={'x': x, 'y': y, 'font-family': 'monospace', 'font-size': CONFIG['font_size'], 'text-anchor': 'middle', 'dominant-baseline': 'central', 'fill': CONFIG['colors']['node_text'], 'font-weight': 'bold' if is_active else 'normal'}))
svg.find_all('text')[-1].string = str(val)
return svg
def create_heap_visualization_div(steps_data):
# (이전과 동일, 변경 없음)
soup = BeautifulSoup("", "html.parser")
wrapper_div = soup.new_tag("div")
style = soup.new_tag("style")
style.string = """.heap-svg-flow { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; justify-content: flex-start; } .heap-svg-flow .arrow { font-size: 24px; color: #555; }"""
wrapper_div.append(style)
flow_container = soup.new_tag("div", attrs={"class": "heap-svg-flow"})
wrapper_div.append(flow_container)
for i, step in enumerate(steps_data):
svg_tree = create_single_tree_svg(soup, step)
flow_container.append(svg_tree)
if i < len(steps_data) - 1:
arrow = soup.new_tag("div", attrs={"class": "arrow"})
arrow.string = "→"
flow_container.append(arrow)
return wrapper_div.prettify()
# --- 🚀 메인 실행 부분 ---
if __name__ == "__main__":
MANUAL_STEPS = [
{"heap": [25, 13, 20, 8, 7, 17, 2, 5, 4], "highlighted": set()},
{"heap": [20, 13, 17, 8, 7, 4, 2, 5], "highlighted": set()},
{"heap": [17, 13, 5, 8, 7, 4, 2], "highlighted": set()},
{"heap": [13, 8, 5, 2, 7, 4], "highlighted": set()},
{"heap": [8, 7, 5, 2, 4], "highlighted": set()},
{"heap": [7, 4, 5, 2], "highlighted": set()},
]
html_output = create_heap_visualization_div(MANUAL_STEPS)
print(html_output)
```
```
out 25 -> out 20 -> out 17 -> out 13 -> out 8
```
* MAX-HEAP-INSERT(A, 15)
```python { cmd, output='html' hide }
from bs4 import BeautifulSoup
import math
# --- SVG 생성을 위한 설정값 ---
CONFIG = {
'canvas_padding': 10,
'node_radius': 12,
'font_size': 10,
'x_spacing': 30, # 형제 노드 간 최소 수평 간격
'y_spacing': 40, # 세대 간 수직 간격
'stroke_width': 1.5,
'colors': {
'node_border': '#aaa',
'node_bg': '#fff',
'node_text': '#333',
'line': '#ccc',
'active_border': '#c0392b',
'active_bg': '#f2d7d5',
}
}
def calculate_positions(arr):
"""2-Pass 알고리즘을 사용하여 노드 좌표를 계산합니다."""
positions = {}
if not arr:
return {}, 0, 0
initial_y = CONFIG['canvas_padding'] + CONFIG['node_radius']
# 1단계: In-order 순회로 겹치지 않는 초기 x 좌표 할당
x_next = 0
def assign_initial_x(i):
nonlocal x_next
if i >= len(arr) or arr[i] is None:
return
assign_initial_x(2 * i + 1) # 왼쪽 서브트리
y = int(math.log2(i + 1)) * CONFIG['y_spacing'] + initial_y
positions[i] = (x_next, y)
x_next += CONFIG['x_spacing']
assign_initial_x(2 * i + 2) # 오른쪽 서브트리
assign_initial_x(0)
# 2단계: Post-order 순회로 부모 노드를 자식들의 중앙으로 재조정
def center_parents(i):
if i >= len(arr) or arr[i] is None:
return
left_child, right_child = 2 * i + 1, 2 * i + 2
center_parents(left_child)
center_parents(right_child)
has_left = left_child < len(arr) and left_child in positions
has_right = right_child < len(arr) and right_child in positions
# 자식이 있는 경우에만 부모 위치 조정
if has_left and has_right:
# 자식이 둘 다 있으면 그 중앙으로 이동
left_x = positions[left_child][0]
right_x = positions[right_child][0]
positions[i] = ((left_x + right_x) / 2, positions[i][1])
elif has_left and not has_right:
# 왼쪽 자식만 있으면 그 위로 이동
positions[i] = (positions[left_child][0], positions[i][1])
elif not has_left and has_right:
# 오른쪽 자식만 있으면 그 위로 이동
positions[i] = (positions[right_child][0], positions[i][1])
center_parents(0)
# 맨 왼쪽 노드가 잘리지 않도록 전체 트리 이동
if not positions: return {}, 0, 0
min_x = min(p[0] for p in positions.values())
x_shift = 0
if min_x < CONFIG['canvas_padding'] + CONFIG['node_radius']:
x_shift = -min_x + CONFIG['canvas_padding'] + CONFIG['node_radius']
shifted_positions = {i: (x + x_shift, y) for i, (x, y) in positions.items()}
max_x = max(p[0] for p in shifted_positions.values())
max_y = max(p[1] for p in shifted_positions.values())
canvas_width = max_x + CONFIG['canvas_padding'] + CONFIG['node_radius']
canvas_height = max_y + CONFIG['canvas_padding'] + CONFIG['node_radius']
return shifted_positions, canvas_width, canvas_height
def create_single_tree_svg(soup, step_data):
# (이전과 동일, 변경 없음)
arr = step_data.get('heap', [])
highlighted = step_data.get('highlighted', set())
positions, width, height = calculate_positions(arr)
svg = soup.new_tag('svg', attrs={'width': width, 'height': height, 'xmlns': "http://www.w3.org/2000/svg"})
for i in range(len(arr)):
if i not in positions: continue
px, py = positions[i]
left_child, right_child = 2 * i + 1, 2 * i + 2
if left_child < len(arr) and left_child in positions:
cx, cy = positions[left_child]
svg.append(soup.new_tag('line', attrs={'x1': px, 'y1': py, 'x2': cx, 'y2': cy, 'stroke': CONFIG['colors']['line'], 'stroke-width': CONFIG['stroke_width']}))
if right_child < len(arr) and right_child in positions:
cx, cy = positions[right_child]
svg.append(soup.new_tag('line', attrs={'x1': px, 'y1': py, 'x2': cx, 'y2': cy, 'stroke': CONFIG['colors']['line'], 'stroke-width': CONFIG['stroke_width']}))
for i, val in enumerate(arr):
if i not in positions: continue
x, y = positions[i]
is_active = i in highlighted
svg.append(soup.new_tag('circle', attrs={'cx': x, 'cy': y, 'r': CONFIG['node_radius'], 'stroke': CONFIG['colors']['active_border'] if is_active else CONFIG['colors']['node_border'], 'stroke-width': CONFIG['stroke_width'], 'fill': CONFIG['colors']['active_bg'] if is_active else CONFIG['colors']['node_bg']}))
svg.append(soup.new_tag('text', attrs={'x': x, 'y': y, 'font-family': 'monospace', 'font-size': CONFIG['font_size'], 'text-anchor': 'middle', 'dominant-baseline': 'central', 'fill': CONFIG['colors']['node_text'], 'font-weight': 'bold' if is_active else 'normal'}))
svg.find_all('text')[-1].string = str(val)
return svg
def create_heap_visualization_div(steps_data):
# (이전과 동일, 변경 없음)
soup = BeautifulSoup("", "html.parser")
wrapper_div = soup.new_tag("div")
style = soup.new_tag("style")
style.string = """.heap-svg-flow { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; justify-content: flex-start; } .heap-svg-flow .arrow { font-size: 24px; color: #555; }"""
wrapper_div.append(style)
flow_container = soup.new_tag("div", attrs={"class": "heap-svg-flow"})
wrapper_div.append(flow_container)
for i, step in enumerate(steps_data):
svg_tree = create_single_tree_svg(soup, step)
flow_container.append(svg_tree)
if i < len(steps_data) - 1:
arrow = soup.new_tag("div", attrs={"class": "arrow"})
arrow.string = "→"
flow_container.append(arrow)
return wrapper_div.prettify()
# --- 🚀 메인 실행 부분 ---
if __name__ == "__main__":
MANUAL_STEPS = [
{"heap": [16, 14, 10, 8, 7, 9, 3, 2, 4, 1], "highlighted": set()},
{"heap": [16, 14, 10, 8, 7, 9, 3, 2, 4, 1, 15], "highlighted": {10}},
{"heap": [16, 15, 10, 8, 14, 9, 3, 2, 4, 1, 7], "highlighted": set()},
]
html_output = create_heap_visualization_div(MANUAL_STEPS)
print(html_output)
```
## Problem 2
Fill in the blanks in the following pseudocode for Heapsort.
### Solution 2
```{ .line-numbers }
HEAPSORT(A)
BUILD-MAX-HEAP
for i = A.length downto 2
exchange A[1] with A[i]
A.heap-size = A.heap-size - 1
MAX-HEAPIFY(A, 1)
```