Morteza Noferesti
Arrays a kind of data structure that can store a fixedsize sequential collection of elements of the same type. An array is used to store a collection of data, but it is often more useful to think of an array as a collection of variables of the same type. Instead of declaring individual variables, such as number0, number1,..., and number99, you declare one array variable such as numbers and use numbers[0], numbers[1], and..., numbers[99] to represent individual variables. A specific element in an array is accessed by an index.
All arrays consist of contiguous memory locations. The lowest address corresponds to the first element and the highest address to the last element.
To declare an array in C, a programmer specifies the type of the elements and the number of elements required by an array as follows type arrayname [ arraysize ]; This is called a single-dimensional array. The arraysize must be an integer constant greater than zero and type can be any valid C data type.
For example, to declare a 10-element array called balance of type double, use this statement double balance[10]; Here balance is a variable array which is sufficient to hold up to 10 double numbers.
You can initialize an array in C either one by one or using a single statement as follows double balance[5] = 1000.0, 2.0, 3.4, 7.0, 50.0; The number of values between braces cannot be larger than the number of elements that we declare for the array between square brackets [ ].
If you omit the size of the array, an array just big enough to hold the initialization is created. Therefore, if you write double balance[] = 1000.0, 2.0, 3.4, 7.0, 50.0; You will create exactly the same array as you did in the previous example.
Following is an example to assign a single element of the array balance[4] = 50.0; The above statement assigns the 5th element in the array with a value of 50.0. All arrays have 0 as the index of their first element which is also called the base index and the last index of an array will be total size of the array minus 1. Shown below is the pictorial representation of the array we discussed above
An element is accessed by indexing the array name. This is done by placing the index of the element within square brackets after the name of the array. For example double salary = balance[9]; The above statement will take the 10th element from the array and assign the value to salary variable.
#include <stdio.h> int main () int n[ 10 ]; /* n is an array of 10 integers */ int i,j; /* initialize elements of array n to 0 */ for ( i = 0; i < 10; i++ ) n[ i ] = i + 100; /* set element at location i to i + 100 */ /* output each array element's value */ for (j = 0; j < 10; j++ ) printf("element[%d] = %d\n", j, n[j] ); return 0;
#include <stdio.h> int main() int marks[10], i, n, sum = 0, average; printf("enter n: "); scanf("%d", &n); for(i=0; i<n; ++i) printf("enter number%d: ",i+1); scanf("%d", &marks[i]); sum += marks[i]; average = sum/n; printf("average marks = %d", average); return 0;
Each name refers to a constant pointer Space for array elements is allocated at declaration time Can t change where the array name refers to but you can change the array elements, via pointer arithmetic int m[4]; (int [])??? (int)??? (int)??? (int)??? (int) m 13
array[subscript] equivalent to *(array + (subscript)) Strange but true: Given earlier declaration of m, the expression 2[m] is legal! Not only that: it s equivalent to *(2+m) *(m+2) m[2] 14
int m[3]; (int [])??? (int)??? (int)??? (int) m int *mid = m + 1; int *right = mid[1]; int *left = mid[-1]; int *beyond = mid[2]; 15
int m[3]; (int [])??? (int)??? (int)??? (int) m int *mid = m + 1; (int []) int *right = mid[1]; mid (int []) right int *left = mid[-1]; (int []) int *beyond = mid[2]; left compiler may not catch this runtime environment certainly won t (int []) beyond 16
But, functions that take arrays as arguments can exhibit what looks like pass-by-reference behavior, where the array passed in by the callee does get changed Remember the special status of arrays in C They are basically just pointers. So arrays are indeed passed by value but only the pointer is copied, not the array elements! Note the advantage in efficiency (avoids a lot of copying) But the pointer copy points to the same elements as the callee s array These elements can easily be modified via pointer manipulation 17
Ret_type fun (int array[length]). int main() int N=10; int A[N]; fun(a); Ret_type fun (int array[],int length). int main() int N=10; int A[N]; fun(a,n); Method 1 Method 2 18
#include <stdio.h> float print_array(int x[],int N) int i; for (i=0;i<n;i++) printf("%d\n",x[i]); void fill_array(int x[],int N) int i; for(i=0;i<n;i++) x[i]=i+1; int main() int N=10; int x[n]; fill_array(x,n); print_array(x,n); 19
How to interpret a declaration like: int d[2][4]; This is an array with two elements: Each element is an array of four int values The elements are laid out sequentially in memory, just like a one-dimensional array Row-major order: the elements of the rightmost subscript are stored contiguously (int) (int) (int) (int) (int) (int) (int) (int) d[0][0] d[0][1] d[0][2] d[0][3] d[1][0] d[1][1] d[1][2] d[1][3] d[0] d[1] 20
int d[2][4]; d [1] [2] *(d+1) Increment by the size of 1 array of 4 ints (int) (int) (int) (int) (int) (int) (int) (int) d[0][0] d[0][1] d[0][2] d[0][3] d[1][0] d[1][1] d[1][2] d[1][3] d[0] d[1] 21
int d[2][4]; d [1] [2] *(*(d+1)+2)*(d+1) Then increment by the size of 2 ints (int) (int) (int) (int) (int) (int) (int) (int) d[0][0] d[0][1] d[0][2] d[0][3] d[1][0] d[1][1] d[1][2] d[1][3] d[0] d[1] 22
If you use tricks with pointer arithmetic, the order matters a lot It also matters for initialization To initialize d like this: use this: int d[2][4] = 0, 1, 2, 3, 4, 5, 6, 7; 0 1 2 3 4 5 6 7 CS 3090: Safety Critical Programming in C 23
Only the first subscript may be left unspecified void f(int matrix[][10]); /* OK */ void g(int (*matrix)[10]); /* OK */ void h(int matrix[][]); /* not OK */ Why? Because the other sizes are needed for scaling when evaluating subscript expressions (see slide 10) This points out an important drawback to C: Arrays do not carry information about their own sizes! If array size is needed, you must supply it somehow (e.g., when passing an array argument, you often have to pass an additional array size argument) bummer 24
Matrix multiplication int main() int X[N][N],Y[N][N],Res[N][N],i,j,k; printf("enter X>>\n"); initial_matrix(n,x); printf("enter Y>>\n"); initial_matrix(n,y); //multiply the two matrix: for (i=0;i<n;i++) for (j=0;j<n;j++) Res[i][j]=0; for (k=0;k<n;k++) Res[i][j]+=X[i][k]*Y[k][j]; //print the result: print_matrix(res); 25
void initial_matrix(int N,int X[][N]) int i,j; for (i=0;i<n;i++) for (j=0;j<n;j++) scanf("%d",&x[i][j]); void print_matrix(int mat[][n]) int i,j; for(i=0;i<n;i++) for (j=0;j<n;j++) printf("%3d",mat[i][j]); printf("\n");
Search: locate an item in a list of information Two algorithms we will examine: Linear search Binary search
Also called the sequential search Starting at the first element, this algorithm sequentially steps through an array examining each element until it locates the value it is searching for.
Array numlist contains: 17 23 5 11 2 29 3 Searching for the the value 11, linear search examines 17, 23, 5, and 11 Searching for the the value 7, linear search examines 17, 23, 5, 11, 2, 29, and 3
Algorithm: set found to false; set position to 1; set index to 0 while index < number of elts. and found is false if list[index] is equal to search value found = true position = index end if add 1 to index end while return position
#include<stdio.h> int main() int N,key;int A[N];int i,indx=-1; printf("enter the number of elements:"); scanf("%d",&n); printf("enter the array\'s elements:"); for(i=0;i<n;i++) scanf("%d",&a[i]); printf("enter the key:"); scanf("%d",&key); for(i=0;i<n;i++) if(a[i]==key) indx=i; break; if(indx==-1) printf("the key does not exist"); else printf("the key does exist at index: %d ",indx); return 0;
Benefits: Easy algorithm to understand Array can be in any order Disadvantages: Inefficient (slow): for array of N elements, examines N/2 elements on average for value in array, N elements for value not in array
Requires array elements to be in order 1. Divides the array into three sections: middle element elements on one side of the middle element elements on the other side of the middle element 2. If the middle element is the correct value, done. Otherwise, go to step 1. using only the half of the array that may contain the correct value. 3. Continue steps 1. and 2. until either the value is found or there are no more elements to examine
Array numlist2 contains: 2 3 5 11 17 23 29 Searching for the the value 11, binary search examines 11 and stops Searching for the the value 7, linear search examines 11, 3, 5, and stops
Set first index to 0. Set last index to the last subscript in the array. Set found to false. Set position to -1. While found is not true and first is less than or equal to last Set middle to the subscript half-way between array[first] and array[last]. If array[middle] equals the desired value Set found to true. Set position to middle. Else If array[middle] is greater than the desired value Set last to middle - 1. Else Set first to middle + 1. End If. End While. Return position.
int binarysearch(int array[], int size, int value) int first = 0, // First array element last = size - 1, // Last array element middle, // Mid point of search position = -1; // Position of search value bool found = false; // Flag while (!found && first <= last) middle = (first + last) / 2; if (array[middle] == value) found = true; position = middle; // Calculate mid point // If value is found at mid else if (array[middle] > value) // If value is in lower half last = middle - 1; else first = middle + 1; return position; // If value is in upper half
0 1 2 3 4 5 6 10 14 19 27 31 35 42 log 2 N
Benefits: Much more efficient than linear search. For array of N elements, performs at most log 2 N comparisons Disadvantages: Requires that array elements be sorted
Sort: arrange values into an order: Ascending numeric Descending numeric Two algorithms considered here: Bubble sort Selection sort
Bubble sort algorithm starts by comparing the first two elements of an array and swapping if necessary, i.e., if you want to sort the elements of array in ascending order and if the first element is greater than second then, you need to swap the elements but, if the first element is smaller than second, you mustn't swap the element. Then, again second and third elements are compared and swapped if it is necessary and this process go on until last and second last element is compared and swapped. This completes the first step of bubble sort. If there are n elements to be sorted then, the process mentioned above should be repeated n-1 times to get required result. But, for better performance, in second step, last and second last elements are not compared becuase, the proper element is automatically placed at last after first step. Similarly, in third step, last and second last and second last and third last elements are not compared and so on. A figure is worth a thousand words so, acknowledge this figure for better understanding of bubble sort.
Here, there are 5 elements to the sorted. -2 45 0 11-9
Bubble Sort Algorithm(cont.)
Bubble Sort Algorithm(cont.)
Bubble Sort Algorithm(cont.)
Bubble Sort Algorithm(cont.)
/*C Program To Sort data in ascending order using bubble sort.*/ #include <stdio.h> int main() int data[100],i,n,step,temp; printf("enter the number of elements to be sorted: "); scanf("%d",&n); for(i=0;i<n;++i) printf("%d. Enter element: ",i+1); scanf("%d",&data[i]); for(step=0;step<n-2;++step) for(i=0;i<n-step-1;++i) if(data[i]>data[i+1]) /* To sort in descending order, change > to < in this line. */ temp=data[i]; data[i]=data[i+1]; data[i+1]=temp; printf("in ascending order: "); for(i=0;i<n;++i) printf("%d ",data[i]); return 0;
Benefit: Easy to understand and implement Disadvantage: Inefficient: slow for large arrays
The list is divided into two sublists, sorted and unsorted, which are divided by an imaginary wall. We find the smallest element from the unsorted sublist and swap it with the element at the beginning of the unsorted data. After each selection and swapping, the imaginary wall between the two sublists move one element ahead, increasing the number of sorted elements and decreasing the number of unsorted ones. Each time we move one element from the unsorted sublist to the sorted sublist, we say that we have completed a sort pass. A list of n elements requires n-1 passes to completely rearrange the data. CENG 213 Data Structures
Sorted Unsorted 23 78 45 8 32 56 Original List 8 78 45 23 32 56 After pass 1 8 23 45 78 32 56 After pass 2 8 23 32 78 45 56 After pass 3 8 23 32 45 78 56 After pass 4 8 23 32 45 56 78 After pass 5 CENG 213 Data Structures
#include <stdio.h> int main() int indexmin,i,j; int intarray[]=5,3,6,8,1,9; int MAX=6; // loop through all numbers for(i = 0; i < MAX; i++) // set current element as minimum indexmin = i; // check the element to be minimum for(j = i+1; j<max; j++) if(intarray[j] < intarray[indexmin]) indexmin = j; if(indexmin!= i) printf("items swapped: [ %d, %d ]\n", intarray[i], intarray[indexmin]); // swap the numbers int temp = intarray[indexmin]; intarray[indexmin] = intarray[i]; intarray[i] = temp; printf("iteration %d#:\n",(i+1)); for (i=0;i<max;i++) printf("%d\n",intarray[i]);
Benefit: More efficient than Bubble Sort, since fewer exchanges Disadvantage: May not be as easy as Bubble Sort to understand