Data Structures Visualizer Suite

Agent #111 Β· 100 AI Agents Challenge
Array Visualization O(?)
Ready. Choose an operation.
Step Mode
OperationTimeSpace
Access by indexO(1)O(1)
Search (unsorted)O(n)O(1)
Insert at endO(1) amortizedO(1)
Insert at indexO(n)O(1)
Delete at indexO(n)O(1)
Sort (bubble)O(nΒ²)O(1)
# Python Array (list) operations
# Insert at index
def insert(arr, idx, val):
    arr.insert(idx, val)  # O(n) β€” shifts elements right

# Delete at index
def delete(arr, idx):
    return arr.pop(idx)   # O(n) β€” shifts elements left

# Linear search
def search(arr, val):
    for i, x in enumerate(arr):
        if x == val: return i
    return -1  # O(n)

# Bubble sort
def bubble_sort(arr):
    n = len(arr)
    for i in range(n):
        for j in range(n-i-1):
            if arr[j] > arr[j+1]:
                arr[j], arr[j+1] = arr[j+1], arr[j]
    # O(nΒ²) time, O(1) space
Linked List Visualization
Ready. Choose an operation.
Step Mode
OperationTimeSpace
Access/SearchO(n)O(1)
Insert at headO(1)O(1)
Insert at tail (with tail ptr)O(1)O(1)
Insert at positionO(n)O(1)
Delete at headO(1)O(1)
ReverseO(n)O(1)
class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val; self.next = next

class LinkedList:
    def __init__(self):
        self.head = None

    def append(self, val):
        node = ListNode(val)
        if not self.head: self.head = node; return
        curr = self.head
        while curr.next: curr = curr.next
        curr.next = node

    def reverse(self):
        prev, curr = None, self.head
        while curr:
            nxt = curr.next
            curr.next = prev
            prev = curr; curr = nxt
        self.head = prev

    def has_cycle(self):
        slow = fast = self.head
        while fast and fast.next:
            slow = slow.next; fast = fast.next.next
            if slow == fast: return True
        return False
Stack Visualization (LIFO)
Ready. Push some values.
OperationTimeSpace
PushO(1)O(1)
PopO(1)O(1)
Peek/TopO(1)O(1)
SearchO(n)O(1)
class Stack:
    def __init__(self): self._data = []
    def push(self, val): self._data.append(val)   # O(1)
    def pop(self):
        if not self._data: raise IndexError("Empty stack")
        return self._data.pop()   # O(1)
    def peek(self):
        if not self._data: raise IndexError("Empty stack")
        return self._data[-1]   # O(1)
    def is_empty(self): return len(self._data) == 0

# Classic: Valid Parentheses
def is_valid(s):
    stack, match = [], {')':'(', ']':'[', '}':'{'}
    for c in s:
        if c in "([{": stack.append(c)
        elif not stack or stack[-1] != match[c]: return False
        else: stack.pop()
    return not stack
Queue Visualization (FIFO)
← FRONT (Dequeue) REAR (Enqueue) β†’
Ready. Enqueue some values.
OperationTimeSpace
EnqueueO(1)O(1)
DequeueO(1) with dequeO(1)
PeekO(1)O(1)
BFS traversalO(V+E)O(V)
from collections import deque

class Queue:
    def __init__(self): self._q = deque()
    def enqueue(self, val): self._q.append(val)      # O(1)
    def dequeue(self):
        if not self._q: raise IndexError("Empty queue")
        return self._q.popleft()   # O(1)
    def peek(self): return self._q[0] if self._q else None

# BFS skeleton
def bfs(graph, start):
    visited, q = {start}, deque([start])
    while q:
        node = q.popleft()
        for neighbor in graph[node]:
            if neighbor not in visited:
                visited.add(neighbor); q.append(neighbor)
Binary Search Tree Balanced βœ“
Ready. Insert nodes to build the tree.
Step Mode
OperationAverageWorst (degenerate)
Search/Insert/DeleteO(log n)O(n)
Min/MaxO(log n)O(n)
In-order traversalO(n)O(n)
class BST:
    class Node:
        def __init__(self,v): self.v=v; self.l=self.r=None

    def __init__(self): self.root=None

    def insert(self, v):
        def _ins(n,v):
            if not n: return self.Node(v)
            if v < n.v: n.l = _ins(n.l,v)
            elif v > n.v: n.r = _ins(n.r,v)
            return n
        self.root = _ins(self.root, v)

    def inorder(self):
        result=[]
        def _io(n):
            if not n: return
            _io(n.l); result.append(n.v); _io(n.r)
        _io(self.root); return result
Heap Visualization
Array representation:
Ready. Insert values.
Step Mode
OperationTimeSpace
InsertO(log n)O(1)
Extract min/maxO(log n)O(1)
Peek min/maxO(1)O(1)
Build from arrayO(n)O(1)
HeapsortO(n log n)O(1)
import heapq

# Min-heap (Python default)
h = []
heapq.heappush(h, 5)   # O(log n)
heapq.heappush(h, 2)
heapq.heappush(h, 8)
minimum = heapq.heappop(h)  # O(log n) β†’ returns 2

# Max-heap: negate values
maxh = []
heapq.heappush(maxh, -5)
heapq.heappush(maxh, -2)
maximum = -heapq.heappop(maxh)  # β†’ 5

# Build heap from list O(n)
nums = [3,1,4,1,5,9,2,6]
heapq.heapify(nums)

# K largest elements
def k_largest(nums, k):
    return heapq.nlargest(k, nums)  # O(n log k)
Hash Table Visualization (Chaining)
Load Factor 0.00
Ready. Insert key-value pairs.
OperationAverageWorst
Insert/Get/DeleteO(1)O(n) β€” all keys hash to same bucket
SpaceO(n)O(n)
# Python dict is a hash map
ht = {}
ht["name"] = "Alice"   # Insert O(1)
val = ht.get("name")  # Get O(1)
del ht["name"]        # Delete O(1)

# Two Sum β€” classic hash map problem
def two_sum(nums, target):
    seen = {}
    for i, n in enumerate(nums):
        complement = target - n
        if complement in seen:
            return [seen[complement], i]
        seen[n] = i
    return []   # O(n) time, O(n) space

# Collision handling (chaining concept)
def hash_fn(key, size):
    return sum(ord(c) for c in str(key)) % size
Trie Visualization
Ready. Insert words to build the trie.
Step Mode
OperationTimeSpace
Insert word (len L)O(L)O(L)
Search wordO(L)O(1)
Prefix searchO(P)O(1)
Space totalβ€”O(total chars)
class TrieNode:
    def __init__(self):
        self.children = {}  # char β†’ TrieNode
        self.is_end = False

class Trie:
    def __init__(self): self.root = TrieNode()

    def insert(self, word):  # O(L)
        node = self.root
        for ch in word:
            node = node.children.setdefault(ch, TrieNode())
        node.is_end = True

    def search(self, word):  # O(L)
        node = self.root
        for ch in word:
            if ch not in node.children: return False
            node = node.children[ch]
        return node.is_end

    def starts_with(self, prefix):  # O(P)
        node = self.root
        for ch in prefix:
            if ch not in node.children: return False
            node = node.children[ch]
        return True