int selectKth(int *num, int b, int e, int k) { if (b >= e) { return num[b]; } int cmpIndex = b + rand() % (e - b); swap(&num[cmpIndex], &num[e - 1]); int i, m = b - 1; for (i = b; i < e - 1; i++) { if (num[i] < num[e - 1]) { m++; swap(&num[i], &num[m]); } } m++; swap(&num[m], &num[e - 1]); i = m - b + 1; if (i == k) { return num[m]; } else if(k < i) { selectKth(num, b, m, k); } else { selectKth(num, m + 1, e, k - i); } }
/** * Average-case linear time recursive algorithm to find position of kth * element in ar, which is modified as this computation proceeds. Note 1 * <= k <= right-left+1. The comparison function, cmp, is needed to * properly compare elements. Worst-case is quadratic, O(n^2). */ int selectKth (void **ar, int(*cmp)(const void *,const void *), int k, int left, int right) { int idx = selectPivotIndex (ar, left, right); int pivotIndex = partition (ar, cmp, left, right, idx); if (left+k-1 == pivotIndex) { return pivotIndex; } /* continue the loop, narrowing the range as appropriate. If we are within * the left-hand side of the pivot then k can stay the same. */ if (left+k-1 < pivotIndex) { return selectKth (ar, cmp, k, left, pivotIndex - 1); } else { return selectKth (ar, cmp, k - (pivotIndex-left+1), pivotIndex+1, right); } }
int main(int argc, char const *argv[]) { int k = atoi(argv[1]); int arr[] = {1,6,4,7,11,3,5,12}; //{1,3,4,5,6,7,11,12} int n = sizeof(arr) / sizeof(arr[0]); std :: cout << n << std :: endl; std :: cout << selectKth(arr,k-1,n) << std :: endl; return 0; }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { /* Matrix for input, temporary, and output. */ double *Z, *ZTmp, v; // v return value, *Z input values. /* Size */ mwSignedIndex n; /* k-th smallest element */ int k; /* Check for proper number of arguments. */ if ( nrhs != 2 ) { mexErrMsgIdAndTxt("MATLAB:imresize:rhs", "This function requires 2 input arguments."); } if ( nlhs != 1) { mexErrMsgIdAndTxt("MATLAB:imresize:lhs", "This function requires 1 output argument."); } k = (int) mxGetScalar(prhs[1]); n = (mwSignedIndex) mxGetM(prhs[0]); // Ensure that Z is a 1D column vector. if ( n < 1 || ((mwSignedIndex) mxGetN(prhs[0])) > 1 ) { mexErrMsgIdAndTxt("MATLAB:selectKth", "Z must be a 1D column-vector."); } // The index k must range have the range 1 <= k <= n. if ( k < 1 || k > n ) { mexErrMsgIdAndTxt("MATLAB:selectKth", "k must be >= 1 and <= n."); } Z = mxGetPr(prhs[0]); ZTmp = (double*) malloc(n * sizeof(double)); // Create copy because Z will be changed! memcpy(ZTmp, Z, n * sizeof(double)); v = selectKth(ZTmp, n, k-1); // k-1 to match index range 0...n-1 plhs[0] = mxCreateDoubleScalar(v); free(ZTmp); }
/** * Sort using medianSort method. * * @param ar array of elements to be sorted. * @param cmp comparison function to order elements. * @param left The left-bounds within which to sort (0 <= left < ar.length) * @param right The right-bounds within which to sort (0 <= right < ar.length) */ void mediansort (void **ar, int(*cmp)(const void *,const void *), int left, int right) { int me, mid; /* if the subarray to be sorted has 1 (or fewer!) elements, done. */ if (right <= left) { return; } /* get midpoint and median element position (note 1<=k<=right-left-1). */ mid = (right - left + 1)/2; me = selectKth (ar, cmp, mid+1, left, right); /* at this point, me should be equal to mid+1. */ if (mid-1 <= minSize) { insertion (ar, cmp, left, left+mid-1); } else { mediansort (ar, cmp, left, left+mid-1); } if (right-left-mid-1 <= minSize) { insertion (ar, cmp, left+mid+1, right); } else { mediansort (ar, cmp, left+mid+1, right); } }