Data Structures in Python — The Dynamic Arrays Disguised as Lists
By: Yash Prakash
Tags: Algorithms, Arrays, Thiscodecsbasics, Python, Data Structures

An array is a data structure which arranges items sequentially. In most programming languages, it’s done in typically a more or less similar manner but in Python, it’s done a bit differently.

But before we dive into the specifics associated with Python, we must first have a quick look at what a regular array is.

General definition and characteristics of an Array

Each position in the array has an index, starting at 0, with elements stored sequentially corresponding to those indexes.

runtime of array operations!

Arrays typically come with fast appends and lookups — adding a new element at the end of the array as well as retrieving an element from a given index in the array both take O(1) time only.

On the other hand, the shortcomings of arrays include — they’re of fixed size. The number of elements we’re going to have in our array always needs to be specified beforehand. (But NOT in a dynamic array, which we’ll get to later…:))

Also, we have O(n) worst time for any insertion or deletion operation in the array. You might question why that is —if we just insert an element without moving all the others or just delete an element without moving over and rearranging all the others, won’t the runtime be lesser?

The answer is — this theory actually violates the very idea arrays operate on — keeping elements sequentially arranged in memory. If gaps are left to facilitate quicker insertion or deletions, we will no longer be able to know exactly where each element in the array will be.

Quick note: If you’re wondering about what worst time is or want to get a basic conceptual idea of time complexity, please do consider reading my previous article on Big O notations! ❤

Lists in Python — the difference!

Now that we’ve seen what arrays look like, we can move on to defining and understanding them in our programming language of choice — Python!

Python does not give regular array data structures like Java or C++.

The one big point of difference of how arrays are implemented in Python is that they’re not normal arrays, they’re dynamic arrays.

A dynamic array has the property of auto-resizing. The arrays we define no longer need to be of fixed size, the number of elements we have in them can change(increase or decrease) anytime. Thus, it means that we can add or delete elements dynamically.

lists are used to implement arrays in python

So how do the runtime for different operations differ then?

Python lists runtime! — same but not really the same!

Insertion and deletion as well as lookup of elements and the append operation all take the same amount of time— O(n) and O(1) respectively. But there is a big point to take into consideration here, something to be beware of.

The time complexities mentioned here are not worst case time complexities, they are actually the amortised worst case times. This concept is quite easy to grasp once you understand the motivation behind it.

Here’s how this wiki article states it:

The motivation for amortised analysis is that looking at the worst-case run time per operation, rather than per algorithm, can be too pessimistic.

What this means is — amortisation consists of looking over the whole series of operations (each line of code or groups of lines of code) in the algorithm and then determining if they add up to be as costly or not. This is because while some operations in the algorithm might be costly, some might be actually very cheap, hence summing those up and looking at the entire algorithm, the runtime of the algorithm might not be as costly in practise!

How does this apply to dynamic arrays?

Now, as we were talking about dynamic arrays (implemented as Lists) before, let’s get back into it to understand this new concept of time complexity.

What happens when we try to append an element to an array that is already full? To make extra room, dynamic arrays automatically make a new, bigger underlying array of size twice as big as the current one.

The operations involved here will now include these — creating a new array of double the current size and then copying the elements of the current (old) array into the new array, one by one, and then finally, adding the new element to the array.

How much time does it take?

Let us look at an example first, to get the intuition behind and then we’ll move into the necessary jargon.