0% found this document useful (0 votes)
48 views

Array Patterns

This document describes common patterns for using arrays. It provides examples of how to access a specific element, print or process all elements in order or reverse order, count elements meeting a condition, sum elements, find the largest/smallest element, find a specific element, and initialize arrays. The examples demonstrate using for loops with indexing and conditions to iterate through arrays element-by-element to perform these common tasks in 3 lines of code or less.

Uploaded by

Sofia TheFirst
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
48 views

Array Patterns

This document describes common patterns for using arrays. It provides examples of how to access a specific element, print or process all elements in order or reverse order, count elements meeting a condition, sum elements, find the largest/smallest element, find a specific element, and initialize arrays. The examples demonstrate using for loops with indexing and conditions to iterate through arrays element-by-element to perform these common tasks in 3 lines of code or less.

Uploaded by

Sofia TheFirst
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 11

Arrays Page 1

Array Patterns: Here are some common patterns that use arrays. In all the examples,
assume that the array is called blah; that it has length given by the variable length; and that the
array holds numbers, except where indicated.
Follow the link to go straight to that pattern.

1. Accessing the kth element of the array, d. Initializing the elements of an


for a given k. array to values input by the user
(or from a file), with a sentinel
2. Printing (or otherwise processing) all the loop.
values of an array, from beginning to
end. 9. Patterns that refer to another element
while processing the current element,
3. Printing (or otherwise processing) all the e.g.:
values of an array, backwards.
a. Determining whether an array is
4. Counting the number of elements in the sorted from smallest to largest.
array that meet a given condition.
b. Determining whether an array is
5. Summing the elements in an array of a palindrome.
numbers.
10. Loop-within-a-loop array patterns, e.g.:
6. Finding the largest (or smallest) number
in an array of numbers. a. Printing (or otherwise
processing) all the values of a
7. Finding a given element in an array, or two-dimensional array.
an element that meets a given
condition. b. Selection sort.

8. Initializing the elements of an array: 11. The sort-first pattern, e.g.:

a. Initializing the elements of an a. Finding the median value of an


array to random values. array.

b. Initializing the elements of an b. Binary search.


array to values that are a
function of the index. 12. The “histogram pattern” for counting
the occurrences of “events”, e.g. to find
c. Initializing the elements of an the mode (most common number) of an
array to values input by the user array.
(or from a file), asking the user
how big the array should be. 13. Using a pointer to simulate an array.
Arrays Page 2

1. Accessing the kth element of the array, for a given k. Just use:

blah[k]

No loop is necessary to access this single element.

2. Printing (or otherwise processing) all the values of an array, from beginning to end.

Must begin at 0.
Must be < (not <=).
int k;

for (k = 0; k < length; ++k) {


... blah[k] ...
Equivalent to: k = k + 1;
}

Many of the following patterns are special cases or variations of this general “processing”
pattern.

3. Printing (or otherwise processing) all the values of an array, backwards.

The index of the last element in the array.


int k;
Must be >= (not <=).
for (k = length - 1; k >= 0; --k) {
... blah[k] ...
} Equivalent to: k = k - 1;
Arrays Page 3

4. Counting the number of elements in the array that meet a given condition.

int k; Don’t forget to start the count variable at 0.


int count;

count = 0; The condition (what is inside the if clause)


will vary from problem to problem. This
for (k = 0; k < length; ++k) { example counts the number of elements in
if (blah[k] >= 5 && blah[k] <= 8) { the array that are between 5 and 8, inclusive.
++ count;
} After the loop concludes, the count
} variable contains the number of elements
... count ... in the array that met the condition.

5. Summing the elements in an array of numbers.


If you are summing integers, the type of sum
int k; should be int, not double.
double sum;
Don’t forget to start the sum variable at 0.
sum = 0;

for (k = 0; k < length; ++k) { Equivalent to: sum = sum + blah[k];


sum += blah[k];
} After the loop concludes, the sum variable
... sum ... contains the sum of the numbers in the array.

