Data Structures and Algorithms (DSA)  

What is Array in Data Structures with Examples

Introduction

In computer science and software development, a data structure is a way to organize and store data so that we can perform operations on it efficiently (like searching, inserting, deleting, etc.). One of the simplest and most important data structures is the array.

An array is a collection of elements (all of the same kind, e.g. all integers or all strings), stored in contiguous (next-to-each-other) memory locations, accessible by their index (position). Because of this structure, arrays let us access any element quickly when we know its index.

What Is an Array?

Think of an array as a row of boxes, each box labeled with a number (or index). In each box, you can store one item (say, an integer, or a string). Because the boxes are lined up consecutively, if you know the starting box number and the index, you can jump directly to the box you want. That is what gives the array its power: direct access.

Formally:

  • An array stores elements of the same data type (homogeneous).

  • Elements are stored in contiguous memory locations (so they’re next to each other in memory).

  • Each element is identified by an index (often starting from 0).

  • Because the size is fixed, you can’t easily grow the array (unless you allocate a new one).

Why Contiguous Memory?

Because the elements are stored in adjacent memory addresses, we can compute the address of an element if we know:

  • The array’s base (starting) address

  • The size (in bytes) of each element

  • The index

Thus, we can do constant time access (O(1)) to any element via its index.

Key Properties of Arrays (with Explanations)

Here are the important properties of arrays, described in simple words:

PropertyDescriptionWhy It Matters
Fixed SizeWhen you create an array, you decide how many elements it can hold, and that doesn’t change (unless you recreate a new array).You can’t dynamically increase the size in place.
Homogeneous ElementsAll elements in an array are of the same type (e.g. all integers, all strings).This uniformity makes memory allocation and indexing simpler.
Contiguous MemoryThe elements are stored one after another in memory.Enables fast indexing and good cache performance.
Index-based AccessYou use an integer index (often starting from 0) to get any element.Direct (random) access to any element is fast (constant time).
Sequential StructureArray is a linear or one-dimensional structure by default.Helps in walking through the array in order.

Types of Arrays

Arrays can come in different forms depending on how many dimensions they have.

  1. One-Dimensional Array (1D array)
    This is the simple, straight line of boxes case we described above.
    Example in Python:

    arr = [10, 20, 30, 40, 50]
    
  2. Multi-Dimensional Array (2D, 3D, …)
    These are arrays of arrays. For example, a 2D array is like a table or grid (rows and columns).
    Example in Python (2D list):

    matrix = [
        [1, 2, 3],
        [4, 5, 6],
        [7, 8, 9]
    ]
    
  3. Dynamic Arrays / Resizable Arrays
    In some languages (or libraries), arrays can “grow” by internally creating a new larger array and copying the elements. In Python, the built-in list behaves like a dynamic array.
    Even though Python’s list is more flexible, under the hood, it uses similar contiguous memory logic to some extent.

Common Operations on Arrays

Here are the typical operations you perform on arrays, and how they behave (with examples). We also discuss their time complexity (how the runtime changes when the array has more elements, n).

1. Access (Read) an Element

You want to get the element at a particular index.

Example in Python:

arr = [10, 20, 30, 40, 50]
print(arr[2])   # prints 30

Time Complexity: O(1), constant time, because we directly compute the location based on index.

2. Update (Write) an Element

You want to change the value of an element at a certain index.

Example in Python:

arr = [10, 20, 30, 40, 50]
arr[3] = 100print(arr)  # now: [10, 20, 30, 100, 50]

Time Complexity: O(1)

3. Traversal (Iterating Through All Elements)

You go through each element one by one (for example, to print or sum all).

Example:

for elem in arr:
    print(elem)

or using indices:

for i in range(len(arr)):
    print(arr[i])

Time Complexity: O(n) — you visit every element once.

4. Searching (Finding an Element)

You want to check whether a value exists in the array, and maybe get its index.

  • Linear Search (for unsorted array): check each element one by one

    • Time Complexity: O(n)

    def linear_search(arr, target):
        for i in range(len(arr)):
            if arr[i] == target:
                return i
        return -1
  • Binary Search (for sorted array): repeatedly divide the search interval

    • Time Complexity: O(log n)

    • But you can use it only if the array is sorted already.

    Example:

    def binary_search(arr, target):
        low, high = 0, len(arr) - 1
        while low <= high:
            mid = (low + high) // 2
            if arr[mid] == target:
                return mid
            elif arr[mid] < target:
                low = mid + 1
            else:
                high = mid - 1
        return -1

5. Insertion (Add an Element)

You insert a new element at a given position (or at end).

  • If you insert at the end (and there is free space), it can be done in O(1).

  • If you insert at the middle or beginning, you have to shift all elements to make room -> O(n).

In Python’s list, you might do:

arr.insert(2, 25)   # insert 25 at index 2

But internally, elements from index 2 onward will shift right by one.

6. Deletion (Remove an Element)

You remove an element at a given index (or first occurrence of a value).

  • Deleting from the end is simple, O(1).

  • Deleting from the middle or beginning requires shifting elements to fill the gap -> O(n).

In Python:

