0. Data Structure Definitions & ADT
Formal definitions, mathematical model (Domain, Operations, Axioms), classification (Primitive vs Non-Primitive, Linear vs Non-Linear, Static vs Dynamic), Abstract Data Types (ADT), and core operations across C, C++, and Python
NPTEL / GATE CS / UGC NET Foundation Module Exam Weightage: 1–2 Questions directly testing ADT vs concrete data structures, classification taxonomy (Linear vs Non-Linear, Static vs Dynamic, Homogeneous vs Heterogeneous), and the asymptotic bounds of fundamental operations.
1. Prerequisites & What You Should Know#
Before studying data structures formally, you should be comfortable with:
- Variables & Data Types: Understanding basic primitives like
int,float,char, and how compilers store them. - Memory Addresses & Pointers: Conceptualizing that RAM is a sequential collection of numbered byte cells.
- Functions & Interfaces: Knowing the difference between calling a function and how its inner logic executes.
- Mathematical Sets & Relations: Basic set notation () and ordering relations.
2. What is a Data Structure? (Conceptual Foundation)#
2.1 Data vs. Information vs. Data Structure#
To understand data structures, we must first distinguish three fundamental layers:
- Data: Raw, unorganized facts or values without context (e.g.,
42,"Alice",3.14). On its own, raw data carries no semantic meaning. - Information: Data processed, contextualized, and organized so that it becomes meaningful (e.g., "Alice scored 42 points in exam round 3").
- Data Structure: A specialized mathematical and algorithmic format for organizing, storing, managing, and relating data so that operations (such as retrieval, insertion, modification, and deletion) can be performed efficiently.
+————————————+ Organization & Relationships +——————————————————————+
| Raw Data | —————————————————————————————————————> | Data Structure |
| (42, "Bob")| (Arrays, Pointers, Hierarchy) | (Indexed, Linked, etc)|
+————————————+ +——————————————————————+
│
│ Optimized Algorithms
▼
+——————————————————————+
| Useful Information |
| Fast O(1) / O(log n) |
+——————————————————————+
2.2 The Real-World Warehouse Analogy#
Imagine a massive shipping warehouse storing 500,000 packages:
- Unstructured Pile: Dumping all 500,000 packages in an unsorted pile on the warehouse floor. Finding any single item requires inspecting packages one by one ( time).
- Indexed Grid (Array): Numbered aisles and shelves where each box has an exact fixed coordinate. You reach box #314 instantly ( time).
- Dispatch Queue (FIFO): Packages arranged on a conveyor belt so that the earliest arrived package ships first ( enqueue/dequeue).
- Hierarchical Shelves (Tree): Sorting items by Country State City Postal Code. Narrowing down the location takes logarithmic steps ( time).
Axiom of Computer Science: Algorithm + Data Structure = Program (Niklaus Wirth, 1976) An algorithm cannot exist in isolation; it operates exclusively upon data structured in memory. Choosing the wrong data structure degrades the most brilliant algorithm.
3. Formal Mathematical Definition of Data Structures#
In formal computer science and university curricula (NPTEL, GATE, UGC NET), a data structure is not merely code; it is defined mathematically.
3.1 The 4-Tuple Model: #
Formally, a data structure is characterized as a 4-tuple:
Where:
- (Domain): The set of data objects or elements being structured (e.g., integers , strings ).
- (Functions / Operations): The set of valid mappings and functions permitted on the domain (e.g., , ).
- (Axioms / Semantic Rules): The formal mathematical equations and identities that must always hold true (e.g., in a Stack: ).
- (Preconditions): The prerequisite constraints for operations to be valid (e.g., requires ; violation produces Stack Underflow).
3.2 The Relational Model: #
Alternative mathematical formulation: A data structure is an ordered pair:
Where:
- is a finite set of data items: .
- is a set of relationships over : , where each .
- In a Linear Structure: is a strict total order relation where every element (except first and last) has a unique immediate predecessor and unique immediate successor.
- In a Hierarchical Structure (Tree): is an asymmetric acyclic parent-child relation with a unique root having no predecessor.
- In a Graph: is an arbitrary binary adjacency relation with no structural constraints.
4. Comprehensive Classification of Data Structures#
Data structures are categorized across several orthogonal taxonomic axes:
Data Structures
/ \
Primitive Non-Primitive
/ | \ / \
int float char Linear Non-Linear
bool pointer / \ / \
Static Dynamic Trees Graphs
| / | \ | |
Array LL Stack Queue BST, AVL Directed,
Heap, Trie Undirected
4.1 Classification Dimension 1: Primitive vs. Non-Primitive#
| Feature | Primitive Data Structures | Non-Primitive Data Structures |
|---|---|---|
| Definition | Basic types directly supported by CPU hardware and machine instructions | Complex structures constructed by grouping primitive and non-primitive types |
| Atomic Nature | Atomic; cannot be decomposed into smaller constituent parts | Composite; can be broken down into individual elements |
| Hardware Support | Handled directly by machine registers and arithmetic logic units (ALU) | Managed by software routines, runtime memory allocators, and compilers |
| Examples | int, float, char, double, pointer | Arrays, Linked Lists, Stacks, Trees, Hash Tables |
| Memory Size | Fixed by hardware architecture (e.g., 4 bytes for 32-bit integer) | Variable or user-defined, scaling with element count |
4.2 Classification Dimension 2: Linear vs. Non-Linear#
Linear: [ Node 1 ] <——> [ Node 2 ] <——> [ Node 3 ] <——> [ Node 4 ]
(Single predecessor, single successor — sequential traversal)
Non-Linear: [ Root / Node A ]
/ \
[ Child B ] [ Child C ]
/ \ \
[ Leaf D ] [ Leaf E ] [ Leaf F ]
(Hierarchical parent-child or arbitrary graph network)
| Feature | Linear Data Structures | Non-Linear Data Structures |
|---|---|---|
| Arrangement | Elements arranged in a strict sequential order | Elements arranged in hierarchical, multi-level, or interconnected graph patterns |
| Relationships | 1-to-1 relationship between adjacent elements (predecessor & successor) | 1-to-Many (Trees) or Many-to-Many (Graphs) relationships |
| Traversal | Single run: can traverse all elements in a single sequential pass | Multiple runs: requires specialized algorithms (DFS, BFS, Pre/In/Postorder) |
| Levels | Single level of data storage | Multiple levels (root, interior, leaves) or arbitrary cycles |
| Examples | Arrays, Linked Lists, Stacks, Queues | Binary Trees, BSTs, AVL Trees, Heaps, Graphs, Tries |
| Complexity | Traversal is straightforward | Search, insertion, and traversal require non-trivial traversal logic |
4.3 Classification Dimension 3: Static vs. Dynamic#
| Characteristic | Static Data Structures | Dynamic Data Structures |
|---|---|---|
| Memory Allocation | Allocated at compile-time (or fixed initial runtime size) | Allocated dynamically at runtime from the system Heap |
| Size Flexibility | Fixed maximum capacity; cannot grow or shrink during execution | Elastic; expands and contracts automatically as items are inserted/removed |
| Memory Region | Typically stored on the program Stack (or fixed static memory) | Stored on the program Heap via malloc, new, or runtime allocators |
| Waste / Overflow Risk | High risk of unused pre-allocated space OR overflow if capacity exceeded | Optimal memory usage; memory freed immediately upon deletion |
| Access Speed | Extremely fast; direct memory offset computation | Slight pointer chasing overhead, cache misses |
| Examples | Fixed-size C Arrays (int arr[100]), fixed static buffers | Singly/Doubly Linked Lists, Dynamic Arrays (std::vector, Python list) |
4.4 Classification Dimension 4: Homogeneous vs. Heterogeneous#
- Homogeneous Data Structures: All stored elements must be of the identical data type (e.g., standard C arrays where every element occupies exactly
sizeof(T)bytes). - Heterogeneous Data Structures: Elements can be of varying, dissimilar data types (e.g., C
struct, Python tuples/lists, JSON objects, database tuples).
4.5 Classification Dimension 5: Persistent vs. Ephemeral#
- Ephemeral Data Structures: Any modification (insert, delete) destroys the prior version; only the latest mutated state is preserved (e.g., standard arrays and pointers mutated in-place).
- Persistent Data Structures: Preserves historic versions when updated:
- Partially Persistent: All versions can be read, but only the newest version can be modified.
- Fully Persistent: Any version can be both inspected and modified, creating a version tree (used in Git, functional programming languages, and undo history).
5. Abstract Data Types (ADT) vs. Concrete Data Structures#
A paramount question in GATE CS and university oral exams is: "What is the precise difference between an ADT and a Data Structure?"
5.1 The Interface Contract: WHAT vs. HOW#
+—————————————————————————————————————————————————————————+
| ABSTRACT DATA TYPE (ADT) |
| Logical Specification |
| |
| "WHAT operations can be performed?" |
| - Push(x): Add element to top |
| - Pop(): Remove element from top |
| - Peek(): Inspect top element |
| - IsEmpty(): Check if empty |
+—————————————————————————————————————————————————————————+
│
Implemented via Concrete DS
▼
+—————————————————————————————+———————————————————————————+
| Array-Based Implementation | Linked List Implementation|
| | |
| - int data[MAX]; | - struct Node { |
| - int top = -1; | int val; |
| | Node* next; |
| Fast index lookups | }; |
| Fixed size bound | Truly dynamic heap growth |
+—————————————————————————————+———————————————————————————+
-
Abstract Data Type (ADT):
- A mathematical model specifying WHAT operations can be performed and WHAT constraints apply, without defining how elements are placed in physical memory.
- It defines the public interface, behaviors, and semantic contracts.
- The user of an ADT does not know (and does not care) whether an array, a linked list, or memory mapped files are used internally.
-
Concrete Data Structure:
- The physical, concrete implementation in programming code detailing HOW data is represented in RAM and HOW algorithms manipulate those bits.
5.2 Classic ADT vs. Concrete DS Mapping#
| Abstract Data Type (ADT) | Conceptual Behavior | Possible Concrete Implementations |
|---|---|---|
| List ADT | Ordered sequence with positional access, insertions, and deletions | Contiguous Array, Singly Linked List, Doubly Linked List, Unrolled Linked List |
| Stack ADT | LIFO (Last-In, First-Out) discipline | Array with top index, Singly Linked List with head insertion |
| Queue ADT | FIFO (First-In, First-Out) discipline | Circular Array, Doubly Linked List, Two Stacks |
| Priority Queue ADT | Extract minimum or maximum key with highest priority | Binary Heap, Fibonacci Heap, Sorted Linked List, BST |
| Map / Dictionary ADT | Key-Value associative mapping with unique keys | Hash Table with Chaining, Red-Black Tree, Open Addressing Array |
| Set ADT | Collection of distinct, unordered elements | Hash Set, Boolean Bit-Vector, Balanced Binary Search Tree |
| Graph ADT | Set of vertices and connecting edges | Adjacency Matrix (), Adjacency List (), Edge List |
6. Multi-Language Implementation of an ADT#
To solidify the ADT concept, below is a complete implementation of a Stack ADT showing strict separation of interface and implementation across C, C++, and Python.
/**
* In ANSI C, an ADT is implemented via:
* 1. An OPAQUE POINTER in the header file (hiding struct internals).
* 2. Strict function signatures defining the ADT operations.
* 3. Dynamic allocation ensuring true memory encapsulation.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
// --- ADT Interface (Header Declaration) ---
typedef struct StackADT* Stack;
Stack stack_create(size_t capacity);
void stack_destroy(Stack s);
bool stack_push(Stack s, int value);
bool stack_pop(Stack s, int* popped_val);
bool stack_peek(const Stack s, int* peek_val);
bool stack_is_empty(const Stack s);
bool stack_is_full(const Stack s);
// --- Concrete Implementation (Source File) ---
struct StackADT {
int* data;
size_t capacity;
int top; // Index of top element, -1 when empty
};
Stack stack_create(size_t capacity) {
if (capacity == 0) return NULL;
Stack s = (Stack)malloc(sizeof(struct StackADT));
if (!s) return NULL;
s->data = (int*)malloc(capacity * sizeof(int));
if (!s->data) {
free(s);
return NULL;
}
s->capacity = capacity;
s->top = -1;
return s;
}
void stack_destroy(Stack s) {
if (s) {
free(s->data);
free(s);
}
}
bool stack_is_empty(const Stack s) {
return s == NULL || s->top == -1;
}
bool stack_is_full(const Stack s) {
return s != NULL && (size_t)(s->top + 1) == s->capacity;
}
bool stack_push(Stack s, int value) {
if (stack_is_full(s)) return false; // Overflow guard
s->data[++(s->top)] = value;
return true;
}
bool stack_pop(Stack s, int* popped_val) {
if (stack_is_empty(s)) return false; // Underflow guard
*popped_val = s->data[(s->top)--];
return true;
}
bool stack_peek(const Stack s, int* peek_val) {
if (stack_is_empty(s)) return false;
*peek_val = s->data[s->top];
return true;
}7. Fundamental Operations on Data Structures#
Regardless of structure type, data structures support six foundational primitive operations:
+—————————————————————————————————————————————————————————+
| Core Operations on Data |
+—————————————————+———————————————————————————————————————+
| 1. Traversing | Visit every node/element exactly once |
| 2. Searching | Locate element matching target key |
| 3. Insertion | Add new item at target position |
| 4. Deletion | Remove specified element & rewire |
| 5. Sorting | Arrange items in ascending/descending |
| 6. Merging | Combine two collections into single DS|
+—————————————————+———————————————————————————————————————+
- Traversing: Systematically processing or inspecting each element in the data structure exactly once without omissions or infinite looping.
- Searching: Locating the memory address or logical index of a data element satisfying a search predicate (Linear Search , Binary Search , Hash Lookup ).
- Insertion: Adding a new element into the collection. In arrays this requires shifting items right (); in linked lists it requires pointer rewiring ( at known pointer).
- Deletion: Locating and removing an existing item, reclaiming memory, and maintaining structural invariants.
- Sorting: Arranging elements in a defined logical ordering (Quicksort, Mergesort, Heapsort).
- Merging: Combining two distinct collections into a single unified structure (e.g., merging two sorted linked lists in ).
8. Data Structure Selection Decision Framework#
How do real-world system architects and competitive programmers select the ideal data structure? Follow this mental decision tree:
What is your primary operational need?
│
┌──────────────────┬─────────────────┼──────────────────┬──────────────────┐
▼ ▼ ▼ ▼ ▼
Access by Index Frequent Insert/ LIFO Ordering FIFO Ordering Key-Value Lookup
at O(1) Speed Delete at Ends (Undo/Recursion) (Buffering/Jobs) at O(1) Average
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
Array / Vector Linked List Stack Queue Hash Table / Map
Comparative Performance Matrix#
| Data Structure | Random Access | Search (Unsorted) | Search (Sorted) | Insertion (Head) | Insertion (Tail) | Deletion (Head) | Space Overhead |
|---|---|---|---|---|---|---|---|
| Array (Static) | (if room) | None (contiguous) | |||||
| Dynamic Array | amortized | Low (capacity buffer) | |||||
| Singly Linked List | with tail | 1 pointer per element | |||||
| Doubly Linked List | with tail | 2 pointers per element | |||||
| Stack | N/A | N/A | Minimal | ||||
| Queue | N/A | N/A | Minimal | ||||
| Binary Search Tree | 2 child pointers | ||||||
| AVL / Red-Black Tree | 2 pointers + balance bits | ||||||
| Hash Table | N/A | avg | N/A | avg | avg | avg | Table buckets + chains |
9. GATE & UGC NET Exam Traps & Conceptual Insights#
Trap 1: Confusing an ADT with a Concrete Data Structure
- Wrong: "Stack is a linear data structure stored with pointers."
- Right: Stack is an Abstract Data Type (ADT) defining LIFO semantics. It can be implemented physically using an Array, a Linked List, or even two Queues!
Trap 2: Sequential vs. Linear Distinction
- All linear data structures have sequential logical order (item precedes item ).
- However, memory allocation can be sequential/contiguous (Arrays) or non-contiguous/scattered across the heap (Linked Lists).
Trap 3: Primitive vs. Non-Primitive in Modern Languages
In C, int is primitive and int[] is non-primitive. In Python, strictly speaking, everything is an object (an instance of int is a heap-allocated C struct PyObject), but conceptually Python distinguishes atomic scalars (int, float) from collection data structures (list, dict, set).
Practice Quiz
Test your understanding with step-by-step solutions
Practice Quiz
10 questions · 90s per question
Each question has a 90-second time limit. Unanswered questions will be auto-submitted when time runs out.