DSA Material

Abstract Data Types (ADTs)

Share to

This chapter follows the core ideas from Chapter 1 (Abstract Data Types) in the Necaise book: define behavior first, then implement it.

ADT contract diagram

What an ADT gives you

An ADT is a contract:

This separation is the main reason ADTs scale in larger projects.

Core contract pieces

Every operation should be specified with:

Example for pop() on a stack:

Preconditions and assertions

When learning data structures, assertions are useful for making contracts explicit.

class Stack:
    def __init__(self):
        self._items = []

    def pop(self):
        assert len(self._items) > 0, "precondition failed: stack must be non-empty"
        return self._items.pop()

In production systems, you usually raise specific exceptions for invalid operations.

Multiple implementations, same ADT

A queue ADT can have different implementations:

As long as each implementation preserves queue semantics (FIFO), user-facing code stays the same.

def process_jobs(queue):
    while not queue.is_empty():
        job = queue.dequeue()
        handle(job)

process_jobs should not care about internal storage layout.

Why this matters before coding structures

If you define the ADT contract first, then implementation work in later chapters is easier:

This is the foundation for the rest of the data structures section.