Skip to content

Commit dceae64

Browse files
committed
feat(visualizations): add kth largest element max heap visualization
Implement step-by-step visualization of finding the kth largest element using a max heap data structure. The visualization renders the heap as an actual binary tree with SVG nodes and edges, showing both sift-up operations during heap construction and sift-down operations during element extraction. The tree view dynamically scales based on heap size to accommodate larger arrays without requiring scrolling. Node radius and level spacing shrink proportionally as more levels are added, keeping the entire heap visible within the fixed container. Font sizes also scale with node size to maintain readability. The visualization includes a synchronized array representation below the tree, an extracted elements section that builds up as elements are popped, and highlights for current node, parent, children, and the larger child during comparisons. Signed-off-by: Ayush Joshi <ayush854032@gmail.com>
1 parent 5f2ca7c commit dceae64

6 files changed

Lines changed: 1154 additions & 0 deletions

File tree

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
from typing import List, Any
2+
3+
4+
def _siftup(heap: List[Any], i: int) -> None:
5+
p = (i - 1) >> 1
6+
if p < 0:
7+
return
8+
# For Max-Heap
9+
# If current node is greater than its parent
10+
# Swap both of them and call heapify again
11+
# for the parent
12+
if heap[i] > heap[p]:
13+
heap[i], heap[p] = heap[p], heap[i]
14+
_siftup(heap, p)
15+
16+
17+
def heappush(heap: List[Any], v: Any) -> None:
18+
heap.append(v)
19+
size = len(heap)
20+
_siftup(heap, size - 1)
21+
22+
23+
def _siftdown(heap: List[Any], size: int, i: int) -> None:
24+
largest = i
25+
l = (i << 1) + 1
26+
r = (i << 1) + 2
27+
if l < size and heap[largest] < heap[l]:
28+
largest = l
29+
if r < size and heap[largest] < heap[r]:
30+
largest = r
31+
if largest != i:
32+
heap[largest], heap[i] = heap[i], heap[largest]
33+
_siftdown(heap, size, largest)
34+
35+
36+
def heappop(heap: List[Any]) -> Any:
37+
if heap:
38+
max = heap[0]
39+
heap[0] = heap[-1]
40+
heap.pop()
41+
size = len(heap)
42+
_siftdown(heap, size, 0)
43+
return max
44+
45+
46+
class Solution:
47+
def findKthLargest(self, nums: List[int], k: int) -> int:
48+
heap = []
49+
for n in nums:
50+
heappush(heap, n)
51+
klargest = []
52+
while len(klargest) < k:
53+
klargest.append(heappop(heap))
54+
return klargest[k - 1]
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import pytest
2+
3+
from algos.arrays.kth_largest_element import Solution
4+
5+
6+
@pytest.fixture
7+
def solution() -> Solution:
8+
return Solution()
9+
10+
11+
def test_kth_largest_element(solution: Solution) -> None:
12+
assert solution.findKthLargest([3, 2, 1, 5, 6, 4], 2) == 5
13+
assert solution.findKthLargest([3, 2, 3, 1, 2, 4, 5, 5, 6], 4) == 4
14+
assert solution.findKthLargest([2, 10, 8, 7, 5, 4, 3, 9, 6, 0, 1], 9) == 2
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Kth Largest Element - Max Heap</title>
7+
<link rel="stylesheet" href="../../shared/css/main.css">
8+
<link rel="stylesheet" href="style.css">
9+
</head>
10+
<body>
11+
<div class="container">
12+
<a href="../../" class="back-link">&larr; Back to all algorithms</a>
13+
<h1>Kth Largest Element</h1>
14+
<p class="description">Find the kth largest element using a max heap with O(n + k log n) time complexity</p>
15+
16+
<div class="controls">
17+
<div class="input-group">
18+
<label>Array:</label>
19+
<input type="text" id="arrayInput" value="3, 2, 1, 5, 6, 4" placeholder="e.g., 3, 2, 1, 5, 6, 4">
20+
</div>
21+
<div class="input-group">
22+
<label>k:</label>
23+
<input type="number" id="kInput" value="2" min="1" max="10" style="width: 60px;">
24+
</div>
25+
<button class="btn-random" id="randomBtn">Random</button>
26+
<button class="btn-primary" id="resetBtn">Reset</button>
27+
<button class="btn-secondary" id="stepBtn">Step</button>
28+
<button class="btn-success" id="playBtn">Play</button>
29+
<div class="speed-control">
30+
<label>Speed:</label>
31+
<input type="range" id="speedSlider" min="100" max="2000" value="800">
32+
</div>
33+
</div>
34+
35+
<div class="main-content">
36+
<div class="visualization">
37+
<div class="section-title">Max Heap (Tree View)</div>
38+
39+
<div class="heap-wrapper">
40+
<svg id="heapTree" class="heap-tree"></svg>
41+
</div>
42+
43+
<div class="section-title">Heap Array</div>
44+
<div class="array-wrapper">
45+
<div class="heap-array" id="heapArray"></div>
46+
</div>
47+
48+
<div class="extracted-section">
49+
<div class="section-title">Extracted Elements (Largest to Smallest)</div>
50+
<div class="extracted-list" id="extractedList"></div>
51+
</div>
52+
53+
<div class="info-panel">
54+
<div class="info-box phase-box">
55+
<h3>Phase</h3>
56+
<div class="info-value" id="phaseValue">-</div>
57+
<div class="info-desc">Current operation</div>
58+
</div>
59+
<div class="info-box size-box">
60+
<h3>Heap Size</h3>
61+
<div class="info-value" id="sizeValue">0</div>
62+
<div class="info-desc">Elements in heap</div>
63+
</div>
64+
<div class="info-box k-box">
65+
<h3>k</h3>
66+
<div class="info-value" id="kValue">2</div>
67+
<div class="info-desc">Target position</div>
68+
</div>
69+
<div class="info-box result-box">
70+
<h3>Result</h3>
71+
<div class="info-value" id="resultValue">-</div>
72+
<div class="info-desc">kth largest</div>
73+
</div>
74+
</div>
75+
76+
<div class="status" id="status">
77+
Click "Step" or "Play" to build the heap and find the kth largest element
78+
</div>
79+
80+
<div class="legend">
81+
<div class="legend-item">
82+
<div class="legend-color root-color"></div>
83+
<span>Root (Max)</span>
84+
</div>
85+
<div class="legend-item">
86+
<div class="legend-color current-color"></div>
87+
<span>Current</span>
88+
</div>
89+
<div class="legend-item">
90+
<div class="legend-color parent-color"></div>
91+
<span>Parent</span>
92+
</div>
93+
<div class="legend-item">
94+
<div class="legend-color child-color"></div>
95+
<span>Child</span>
96+
</div>
97+
<div class="legend-item">
98+
<div class="legend-color extracted-color"></div>
99+
<span>Extracted</span>
100+
</div>
101+
</div>
102+
</div>
103+
104+
<div class="code-panel">
105+
<div class="section-title">Python Code - Kth Largest Element</div>
106+
<div class="code-line" id="code-0">
107+
<span class="code-keyword">def</span> <span class="code-function">findKthLargest</span>(nums, k):
108+
</div>
109+
<div class="code-line" id="code-1">
110+
&nbsp;&nbsp;&nbsp;&nbsp;heap = []
111+
</div>
112+
<div class="code-line" id="code-2">
113+
&nbsp;&nbsp;&nbsp;&nbsp;<span class="code-keyword">for</span> n <span class="code-keyword">in</span> nums:
114+
</div>
115+
<div class="code-line" id="code-3">
116+
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;heappush(heap, n) <span class="code-comment"># sift-up</span>
117+
</div>
118+
<div class="code-line" id="code-4">
119+
&nbsp;&nbsp;&nbsp;&nbsp;extracted = []
120+
</div>
121+
<div class="code-line" id="code-5">
122+
&nbsp;&nbsp;&nbsp;&nbsp;<span class="code-keyword">while</span> len(extracted) &lt; k:
123+
</div>
124+
<div class="code-line" id="code-6">
125+
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;extracted.append(heappop(heap))
126+
</div>
127+
<div class="code-line" id="code-7">
128+
&nbsp;&nbsp;&nbsp;&nbsp;<span class="code-keyword">return</span> extracted[k - <span class="code-number">1</span>]
129+
</div>
130+
<div class="code-line" id="code-8">
131+
&nbsp;
132+
</div>
133+
<div class="code-line" id="code-9">
134+
<span class="code-comment"># sift-up: bubble up if > parent</span>
135+
</div>
136+
<div class="code-line" id="code-10">
137+
<span class="code-comment"># sift-down: sink to larger child</span>
138+
</div>
139+
<div class="code-line" id="code-11">
140+
<span class="code-comment"># Max heap: parent >= children</span>
141+
</div>
142+
</div>
143+
</div>
144+
</div>
145+
146+
<script src="../../shared/js/visualizer.js"></script>
147+
<script src="script.js"></script>
148+
</body>
149+
</html>

0 commit comments

Comments
 (0)