4 of 6 added 350 characters in body

MATL, 28 27 bytes


Adapted from my answer here. The general idea is to create a 2D array of the same size as the input, filled with values that increase in the same order as the zig-zag path. Then the linearized (flattened) version of that array is sorted, and the indices of that sorting are kept. Those are the indices that need to be applied to the input in order to produce the zig-zag path.

Input is in the form

[1 2 3; 5 6 4; 9 7 8; 1 2 3]

Try it online!

t       % input 2D array. Duplicate
ZyZ}    % get size as length-2 vector. Split into two numbers: r, c
:       % range [1,2,...,c] as a row vector
w:!     % swap, range [1;2;...;r] as a column vector
+       % add with broadcast. Gives a 2D array
-1      % push -1
y^      % duplicate previous 2D array. Compute -1 raised to that
7M      % push [1;2;...;r] again
Gn/     % divide by input matrix size, that is, r*c
*       % multiply
-       % subtract
X:      % linearize 2D array into column array
K#S     % sort and push the indices of the sorting. Gives a column vector
)       % index input matrix with that column vector