Module 0054: Introduction to arrays

Tak Auyeung, Ph.D.

October 30, 2018

Contents

1 About this module
2 Why?
3 What is an array?
4 Initialization algorithm
5 Searching for a value in an array
 5.1 Unsorted array

1 About this module

2 Why?

Let us first explore why arrays are useful. This can be illustrated using an example.

The code that we need to find the maximum m of two variables a and b is simple. It is represented in algorithm 1.


Listing 1: Algorithm to find the maximum of 2 variables.
1if ab then 
2  ma 
3else 
4  mb 
5end if

If we add one more variable, c, then the algorithm gets more complicated, as described in algorithm 2.


Listing 2: Algorithm to find the maximum of 3 variables.
1if (ab)(ac) then 
2  ma 
3else 
4  if (ba)(bc) then 
5    mb 
6  else 
7    mc 
8  end if 
9end if

What if we have given 20 values? 200 values? 2000 values?

As you can see, this approach does not “scale”. In other words, the algorithm becomes more and more complicated as the number of values increases. However, if we use an array of numbers, then the algorithm is much simple, as described in algorithm 3.


Listing 3: Algorithm to find the maximum in an array of values.
1i0 
2minf 
3while i<|a| do 
4  if a[i]>m then 
5    ma[i] 
6  end if 
7  ii+1 
8end while

Of course, the complexity of algorithm 3 doesn’t appear to be much simpler than algorithm 2. However, algorithm 3 works for 3 values, 30, values, 3000 values, and etc. The same algorithm works for any number of values!

3 What is an array?

An array can be seen as one variable. However, it is actually the composite of many elements. An array has several attributes:

Note that each element of an array can behave like a variable on its own. You can use it on either side of an assignment, you can perform mathematical operations, you can compare and etc.

4 Initialization algorithm

Let us consider an algorithm that initializes an array so that all elements become 0. This algorithm is illustrated in algorithm 4.


Listing 4: Algorithm to initialize all elements in an array to 0.
1i0  
2while i<|a| do  
3  a[i]0  
4  ii+1  
5end while 

Let us analyze each line of code here.

When we trace an algorithm involving an array, each element in the array has its own column. This is hardly surprising because each element in an array is an independent variable! This fact does make the trace of an algorithm involving an array rather tedious. A table/spreadsheet should be used because the gridlines help significantly.

As an exercise, trace algorithm 4, assuming array a has 3 elements.

5 Searching for a value in an array

5.1 Unsorted array

Given an unsorted array a and a value v to find, how do we know whether the array has an element that matches the value v or not?

Algorithm 5 is the not-so-formal version.


Listing 5: An informal algorithm to search for a value in an unsorted array.
1start with the first element 
2while there are more elements, and the current one does not match v do 
3    move on to the next element 
4end while 
5if we have exhausted all elements then 
6  conclude no element has a value of v 
7else 
8  conclude at least one element has a value of v 
9end if

Recall our technique of using an integer variable to control which element we want to access. We an reapply that technique here. In fact, we’ll use the same variable i for this purpose.

To start with the first element means i should be initialized to 0. Hence, we have i 0 as our first statement.

Next, let us consider the phrase “there are more elements.” Since we start with the first element, then as long as the index remains within the range of 0 to |a| 1, there is at least one more element to consider. Consequently, “there are more elements” translates to the condition i < |a|. Note that we cannot use i |a| because when i = |a|, a[i] is not defined anymore.

The next phrase to consider is “the current one does not match v”. The “current one” is an element controled by the indexing variable i. In other words, the “current one” is simply a[i]. To say that a[i] does not match v is to say a[i]v.

As a result, the condition of the prechecking loop can be more formally written as (i < |a|) (a[i]v).

The only thing to do in the loop is to move on the next element. Because the current element is controled by the indexing variable i, to move on to the next element is to bump i up by 1. This means the action “move on to the next element” is really just i i + 1.

In the conditional (if-then-else) statement, how do we know we have exhausted all the elements in the array? If we have searched through the array and no element matches, i = |a|, and that is the reason to exit the prechecking loop. As a result, “we have exhausted all elements” should be replaced by i = |a|.

Algorithm 6 is the result of replacing all the not-so-formal description with formal pseudocode.


Listing 6: The formalized version of algorithm 5.
1i0 
2while (i<|a|)(a[i]v) do 
3  ii+1 
4end while 
5if i=|a| then 
6  // conclude no element in a has a value of v 
7else 
8  // conclude a[i] is the first element in a that has a value of v 
9end if

Again, it really helps to trace an algorithm. In this case, try to consider a as an array of 4 elements. Let’s assume a[0] = 2, a[1] = 0, a[2] = 10 and a[3] = 1.

Perform two traces. First, assume v = 7, trace. Then, assume v = 0, trace.