#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
 
/* #define DEBUG */
#if defined(DEBUG)
#include "xmalloc.h"
#else
#define xmalloc(x, y) malloc(x)
#define xfree(x, y) free(x)
#define xrealloc(x, y, z) realloc(x, y)
#define xmallocdump()
#endif
#define ID_DATANODE 1001

struct node {
  int value;
  struct node *next;
};

void push(struct node **root, int value) {
  struct node *p;
  if ((p = xmalloc(sizeof(struct node), ID_DATANODE)) != 0) {
    p->value = value;
    p->next = *root;
    *root = p;
  }
}

int pop(struct node **root, int *value) {
  int r;
  struct node *p;
  r = 0;
  if (*root != 0) {
    p = *root;
    *root = p->next;
    *value = p->value;
    xfree(p, ID_DATANODE);
    r = 1;
  }
  return r;
}

void sub_swap(struct node **p, struct node **q) {
  struct node *t, *s;
  if (&((*p)->next) == q) {
    assert((*p)->next == *q);
    t = *p;
    s = (*q)->next;
    *p = (*p)->next;
    (*q)->next = t;
    *q = s;
  } else {
    t = *p;
    *p = *q;
    *q = t;
    s = (*p)->next; /* in fact *p<=>*q but neet to do (*p)->next <=> (*q)->next */
    (*p)->next = (*q)->next;
    (*q)->next = s;
  }
}

void combsort(struct node **root, int n, int (*comp)(int, int)) {
  struct node **p, **q;
  int i, h, flag, c;
  c = 0;
  h = n;
  do {
    h = (int)(h / 1.247330950103979);
    if (h == 10)
      h = 11;
    if (h < 1)
      h = 1;
    fprintf(stderr, "%d:%d\n", ++c, h);
    flag = 0;
    for (q = root, i = 0; i < h; q = &((*q)->next), i++)
      ;
    p = root;
    for (;;) {
      if (comp((*p)->value, (*q)->value) > 0) {
        flag = 1;
        sub_swap(p, q);
      }
      if (*p == 0 || *q == 0 || (*p)->next == 0 || (*q)->next == 0)
        break;
      p = &((*p)->next);
      q = &((*q)->next);
    }
  } while (flag);
}

int cmp_ascent(int a, int b) {
  return a - b;
}

int isSortOK(struct node *root) {
  if (root->next) {
    if (root->value <= root->next->value) {
      return isSortOK(root->next);
    } else {
      return 0;
    }
  } else {
    return 1;
  }
}

#define SEED 31415926
#define N 100
int main(int argc, char *argv[]) {
  struct node *root;
  int i, v, flag;

  root = 0;
  srand(SEED);
  for (i = 0; i < N; i++)
    push(&root, (rand() / (RAND_MAX + 1.0) * 1000.0));

  combsort(&root, i, cmp_ascent);
  flag = isSortOK(root);

  i = 0;
  while (pop(&root, &v) != 0)
    printf("%3d : %4d\n", ++i, v);

  if (flag)
    fprintf(stderr, "Good.\n");
  else
    fprintf(stderr, "NG, there are some bugs in this program.\n");
  xmallocdump();
  return 0;
}
/* end */