To sum just the elements that meet a given condition, use an if as in the counting example
above.
Arrays Page 4

6. Finding the largest (or smallest) number in an array of numbers.

Start by assuming that the index of the largest


int k; element in the array is element 0. Then the
int indexOfLargest = 0; loop that follows can start at 1 instead of at 0.

for (k = 1; k < length; ++k) {


If the element at index k is bigger than the
if (blah[k] > blah[indexOfLargest]) { largest number found so far, then change
indexOfLargest = k; the index of the largest number found so
} far to k.
... blah[indexOfLargest] ...
After the loop concludes, the
indexOfLargest variable
Change the > to < to find the smallest number in the array. contains the index of the
If it is possible that the array has no elements, you’ll need to make a largest number in the array.
special check for that. Also, modifications are necessary if you want
the indices of all the largest elements (including ties).

7. Finding a given element in an array, or an element that meets a given condition.

int k;
Start by setting indexOfElement
int indexOfElement = -1; to an impossible value.
Break out
for (k = 0; k < length; ++k) {
of the loop
if you find if (blah[k] == whatYouAreLookingFor) {
what you indexOfElement = k;
want. break; The condition (what is inside the if clause) will vary
} from problem to problem. This example finds the
} first element that equals whatYouAreLookingFor.

if (indexOfElement == -1) { After the loop concludes, if indexOfElement is


... still -1, then the array does not contain an
element that meets the given condition. Do
} else { whatever the problem calls for in that case.
... indexOfElement ...
}
Otherwise, indexOfElement is the index of the first
element in the array that meets the given condition.
Do whatever the problem calls for in that case.
Modifications are necessary if you want the
indices of all the elements that meet the given condition. Binary search is a much faster
method for finding a given element in an array if the array is already sorted.
Arrays Page 5

8. Initializing the elements of an array


a. Initializing the elements of an int k;
array to random values. int length = 1000;
For example, int dieRolls[length];
you can set all the values of a
dieRolls array to random values for (k = 0; k < length; ++k) {
between 1 and 6, as in the dieRolls[k] = 1 + rand() % 6;
example to the right: }

int k;
b. Initializing the elements of an
int length = 400;
array to values that are a function
int squares[length];
of the index.
For example, you can set the kth entry for (k = 0; k < length; ++k) {
of a squares array to k2, as in the example
squares[k] = k * k;
to the right:
}

c. Initializing the elements of an array to values input by the user (or from a file),
asking the user how big the array should be.

int length, k;

printf("How many temperatures will you enter? ");


fflush(stdout);
scanf("%i", &length);
This statement cannot be placed
earlier in the code – it must appear
double temperatures[length]; only after the variable length has
been assigned a meaningful value.
for (k = 0; k < length; ++k) {
printf("Enter a temperature: ");
fflush(stdout);
scanf("%lf", &(temperatures[k]));
}
Arrays Page 6

d. Initializing the elements of an array to values input by the user (or from a file),
with a sentinel loop.

int k, arrayLength, actualLength;


In this pattern, you don’t know in advance
arrayLength = 100; how many numbers the user will input.
double numbers[arrayLength]; So, your only choice is to pick an array
double number; size that you think will be big enough –
100 in this example.
actualLength = 0;
while (1) {
printf("Enter a floating-point number: "); In this example, the sentinel input (that is,
fflush(stdout); the special input by which the user
indicates that she is finished inputting
scanf("%lf", &number);
numbers) is any number less than 10,000.

if (number < -10000) { // Sentinel reached, stop input


break;
}

if (actualLength == arrayLength) { // Array length reached, stop input


printf("Sorry, I cannot hold more than %i numbers.\n", arrayLength);
break;
}

numbers[actualLength] = number;
After breaking out of the loop, the array
++ actualLength;
contains the numbers that the user
}
inputted. The variable actualLength
holds the number of inputs, hence is
treated as the length of the array in the
subsequent code.

This version of this pattern chooses an array length that the programmer hopes will
be “big enough” in practice. This is not a very robust solution! A better (but more
complicated) solution would be to use pointers to simulate the array and
dynamically (i.e., at run-time) “grow” the array as needed using malloc or realloc –
see How to Use Pointers to Save Time and Space.
Arrays Page 7

9. Patterns that refer to another element while processing the current element.
The pattern above for “finding the largest (or smallest) number in an array of numbers” is
an example of this pattern – the pattern loops through the array from beginning to end, and
at each iteration compares the current element (blah[k]) to the largest element found so
far (blah[indexOfLargest]).
Another example of this pattern is the int k; Start by setting isSorted
code to the right, which determines int isSorted = 1; to 1 (which means “true”).
whether an array is sorted from
smallest to largest. It does so by looping
for (k = 0; k < length - 1; ++k) {
through the array from beginning to end,
if (blah[k] > blah[k+1]) {
comparing the current element to the
next element in the array. isSorted = 0;
break;
After the loop concludes, if isSorted is still 1 (true), then } Here we have
every element of the array is no bigger than the } found a pair of
element after it, so the array is sorted from smallest to elements that are
largest. Do whatever the problem calls for in that case. NOT in the right
if (isSorted == 1) {
order, so set
... isSorted to 0
Otherwise, the loop found an element of the array } else { (“false”) and quit
that is smaller than the element after it, so the array ... the loop.
is NOT perfectly sorted from smallest to largest. Do }
whatever the problem calls for in that case.

Start by setting isPalindrome


One more example of this pattern int k; to 1 (which means “true”).
is the code to the right, which int isPalindrome = 1;
determines whether an array is a
palindrome (i.e., whether the array for (k = 0; k < length / 2; ++k) {
reads the same backwards as if (blah[k] != blah[length – 1 - k]) {
forwards). Here, the current isPalindrome = 0;
element is compared to its mate break;
that is the same distance from the Here we have found
}
end that the current element is a pair of matching
from the beginning. } elements that are
NOT the same, so
if (isPalindrome == 1) { set isPalindrome to
Being “off by 1” is a common error in
... 0 (“false”) and quit
problems like this, for example, using
blah[length – k] } else { the loop.
instead of ...
blah[length – 1 – k] }

The best way to avoid such “off by 1” errors is to trace the code on one or more small,
concrete examples. For example, here you should try arrays of length 4 and 5. (You should
do both odd and even lengths because of the length / 2 in the for statement.)
Arrays Page 8

10. Loop-within-a-loop array patterns.


One classic example here is printing (or otherwise processing) all the values of a two-
dimensional array:
int nRows = 100;
int nColumns = 100;
float blah[nRows][nColumns];

for (j = 0; j < nRows; ++j) {


for (k = 0; k < nColumns; ++k) {
printf("%f\n", blah[j][k]);
}
}

Another classic example of the loop-within-a-loop pattern is selection sort, an algorithm for
sorting an array. Selection sort is simple to understand/code and a good example of a loop-
within-a-loop pattern. However, be aware that there are much faster sorting algorithms
(e.g. quicksort) and that the standard C library includes a sort function (qsort).

int j, k, indexOfMinimum;
float temp;
Repeatedly:

for (j = 0; j < length - 1; ++j) {

indexOfMinimum = j; Find the smallest


for (k = j + 1; k < length; ++k) { remaining element
in the array.
if (blah[k] < blah[indexOfMinimum]) {
indexOfMinimum = k;
}
}
Put that element
just after the other
temp = blah[j];
elements that you
blah[j] = blah[indexOfMinimum]; have already placed
blah[indexOfMinimum] = temp; into their sorted
} order.

So the first time through the outer loop, you put the
smallest element into blah[0]. The second time
through the outer loop, you put the second-smallest
element into blah[1]. And so forth.
Arrays Page 9

11. The sort-first pattern.


Some operations are easier to perform on a sorted array than an unsorted one. For
example, one way to find the median of an array is:
Step 1: Sort the array (using selection sort, per the previous pattern, or some faster
sorting method).
Step 2: The median is the middle element of the sorted array if the array length is
odd, else it is the average of the two closest-to-middle elements in the sorted array.
Be aware that there are more sophisticated methods for finding the median of an array that
are slightly faster than the sort-first approach of this pattern.
Another example of this sort-first pattern is searching for a given element: if the array is
sorted, binary search will usually find the element (or determine that it is not in the array)
much faster than the linear search pattern presented earlier. It is especially useful if you
can sort once, then search many times. Here is the code for binary search:

int binarySearch(int blah[], int length, int numberToFind) {

int leftIndex, rightIndex, middleIndex; Begin by considering the entire array.

leftIndex = 0;
Try the middle of the
rightIndex = length - 1;
portion of the array
that might hold the
while (leftIndex < rightIndex) { numberToFind.
middleIndex = (leftIndex + rightIndex) / 2;

if (blah[middleIndex] < numberToFind) { Since the array is sorted,


leftIndex = middleIndex; if the number at middleIndex
is less than numberToFind,
} else if (blah[middleIndex] > numberToFind) { then we can restrict our search
rightIndex = middleIndex; to array positions bigger than
middleIndex.

} else {
return middleIndex;
Likewise, but we can restrict our
}
search to array positions smaller
} than middleIndex in this case.

return -1;
} The number at middleIndex is
We have eliminated all positions in the numberToFind – found it!
array – numberToFind is not in the
array. Return a code to indicate that.
Arrays Page 10

12. The “histogram pattern” for counting the occurrences of “events”, e.g. to find the mode
(most common number) of an array.
This pattern is useful whenever you want to know how often an “event” occurs, when you
have a collection of events that can be numbered into a relatively small range. The general
pattern goes like this:
Step 1: Declare an array that will hold values 0 .. n, where “events” are numbered
and n is the biggest event that can occur.
Step 2: Initialize all elements of the array to 0.
Step 3: Repeatedly:
o Get the next “event” in the collection of events from which the histogram is
to be built. That event’s number is, say, m.
o Increment the array value at index m.
After Step 3 completes, the array holds the desired histogram – the value at index i is
the number of times that event i occurred (hence the array is a histogram).
Here is a concrete example of this pattern: Suppose that you generate 10,000 random
integers, each between 0 and 100, inclusive, and suppose that you want to know which
random integer occurred most often. The following code solves this problem.

Finding the int k, generatedNumber, indexOfMaximum;


mode of an int numbers[101];
array of There are 101 “events” – the randomly generated
10,000 numbers can be any integer from 0 to 100, inclusive.
for (k = 0; k < 101; ++k) {
numbers, numbers[k] = 0;
each of which Initially, none of the events have occurred, so
}
is between 0 initialize all the entries in the histogram array to 0.
and 100,
works just like for (k = 0; k < 10000; ++k) {
this, except generatedNumber = rand() % 101;
Generate the 10,000 random numbers.
that you loop ++ numbers[generatedNumber];
Each time, increment the histogram
through the } array at the index of the generated
array here
number (i.e., at the index of the “event”.
instead of
indexOfMaximum = 0;
generating
for (k = 1; k < 101; ++k) {
the numbers.
if (numbers[k] > numbers[indexOfMaximum]) {
indexOfMaximum = k;
} Find the largest number in the
histogram array – that is the
}
event that occurred most often.

printf("%i occurred most often. It occurred %i times.\n",


indexOfMaximum, numbers[indexOfMaximum]);
Arrays Page 11

13. Using a pointer to simulate an array.


Applications of this include:
Setting the length of the array at run-time, that is, when the space-allocation
statement executes, even if you have an older compiler (pre-C99).
Two-dimensional “ragged arrays” in which the lengths of the rows vary from row to
row (this is especially handy for inputting and storing lines of text).
Passing an array to a function.
See Using a Pointer to Simulate an Array in Using Pointers to Save Time and Space for
details.

You might also like