void DiaSortItems(long *it, long N, double **d) { /* Sorting keys: */ double *rd; long ka, kb; if (N <= 2) return; /* Find a diametral pair ka,kb of items, put it in it[0], it[N-1]: */ { long i, j, iMax, jMax; double dMax = -1; for (i=1; i dMax) { dMax = dd; iMax = i; jMax = j; } } ka = it[iMax]; it[iMax] = it[0]; it[0] = ka; kb = it[jMax]; it[jMax] = it[N-1]; it[N-1] = kb; } /* Define sort keys based on distances to ka and kb: */ { long i; double eps = 0.000001 * d[ka][kb]; if (eps == 0) return; rd = (double *)(Alloc(N*sizeof(double))); rd[0] = -1; rd[N-1] = +1; for (i=1; i= +1)) { Error("program error - rd[i] out of range"); } } } /* Sort remaining items "it[1..N-2]" by ratio of distances to those two: */ { long i; for (i=1; i ri) { rd[j] = rd[j-1]; it[j] = it[j-1]; j--; } if (i != j) { rd[j] = ri; it[j] = ki; } } } if (rd != NULL) free(rd); } void FarSortItems(long *it, long N, double **d) { /* Distances from path: */ long ka, kb; if (N <= 2) return; /* Find a diametral pair of items ka,kb, put them in it[0], it[1]: */ { long i, j, iMax, jMax; double dMax = -1; for (i=1; i dMax) { dMax = dd; iMax = i; jMax = j; } } ka = it[iMax]; it[iMax] = it[0]; it[0] = ka; kb = it[jMax]; it[jMax] = it[1]; it[1] = kb; } /* Repeately look for the farthest item, insert it in path: */ { long i, j; double *dd = (double *)(Alloc(N*sizeof(double))); /* Initialize the distance-from-path and best-place tables: */ /* If current path if "it[0..i-1]", then */ /* The candidates for insertion are "it[i..N-1]" */ /* Element "dd[j]" is distance of "it[j]" to the path *vertices* */ dd[0] = 0; dd[1] = 0; for (j=2; j ddMax) { ddMax = ddj; jMax = j; } } /* Save that item in "ki" and move the current "it[i]" there: */ /* We don't need "dd[jMax]" anymore: */ ki = it[jMax]; it[jMax] = it[i]; dd[jMax] = dd[i]; dd[i] = 0; where = InsertItemInPath(it, &i, ki, d); for (j=i; j 1) { /* The internal nodes created so far are [N..M-K] */ /* Find the two nearest clusters */ long iMin, jMin; { double dMin = 999; long i, j; for (i=0; i N-2) ? db : d[it[j]][it[j+1]]); double er = db/(da + db + dc + 1.0e-100); double prob = 0.125 + 0.375 * er; if (rand() < (int)(prob*32767)) { keep = !keep; /* fprintf(stderr, "keep=%d at j=%ld\n", keep, j); */ } da = db; db = dc; } if (keep) { /* keep it in the path */ long k = it[i]; it[i] = it[j]; it[j] = k; i++; } } } /* Insert the B items into the A path: */ while (i 0 ? it[p-1] : -1); long kb = (p < N ? it[p] : -1); double da = (ka > 0 ? d[ki][ka] : 0); double db = (kb > 0 ? d[ki][kb] : 0); double de = ((ka > 0) && (kb > 0) ? d[ka][kb] : 0); double ddp = da + db - de; if (ddp < ddMin) { ddMin = ddp; pMin = p; } } /* Open up that edge: */ p = N; while (p > pMin) { it[p] = it[p-1]; p--; } it[pMin] = ki; N++; /* Update path length: */ (*Np) = N; return (pMin); } void UniReSortItems(long *it, long N, double **d) { long i; if (N <= 2) return; /* Take each item and see if it would fit better elsewhere */ i = 0; while (i cjMin) { /* Move "ki = it[i]" to between "it[jMin-1" and "it[jMin]": */ /* Don't increment "i", because "it[i]" changed. */ if (jMin < i) { long r = i; while (r > jMin) { it[r] = it[r-1]; r--; } it[jMin] = ki; } else if (jMin > i+1) { long r = i+1; while (r < jMin) { it[r-1] = it[r]; r++; } it[jMin-1] = ki; } else { Error("program error - jMin = i+1, cjMin < ci"); } } else { i++; } } }