del arr[2]          # delete element at index 2# or
arr.pop(2)          # remove and return element at index 2

Python Example: Putting It All Together

Here is a small Python script that shows creating an array, doing some operations, and printing results:

def main():
    # 1. Create / initialize array (Python list)
    arr = [5, 10, 15, 20]
    print("Initial array:", arr)

    # 2. Access element
    print("Element at index 2:", arr[2])  # 15

    # 3. Update element
    arr[1] = 12
    print("After update:", arr)  # [5, 12, 15, 20]

    # 4. Insert new element
    arr.insert(2, 13)
    print("After inserting 13 at index 2:", arr)  # [5,12,13,15,20]

    # 5. Delete element
    arr.pop(3)  # remove element at index 3
    print("After deletion:", arr)

    # 6. Search
    target = 20
    if target in arr:
        idx = arr.index(target)
        print(f"{target} found at index {idx}")
    else:
        print(f"{target} not found in array")

    # 7. Traverse / print all
    print("Traverse:")
    for x in arr:
        print(x, end=" ")
    print()

if __name__ == "__main__":
    main()

Output will be something like:

Initial array: [5, 10, 15, 20]
Element at index 2: 15After update: [5, 12, 15, 20]
After inserting 13 at index 2: [5, 12, 13, 15, 20]
After deletion: [5, 12, 13, 20]
20 found at index 3Traverse:5 12 13 20 

Note: Although Python’s list behaves dynamically, conceptually it mirrors many array operations.

Time Complexity Table (Big O Notation)

Here's a quick reference:

OperationTime Complexity
Access / ReadO(1)
Update / WriteO(1)
TraversalO(n)
Search (linear)O(n)
Search (binary, sorted)O(log n)
Insertion (end)O(1) amortized (if space)
Insertion (middle / beginning)O(n)
Deletion (end)O(1)
Deletion (middle / beginning)O(n)

Use Cases / Real-Life Analogies

  • Books on a shelf: Think of books lined up in order. You can pick the 3rd book directly (if you count). But inserting a new book in between means shifting those on the right a little.

  • Seats in a row: You have seats labeled 0,1,2,... and people sitting in them. You can ask: who is in seat 5? But to insert someone in seat 2, you may shift others.

  • Monthly temperature records: You may store temperatures for 12 months in an array of size 12.

  • Tables or matrices (2D arrays): For a spreadsheet or grid, you use a 2D array (rows and columns).

Arrays also serve as the foundation for more advanced data structures:

  • A stack or queue can be implemented using arrays

  • A matrix (in maths) is a 2D array

  • Some graph adjacency matrices use arrays

  • Many algorithms (sorting, searching) assume arrays

Limitations of Arrays (When Not to Use Them)

While arrays are simple and efficient for many tasks, they have drawbacks too:

  1. Fixed Size: You must know (or guess) the maximum size ahead of time. If you exceed it, you have to allocate a new array and copy data.

  2. Costly Insert/Delete in Middle: Inserting or deleting in middle requires shifting many elements → O(n) time.

  3. Wasted Memory: If you allocate more space than needed, that extra is unused (waste). If you allocate too little, you may run out.

  4. Not Flexible for Non-Contiguous Storage: Sometimes data needs to grow in irregular ways; linked lists or dynamic structures might suit better.

  5. Costly Resizing: In “dynamic arrays” (like Python lists or Java’s ArrayList), resizing involves creating a new bigger array and copying, which is expensive occasionally.

Array vs Other Linear Data Structures

  • Array vs Linked List

    • Array allows O(1) access, but insertion/deletion in the middle is costly.

    • Linked list allows easy insertion/deletion (if you have pointer) but access is O(n) (you must walk nodes).

  • Array vs Dynamic Array / List Structure

    • Dynamic arrays try to combine the best: they allocate extra space so that small insertions at end are O(1) amortized. But still, insertion in middle costs.

When choosing, you consider:

  • How often you need random access

  • How often you insert/delete elements

  • Memory constraints

Arrays in Memory (Under the Hood)

It helps to understand what “contiguous memory” means at a low level:

  • Suppose each integer occupies 4 bytes.

  • If the base address (start) of the array is 1000, then:

    • Element at index 0 → address 1000

    • Element at index 1 → address 1004

    • Element at index 2 → address 1008

    • And so on...

Thus, to find the address of element at index i, you compute:

address = base_address + i * (size of each element)

That’s why access is constant time: direct computation.

Because of this contiguous layout, arrays also enjoy cache locality (processors can fetch nearby data faster).

Summary

An array is a fundamental data structure that stores a fixed-size sequence of homogeneous elements in contiguous memory, enabling constant-time O(1) access by index. Common operations on arrays include access, update, traversal, search, insertion, and deletion, each with its own time complexity. Arrays are simple and efficient for many tasks, forming the foundation for numerous advanced data structures. However, they become less efficient when frequent insertions or deletions in the middle are required, or when the size needs to be dynamic. In Python, the built-in list often serves as an “array-like” structure that supports dynamic resizing, though it conceptually follows many of the same principles. A strong understanding of arrays is essential, as many algorithms and higher-level structures are built upon or extend this core concept.