C Program to move all zeros to the end of an array
Learn how to move every zero to the end of a C array in place while preserving the order of nonzero elements.
Moving all zeros to the end means rearranging an array so that every nonzero element appears first and every 0 appears afterward. The relative order of the nonzero elements should remain unchanged.
For example:
Original array: 0 4 0 -2 7 0 5
Updated array: 4 -2 7 5 0 0 0
The values 4, -2, 7, and 5 remain in their original order. Only the zeros are moved.
C Program to Move All Zeros to the End of an Array
#include <stdio.h>
#define MAX_SIZE 100
int main(void) {
int array[MAX_SIZE];
int size;
int writeIndex = 0;
printf("Enter the number of elements: ");
if (scanf("%d", &size) != 1 || size < 1 || size > MAX_SIZE) {
printf("Please enter a size between 1 and %d.\n", MAX_SIZE);
return 1;
}
printf("Enter %d elements:\n", size);
for (int index = 0; index < size; index++) {
if (scanf("%d", &array[index]) != 1) {
printf("Invalid array element.\n");
return 1;
}
}
for (int readIndex = 0; readIndex < size; readIndex++) {
if (array[readIndex] != 0) {
array[writeIndex] = array[readIndex];
writeIndex++;
}
}
while (writeIndex < size) {
array[writeIndex] = 0;
writeIndex++;
}
printf("Array after moving zeros to the end: ");
for (int index = 0; index < size; index++) {
printf("%d ", array[index]);
}
printf("\n");
return 0;
}
Sample Output
Enter the number of elements: 7
Enter 7 elements:
0 4 0 -2 7 0 5
Array after moving zeros to the end: 4 -2 7 5 0 0 0
How the Program Works
The algorithm completes the rearrangement in two passes over the array:
- Copy each nonzero element to the next available position at the front.
- Fill every unused position at the end with
0.
The variable readIndex examines the original elements from left to right. The variable writeIndex identifies the next position where a nonzero element should be stored.
for (int readIndex = 0; readIndex < size; readIndex++) {
if (array[readIndex] != 0) {
array[writeIndex] = array[readIndex];
writeIndex++;
}
}
After this loop, writeIndex is also the number of nonzero elements. Every position from writeIndex through size - 1 must therefore contain zero:
while (writeIndex < size) {
array[writeIndex] = 0;
writeIndex++;
}
Dry Run
Consider the input 0 4 0 -2 7 0 5.
During the first pass, only nonzero values are copied:
readIndex | Current value | Action | Nonzero portion after the action |
|---|---|---|---|
| 0 | 0 | Skip | Empty |
| 1 | 4 | Write at index 0 | 4 |
| 2 | 0 | Skip | 4 |
| 3 | -2 | Write at index 1 | 4 -2 |
| 4 | 7 | Write at index 2 | 4 -2 7 |
| 5 | 0 | Skip | 4 -2 7 |
| 6 | 5 | Write at index 3 | 4 -2 7 5 |
At the end of the first pass, writeIndex is 4. The second pass writes zero into indices 4, 5, and 6, producing:
4 -2 7 5 0 0 0
Why Does Overwriting Not Lose an Unread Value?
During the compaction pass, writeIndex can never be greater than readIndex:
- When no zero has been seen, both indices progress together.
- After a zero is found,
writeIndexremains behindreadIndex.
Therefore, the assignment below writes either to the current position or to an earlier position:
array[writeIndex] = array[readIndex];
It never overwrites an element that the loop has not read yet. This makes in-place compaction safe.
Why Is This a Stable Algorithm?
An algorithm is stable here when it preserves the relative order of the nonzero values. Because readIndex visits elements from left to right and each nonzero value is written immediately to the next open position, their order cannot change.
For example:
Input: 3 0 1 0 2
Output: 3 1 2 0 0
The nonzero sequence is 3, 1, 2 before and after the operation.
Swapping each zero with an element from the end would also group the zeros, but it could change that sequence. For example, it might turn 3 0 1 2 into 3 2 1 0. The compaction method avoids this problem.
Is an Additional Array Required?
No. The program modifies the original array and uses only two integer indices. This is called an in-place algorithm.
An approach that creates a second array can also work, but it needs O(n) additional memory. The in-place approach needs only O(1) extra space.
What If the Array Contains No Zeros?
Every element is copied to its current position, and writeIndex reaches size. The while loop does not execute, so the array remains unchanged:
Input: 2 -1 8 5
Output: 2 -1 8 5
What If Every Element Is Zero?
The first loop skips every value, leaving writeIndex equal to 0. The second loop fills the entire array with zeros, which leaves it unchanged:
Input: 0 0 0 0
Output: 0 0 0 0
What About Negative Values?
Negative numbers are nonzero values, so they move toward the front just like positive numbers:
Input: 0 -4 0 3 -1
Output: -4 3 -1 0 0
The condition array[readIndex] != 0 excludes only the integer value zero.
Alternative One-Pass Swap Method
The same stable result can be produced by swapping each nonzero value with the position indicated by writeIndex:
int writeIndex = 0;
for (int readIndex = 0; readIndex < size; readIndex++) {
if (array[readIndex] != 0) {
int temporary = array[writeIndex];
array[writeIndex] = array[readIndex];
array[readIndex] = temporary;
writeIndex++;
}
}
This method places zeros as it scans, so it does not need a separate fill loop. The two-pass compaction version used in the main program is often easier for beginners to follow and avoids unnecessary swaps when elements are already in the correct positions.
Time and Space Complexity
For an array containing n elements:
- Time complexity:
O(n). The first pass examines every element, and the second pass writes at mostnzeros. Together they still perform a linear amount of work. - Extra space complexity:
O(1). The program rearranges the original array using only index variables.
Common Mistakes
- Swapping zeros with values from the end and unintentionally changing the order of nonzero elements.
- Incrementing
writeIndexwhen a zero is found instead of only after copying a nonzero value. - Forgetting to fill the unused positions with zeros after compaction.
- Using a nested loop to shift elements repeatedly, which can take
O(n²)time. - Allocating another array even though the operation can be performed in place.
- Treating negative numbers as zeros or excluding them from the nonzero sequence.
- Printing only up to
writeIndexand omitting the zeros at the end.
By compacting nonzero values first and filling the remaining positions afterward, the program moves every zero to the end in linear time while preserving the original order of all nonzero elements.