The fact it uses bit operations does not mean it is the same.  Here's a quick microbenchmark:

nong@nong-OptiPlex-790:~/Test$ time ./a.out
Done 290329568.

real    0m4.459s              <-- this is zigzag
user    0m4.444s
sys     0m0.000s
nong@nong-OptiPlex-790:~/Test$ fg
vim zigzag-bench.cc

[1]+  Stopped                 vim zigzag-bench.cc
nong@nong-OptiPlex-790:~/Test$ g++ -O3 zigzag-bench.cc
nong@nong-OptiPlex-790:~/Test$ time ./a.out
Done 290329568.

real    0m0.806s              <-- this is min FOR encoding.
user    0m0.800s
sys     0m0.000s
nong@nong-OptiPlex-790:~/Test$ cat zigzag-bench.cc
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <algorithm>

int main(int argc, char** argv) {
  const int ITERS = 50000;
  const int N = 100000;
  int values[N];
  unsigned int zigzag[N];
  int offset[N];
  int min = 1000000;
  int max_val = 100;

  for (int i = 0; i < N; ++i) {
    int r = rand();
    if (r % 2 == 0) {
      values[i] = -r;
    } else {
      values[i] = r;
    }

    min = std::min(min, values[i]);
  }

  for (int i = 0; i < N; ++i) {
    offset[i] = values[i] - min;
    zigzag[i] = (values[i] << 1) ^ (values[i] >> 31);
  }

  for (int i = 0; i < N; ++i) {
    int offset_decode = offset[i] + min;
    if (offset_decode != values[i]) printf("Bad.\n");
    unsigned int v = zigzag[i];
    int zigzag_decode = (v >> 1) ^ -(v & 1);
    if (zigzag_decode != values[i]) printf("Bad.\n");
  }


  int dummy = 0;
  for (int iters = 0; iters < ITERS; ++iters) {
    for (int i = 0; i < N; ++i) {
#if 1
      dummy += (offset[i] + min);
#else
      dummy += (zigzag[i] >> 1) ^ -(zigzag[i] & 1);
#endif
    }
  }

  printf("Done %d.\n", dummy);