Data Structures - Array
Array is one of the most basic and commonly used data structures.
An array is a collection of elements of the same type stored contiguously in memory.
Array Definition and Memory Layout
In C, after an array is declared, a contiguous block of memory is allocated, and each element can be accessed directly by index.
The figure above shows the memory layout of an array containing 5 int elements. Assuming the starting address is 0x1000 and each int occupies 4 bytes, then:
- arr[0]Located at address 0x1000
- arr[1]Located at address 0x1004 (0x1000 + 4)
- arr[i]Located at address 0x1000 + i × 4
It is precisely due to this contiguous storage characteristic that arrays can usestarting address + offsetto access any element in O(1) time.
One-Dimensional Array
Example
int main() {
/* Declare and initialize a one-dimensional array */
int arr[5] = {10, 20, 30, 40, 50};
/* Traverse and access each element */
printf("Array elements: ");
for (int i = 0; i < 5; i++) {
printf("%d ", arr[i]);
}
printf("\n"); /* Output: Array elements: 10 20 30 40 50 */
/* Direct access by index, time complexity O(1) */
printf("arr[2] = %d\n", arr[2]); /* Output: 30 */
return 0;
}
Multidimensional Array
C supports multidimensional arrays, the most common being two-dimensional arrays, often used to represent tabular data such as matrices.
Two-dimensional arrays are still stored contiguously in memory by rows (row-major order), and are mapped to a two-dimensional view by calculating row and column indices.
Example
int main() {
/* Declare a two-dimensional array with 3 rows and 4 columns */
int matrix[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
/* Traverse the two-dimensional array: outer loop iterates over rows, inner loop iterates over columns */
printf("Two-dimensional array (3×4 matrix):\n");
for (int i = 0; i < 3; i++) { /* i is the row index */
for (int j = 0; j < 4; j++) { /* j is the column index */
printf("%2d ", matrix[i][j]);
}
printf("\n");
}
/* Access a specific element: matrix[row][column] */
printf("matrix[1][2] = %d\n", matrix[1][2]); /* Output: 7 */
return 0;
}
The memory address calculation formula for a two-dimensional array:
元素地址 = 起始地址 + (i × 列数 + j) × sizeof(元素类型). Where i is the row index, and j is the column index.
Basic Operations of Arrays
The figure above shows the core steps of array insertion and deletion operations: for insertion, the elements after the target position need to be shifted backward one by one to make room; for deletion, the elements after the target position need to be shifted forward one by one to fill the gap.
Traversal
Example
/* Traverse and print all elements of the array Time complexity: O(n), where n is the array length */
"Traversal result: "
void traverse(int arr[], int n) {
printf(/* Calculate the length of the array */);
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
int main() {
int arr[] = {15, 28, 43, 56, 71};
int n = sizeof(arr) / sizeof(arr[0]); Insertion
traverse(arr, n);
return 0;
}
Insertion
Example
"Array is full, cannot insert
"Invalid insertion position
/* From back to front, shift the elements at pos and after it backward by one position */
/* Write data at the new position */
/* Increase the element count by 1 */
int insert(int arr[], int n, int pos, int value, int capacity) {
if (n >= capacity) {
printf(/* Capacity is 10, currently has 4 elements */\n");
return -1;
}
if (pos < 0 || pos > n) {
printf("Before insertion: "\n");
return -1;
}
/* Output: Before insertion: 10 20 30 40 */
for (int i = n; i > pos; i--) {
arr[i] = arr[i - 1];
}
arr[pos] = value; /* Write data to the new position */
return n + 1; /* Increase the number of elements by 1 */
}
int main() {
int arr[10] = {10, 20, 30, 40}; /* Capacity is 10, currently there are 4 elements */
int n = 4;
printf(Before insertion:); for (int i = 0; i < n; i++) printf("%d ", arr[i]);
printf("\n"); /* Output: Before insertion: 10 20 30 40 */
n = insert(arr, n, 2, 25, 10); /* Insert 25 at index 2 */
printf("After insertion: "); for (int i = 0; i < n; i++) printf("%d ", arr[i]);
printf("\n"); /* Output: After insertion: 10 20 25 30 40 */
return 0;
}
Deletion
Example
/* Delete the element at a specified position in the array
Parameters: arr array, n current element count, pos deletion position (0-based)
Time complexity: O(n), worst case requires moving n elements
Return value: the number of elements after deletion */
int delete(int arr[], int n, int pos) {
if (n <= 0) {
printf("Array is empty, cannot delete\n");
return 0;
}
if (pos < 0 || pos >= n) {
printf("Invalid deletion position\n");
return n;
}
/* From front to back, move the elements after pos forward by one position */
for (int i = pos; i < n - 1; i++) {
arr[i] = arr[i + 1];
}
return n - 1; /* Decrease the element count by 1 */
}
int main() {
int arr[10] = {10, 20, 30, 40, 50};
int n = 5;
printf("Before deletion: "); for (int i = 0; i < n; i++) printf("%d ", arr[i]);
printf("\n"); /* Output: Before deletion: 10 20 30 40 50 */
n = delete(arr, n, 2); /* Delete the element at index 2 (30) */
printf("After deletion: "); for (int i = 0; i < n; i++) printf("%d ", arr[i]);
printf("\n"); /* Output: After deletion: 10 20 40 50 */
return 0;
}
Search
To find a target value in an unordered array, the most straightforward method is to traverse the entire array and compare one by one, which is called linear search.
Example
/* Linear search: search for a target value in an array
Time complexity: O(n), worst case requires traversing the entire array
Return value: the index of the target element, returns -1 if not found */
int search(int arr[], int n, int target) {
for (int i = 0; i < n; i++) {
if (arr[i] == target) {
return i; /* Found, return the index */
}
}
return -1; /* Not found */
}
int main() {
int arr[] = {43, 17, 89, 25, 61};
int n = 5;
int idx = search(arr, n, 89);
if (idx != -1) {
printf("Found target value 89, index is %d\n", idx); /* Output: Found target value 89, index is 2 */
} else {
printf("Target value not found\n");
}
return 0;
}
Advantages and Disadvantages of Arrays
| Advantages | Description |
|---|---|
| O(1) random access | Any element can be accessed in constant time via the index, which is the biggest advantage of arrays |
| Contiguous memory | Contiguous storage facilitates CPU cache hits (spatial locality), improving access efficiency |
| Simple implementation | Intuitive syntax, natively supported in most programming languages |
| Disadvantages | Description |
|---|---|
| Fixed size | Static arrays in C are sized at compile time and cannot be dynamically resized |
| Slow insertion/deletion | Inserting or deleting elements in the middle of an array requires moving many elements, with a time complexity of O(n) |
| Space waste | If the declared array is too large but the actual usage is small, it causes memory waste |
It is precisely these limitations that give rise to the more flexible dynamic structure to be studied in the next chapter —Linked list。
Operation Complexity Summary
| Operation | Time complexity | Description |
|---|---|---|
| Access by index | O(1) | Direct address calculation |
| Insert at the end | O(1) | No need to move elements |
| Insert at the head/middle | O(n) | Need to move subsequent elements |
| Delete the last element | O(1) | No need to move elements |
| Delete the head/middle element | O(n) | Need to move subsequent elements |
| Linear search | O(n) | Compare one by one |
| Binary search (sorted array) | O(log n) | Requires the array to be sorted |