7 structures · animated · code included

The Data Structure
Playground

Push, pop, insert, traverse — watch it happen. A visual, animated home for Stacks, Queues, Linked Lists, Trees, Graphs, Heaps and Tries, with runnable code and the theory behind each move.

array
7 structures
30+ animated operations
2 languages per snippet
0 build steps
explore

Pick a structure

Each one opens into its own workbench: a live visualization, hands-on operations, complexity notes and code in C++ and Python.

why this exists

Built to make DSA click

Reading pseudocode rarely builds intuition on its own. Watching a heap bubble an element into place, or a trie branch out character by character, does. This playground pairs both.

See it happen

Every push, rotation and traversal animates in real time so the mechanics — not just the result — are visible.

Read the code

Each operation ships with matching C++ and Python implementations, written the way you'd actually submit them.

Know the complexity

Big-O for every operation, key formulas, and the trade-offs that decide which structure to reach for.

foundations

Before the structures — the basics

Arrays, strings, maps and sorting are the building blocks everything else in this playground is made of. Start here if you want the theory, not just the animation.

Time complexity, visualized

How each Big-O class grows as input size n increases. O(n²) escapes the chart fast — that's the whole point.

Memory overhead per element

Static arrays store mostly raw data. Linked structures spend real space on pointers and metadata.

Arrays & Dynamic Arrays (Vectors)

An array is a fixed-size, contiguous block of memory — every element sits right next to the last, so jumping to index i is a single pointer calculation: O(1).

A vector (C++ vector, Python list, JS Array) is a dynamic array. It over-allocates capacity, and when it runs out, it allocates a new block — usually double the size — copies every element over, and frees the old block.

That resize is an expensive O(n) operation, but it happens rarely enough (capacity doubling means it happens O(log n) times over n insertions) that the amortized cost of push_back stays O(1).

  Inserting or deleting at the front of an array/vector is still O(n) — every later element has to shift.

Vector resizer — try it

Size: 0  Capacity: 4
Capacity reached — allocating a new O(n) block…

Strings

A string is, under the hood, an array of characters — so most array intuition carries over directly: indexing is O(1), and appending to the end is amortized O(1) if the string is backed by a growable buffer.

In C++, std::string is mutable and growable much like a vector. In Python and Java, strings are immutable — every "modification" (concatenation, replace, slicing) actually builds a brand-new string, which is why repeatedly concatenating in a loop is a classic O(n²) trap.

OperationComplexityNote
Access char at indexO(1)Direct memory offset
ConcatenationO(n)O(n²) if repeated in a loop without a buffer
Substring / sliceO(k)k = length of the slice
Search (naive)O(n·m)Use KMP / Z-algorithm for O(n+m)
Compare equalityO(n)Must check char by char in the worst case

Hash Maps (Dictionaries)

A map stores key → value pairs. It runs the key through a hash function that turns it into an array index, so lookup skips straight to (roughly) the right bucket instead of scanning everything.

Collisions — two keys hashing to the same bucket — are handled by chaining (a small list per bucket) or open addressing (probe to the next free slot). A good hash function keeps buckets short, which is what keeps operations close to O(1) on average.

StructureAccessSearchInsert / Delete
ArrayO(1)O(n)O(n)
Hash Map—O(1) avgO(1) avg
Hash Map (worst case)—O(n)O(n)
Balanced BST Map—O(log n)O(log n)

Worst case degrades to O(n) when many keys collide into the same bucket — rare with a decent hash function, but the reason languages randomize hash seeds for security.

Sorting Algorithms

Every sort trades off between time, space, and stability (whether equal elements keep their original relative order). Comparison-based sorts can't beat O(n log n) in the average case — that bound comes straight from the fact that there are n! possible orderings and each comparison only rules out half of them.

AlgorithmBestAverageWorstSpaceStable?
Bubble SortO(n)O(n²)O(n²)O(1)Yes
Selection SortO(n²)O(n²)O(n²)O(1)No
Insertion SortO(n)O(n²)O(n²)O(1)Yes
Merge SortO(n log n)O(n log n)O(n log n)O(n)Yes
Quick SortO(n log n)O(n log n)O(n²)O(log n)No
Heap SortO(n log n)O(n log n)O(n log n)O(1)No

Bubble / Selection / Insertion

Simple O(n²) sorts. Insertion sort is genuinely fast on nearly-sorted data — many languages use it for small sub-arrays inside a bigger sort.

in-placesimple

Merge Sort

Divide, sort each half recursively, merge. Guaranteed O(n log n) — the trade-off is an extra O(n) buffer for merging.

divide & conquerstable

Quick Sort

Pick a pivot, partition around it, recurse. Fast in practice and in-place, but a bad pivot choice degrades to O(n²).

in-placecache-friendly

Heap Sort

Build a max-heap, repeatedly extract the max. Guaranteed O(n log n) and O(1) extra space — the same heap from the Heap module powers it.

in-placeno worst-case blowup
quick reference

The cheatsheet

Time complexity for every structure, side by side. Click any card to jump into its playground.

about

Hi, I'm Panth Shah

I'm an Electronics & Communication Engineering student at Nirma University, splitting my time between competitive programming and building things for the web. This playground started as a way to actually see the data structures I was drilling on Codeforces — so I built the visual version I wished existed.


Every structure here — stack, queue, linked list, tree, graph, heap, trie — runs on a small shared animation engine, with real operations, real code, and real complexity notes underneath the visuals.


If you spot a bug or want to suggest a structure to add, my inbox and GitHub issues are both open.