Optimizing this matrix shifter
You can sort each column separately (only move the transparent value to the top of the column) with a fast sorting algorithm like merge sort:

void mergeSortBlock(int *a, int index1, int index2, int size, int transparent){
    int *result;
    int resultIndex = 0;
    int mergeIndex1 = index1;
    int mergeIndex2 = index2;

    result = new int [size*2];

    while (mergeIndex1 &lt;= (index1 + size -1) &amp;&amp; mergeIndex2 &lt;= (index2 + size -1)){
        if (a[mergeIndex2] == transparent) {  // check the transparency
            result[resultIndex] = a[mergeIndex2];
            resultIndex++;
            mergeIndex2++;
        }
        else {
            result[resultIndex] = a[mergeIndex1];
            resultIndex++;
            mergeIndex1++;
        }
    }

    if (mergeIndex2 &lt;= (index2 + size - 1)) {
        for (int i = mergeIndex2 ; i&lt; (index2 + size); i++) {
            result[resultIndex] = a[mergeIndex2];
            resultIndex++;
            mergeIndex2++;              
        }
    }
    else{
        for (int i = mergeIndex1 ; i&lt; (index1 + size); i++) {
            result[resultIndex] = a[mergeIndex1];
            resultIndex++;
            mergeIndex1++;
        }
    }

    // copy the result back
    for (int i=0; i &lt; size*2; i++) {
        a[index1+i] = result[i];
    }       
    delete [] result;
}

void mergeSort(int *a, int indexFront,int indexEnd, int transparent){
    int size = (indexEnd - indexFront +1)/2;
    if (size &gt; 1){
        mergeSort(a, indexFront, indexFront + size - 1, transparent); 
        mergeSort(a, indexFront + size, indexEnd, transparent);
    }
    mergeSortBlock(a, indexFront, indexFront + size, size, transparent);
}


As you can see, in the mergeSortBlock function, instead of examining a[mergeIndex1]&gt;a[mergeIndex2] you check the transparency condition.

the indexFront is the index of the first element of your array and indexEnd is the index of the last element.

Now in your main, first you need to transpose the matrix so that the ith row of the transposed matrix (called result in this example) represents the ith column of your map matrix. then call the mergeSort function for each row of the transposed matrix, Result . 

int  main()
    int result[5][5];
    int map[][5] =
    {
        {0, 2, 3, 2, 0},
        {0, 1, 4, 0, 1},
        {1, 2, 2, 0, 3},
        {2, 1, 0, 0, 4},
        {4, 3, 1, 1, 3}
    };

    //transpose map =&gt; map's ith column = result's ith row
    for (int i = 0; i&lt;5; i++)
        for (int j = 0; j&lt;5; j++)
            result[j][i] = map[i][j];


    for (int i=0; i&lt;5; i++) 
        mergeSort(result[i],0,4,0);


    //transpose reuslt =&gt; result's ith row = map's ith column
    for (int i = 0; i&lt;5; i++)
        for (int j = 0; j&lt;5; j++)
            map[j][i] = result[i][j];

    return 0;
}


At the end again we need to transpose the matrix result.

Note: The complexity of merge sort is O(n.logn). You have n columns. This makes the complexity of the matrix shifter O(n^2.logn). Thanks to the nature of your problem, you can still improve this by parallel programming (of course if you have multiple processors). The complexity of transpose is O(n^2). The complexity of your own algorithm is O(n^3). 

Note2: You can modify mergeSort and mergeSortBlock functions to work directly with the columns of your matrix.