//Partition the array into two halves and return the //index about which the array is partitioned int partition(int rows, int cols, int colToSortOn, double * array, int left, int right) { //Makes the leftmost element a good pivot, //specifically the median of medians findMedianOfMedians(rows, cols, colToSortOn, array, left, right); int pivotIndex = left, index = left, i; double * colToSort = array+colToSortOn*rows, pivotValue = colToSort[pivotIndex]; swapRows(rows, cols, array, pivotIndex, right); for(i = left; i < right; i++) { if(colToSort[i] < pivotValue) { swapRows(rows, cols, array, i, index); index += 1; } } swapRows(rows, cols, array, right, index); return index; }
// | | | | | // v v v v v // * * * * * // 0 2 45 77 100 // 0 45 77 2 100 // * * * 2 100 // * * * * * // 2 66 51 78 101 // 2 51 78 66 101 // * * * 66 101 // * * * * * // 6 90 52 79 102 // 6 52 79 90 102 <<---- // 6 52 |79| 90 102 // * * * * * // 89 91 65 90 200 // 89 65 90 91 200 // 89 65 * * * // * * * * * // 200 100 98 99 250 // 200 98 99 100 250 // 200 98 * * * int findMedianOfMedians(std::vector<int>& input, int left, int right) { std::vector<int> medianVecs; for (int rangeCounter = left; rangeCounter < right;) { std::vector<int> fiveElem; for (int i = 0; i < 5 && rangeCounter < right; ++i) /// probably switch to sort directly in the inputvector this could help to reduce memory allocs.. { //std::cout << input[left + rangeCounter] << " "; fiveElem.push_back(input[rangeCounter]); ++rangeCounter; } std::sort(fiveElem.begin(), fiveElem.end()); //std::cout << std::endl << "m: " << fiveElem[static_cast<int> (fiveElem.size() / 2)] << std::endl; medianVecs.push_back(fiveElem[static_cast<int> (fiveElem.size() / 2)]); } //std::cout << "---------------------------" << std::endl; if (medianVecs.size() <= 5) { std::sort(medianVecs.begin(), medianVecs.end()); return medianVecs[(medianVecs.size() - 1) / 2]; } else { return findMedianOfMedians(medianVecs, 0, medianVecs.size()); } }
//The Dselect Algo -> deterministic select algorithm - Median of medians // break A into groups of 5 sort each group with what ever wanted // C = the n/5 "middle elements" // p = Select (C, n/5 , n/10) recursevly computes median of C // Partition A around p // if j = i return p // if j < i return select ( first part of A, j-1 , i) // else if j > i return select ( second part of A , n-j , i-j) void DselectAlgo(std::vector<int>& input, int left, int right) { //std::cout << "----------------------------" << std::endl; //std::cout << "LR: " << left << "|" << right << std::endl << std::endl; std::vector<int>::iterator bound; int median = findMedianOfMedians(input, left, right); //int indexPivot = partition_around_pivot_a(input, left, right, median); bound = std::partition(input.begin() + left, input.begin() + right, [median](int val){return val < median; }); //for (int i = 0; i < input.size(); ++i) //{ // std::cout << input[i] << ", "; //} //std::cout << std::endl; //int boundIdx = left + indexPivot; int boundIdx = bound - input.begin(); //std::cout << "m: " << median; //std::cout << " idx " << boundIdx << std::endl; // check if work is done if ((boundIdx - left) > 1) // left side { //std::cout << "left " << std::endl; //std::cout << "----------------------------" << std::endl << std::endl; DselectAlgo(input, left, boundIdx); } if ((right - boundIdx) > 1) // right side { //std::cout << "right " << std::endl; //std::cout << "----------------------------" << std::endl << std::endl; DselectAlgo(input, boundIdx, right); } }
/* Recursive engine (partial quicksort) */ void findFirstK(mwIndex left, mwIndex right) { mwIndex pivotIndex; if (right > left) { #if (PIVOT==MEDIANMEDIANS) pivotIndex = findMedianOfMedians(left, right); #elif (PIVOT==MEDIAN3) pivotIndex = findMedianThree(left, right); #else /* MIDPOINT */ pivotIndex = (left+right+1)/2; #endif pivotIndex = partition(left, right, pivotIndex); if (pivotIndex > k) findFirstK(left, pivotIndex-1); else if (pivotIndex < k) findFirstK(pivotIndex+1, right); } return; } /* findFirstK */