CategoryC Program

C Program to move all zeros to the beginning of an array

Learn how to move every zero to the beginning of a C array in place while preserving the relative order of all nonzero elements.

Moving all zeros to the beginning means rearranging an array so that every 0 appears before all nonzero values. The relative order of the nonzero values should remain unchanged.

For example:

Original array: 0 4 0 -2 7 0 5
Updated array:  0 0 0 4 -2 7 5

The three zeros are grouped at the front, while the nonzero sequence 4, -2, 7, 5 stays in its original order.

C Program to Move All Zeros to the Beginning of an Array

#include <stdio.h>

#define MAX_SIZE 100

int main(void) {
    int array[MAX_SIZE];
    int size;

    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;
        }
    }

    int writeIndex = size - 1;

    for (int readIndex = size - 1; readIndex >= 0; readIndex--) {
        if (array[readIndex] != 0) {
            array[writeIndex] = array[readIndex];
            writeIndex--;
        }
    }

    while (writeIndex >= 0) {
        array[writeIndex] = 0;
        writeIndex--;
    }

    printf("Array after moving zeros to the beginning: ");
    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 beginning: 0 0 0 4 -2 7 5

How the Program Works

The algorithm rearranges the array in two stages:

  1. Scan from right to left and copy every nonzero value to the next available position at the end.
  2. Fill all remaining positions at the beginning with zero.

The variable readIndex examines the original values. The variable writeIndex marks the next position where a nonzero value belongs:

int writeIndex = size - 1;

for (int readIndex = size - 1; readIndex >= 0; readIndex--) {
    if (array[readIndex] != 0) {
        array[writeIndex] = array[readIndex];
        writeIndex--;
    }
}

After all nonzero values have been compacted at the end, indices 0 through writeIndex are filled with zero:

while (writeIndex >= 0) {
    array[writeIndex] = 0;
    writeIndex--;
}

Dry Run

Consider the array 0 4 0 -2 7 0 5. Initially, writeIndex is 6, the last valid index.

readIndexCurrent valueActionNonzero suffix after the action
65Write at index 65
50Skip5
47Write at index 57 5
3-2Write at index 4-2 7 5
20Skip-2 7 5
14Write at index 34 -2 7 5
00Skip4 -2 7 5

The first pass finishes with writeIndex equal to 2. The second pass writes zero into indices 2, 1, and 0, producing:

0 0 0 4 -2 7 5

Why Must the Array Be Scanned from Right to Left?

The nonzero values are being moved toward the right side. Scanning from right to left ensures that each assignment writes either to the current position or to a later position that has already been processed.

Throughout the first pass, writeIndex is never smaller than readIndex. Therefore:

array[writeIndex] = array[readIndex];

cannot overwrite an unread element on the left.

If the same compaction were attempted from left to right while writing at the end, an early assignment could replace a value that the loop still needed to examine. Matching the scan direction to the movement direction prevents that error.

Why Is the Order of Nonzero Elements Preserved?

The algorithm reads nonzero values from right to left and also writes them from right to left. Their relative order therefore remains unchanged.

For example:

Input:  3 0 1 0 2
Output: 0 0 3 1 2

The nonzero sequence is 3, 1, 2 in both arrays. An algorithm with this property is described as stable.

Is an Additional Array Needed?

No. The program changes the original array and uses only the two index variables. It is an in-place algorithm with constant extra space.

Creating a separate result array would also be possible, but it would require O(n) extra storage. In-place compaction achieves the same result without that additional array.

What If There Are No Zeros?

Each value is copied to its current position, writeIndex eventually becomes -1, and the filling loop does not run:

Input:  6 -2 9 4
Output: 6 -2 9 4

The array remains unchanged because there are no zeros to move.

What If Every Element Is Zero?

The compaction loop skips every element, so writeIndex remains at size - 1. The second loop writes zeros into the entire array, leaving its contents unchanged:

Input:  0 0 0 0
Output: 0 0 0 0

What About Negative Values?

Negative numbers are nonzero and retain their order with the other nonzero values:

Input:  -3 0 5 0 -1
Output: 0 0 -3 5 -1

The condition array[readIndex] != 0 treats only the integer value zero as an element to move.

Moving Zeros to the Beginning Versus the End

Both operations use stable in-place compaction, but the direction is different:

  • To move zeros to the end, scan from left to right and compact nonzero values at the front.
  • To move zeros to the beginning, scan from right to left and compact nonzero values at the end.

Choosing the correct direction prevents unread data from being overwritten and preserves the order of nonzero values.

Alternative Swap Method

A stable one-pass version can swap each nonzero value into the position identified by writeIndex:

int writeIndex = size - 1;

for (int readIndex = size - 1; readIndex >= 0; readIndex--) {
    if (array[readIndex] != 0) {
        int temporary = array[writeIndex];
        array[writeIndex] = array[readIndex];
        array[readIndex] = temporary;
        writeIndex--;
    }
}

This variation moves zeros toward the beginning during the scan. The two-pass method in the main program is often clearer because it separates nonzero compaction from zero filling.

Time and Space Complexity

For an array of n elements:

  • Time complexity: O(n). Every element is inspected once, and at most n leading positions are filled afterward.
  • Extra space complexity: O(1). The original array is modified using only index variables.

Common Mistakes

  • Scanning left to right while copying nonzero values toward the end and overwriting unread data.
  • Swapping zeros with arbitrary values from the front or end and changing the order of nonzero elements.
  • Incrementing writeIndex instead of decrementing it.
  • Forgetting to initialize writeIndex to size - 1.
  • Forgetting to fill indices 0 through writeIndex with zeros after compaction.
  • Using repeated element shifting, which can increase the running time to O(n²).
  • Treating negative numbers as zeros.

By scanning backward, compacting nonzero values at the end, and then filling the remaining leading positions, the program moves all zeros to the beginning in linear time without changing the order of the other elements.