When working with arrays, one important thing to know is “what memory layout to use for storing the data”, and “how to access data in the most efficient manner”.
Since computer memory is inherently linear and a one-dimensional structure, mapping multi-dimensional data on it can be done in several ways. In this tutorial, you will learn contiguous and non-contiguous array topics in detail in this article.
Contiguous and Non-Contiguous Memory Allocation
Memory is a collection of bytes, and memory allocation is a method by which computer programs are allotted space. When it comes to memory allocation, it can be divided into two categories: contiguous memory allocation and non-contiguous memory allocation.
In contiguous memory allocation, a single part of the memory section is allowed to accomplish the further process. On the other hand, in non-contiguous memory allocation, the method is assigned to different memory sections at multiple memory locations in the memory.

In Contiguous memory allocation, all the free memory space can stay in the same place concurrently. In non-contiguous memory allocation, the operation is allowed to different memory sections at multiple memory positions in the memory.
How is Array Element Stored in Memory?
In many programming languages, array elements occupy contiguous memory. If you’re working directly with physical memory, then elements of the array actually occupy contiguous locations in physical memory.
If you’re in a virtual memory environment, then the array actually might be stored across non-contiguous physical pages of memory, but the memory is contiguous. If you look at the virtual addresses of array elements, you’ll see that the elements are stored contiguously, even if the physical memory backup up the pages you’re looking at are not physically contiguous.
NumPy arrays are stored in a contiguous block of memory. This means that all elements of the array are stored in one continuous line in the memory, which allows for quick access and manipulation of the data. The size of this memory block is fixed when the array is created and cannot be changed afterward.
When working with 2D arrays (matrices), the row-major layout of a matrix puts the first row in contiguous memory, then the second row right after it, then the third, and so on.

In row-major layout, the first row of the matrix is placed in contiguous memory, then the second, and so on.
Let’s see a “real” example of how multi-dimensional arrays are stored in memory. For this purpose, the Numpy library of Python is a great tool since it supports both layout kinds and is easy to play with from an interactive shell.
array = np.array([[1, 2, 3], [11, 12, 13], [10, 20, 40]], dtype='uint8', order='C')

The numpy.array constructor can be used to create multi-dimensional arrays. One of the parameters it accepts is order, which is either “C” for C-style layout (row-major) or “F” for Fortran-style layout (column-major). “C” is the default.