/**
* partition, quicksort, ith element
* Template functions
*
* Author: Erel Segal
* Date: 2010-10-17
*/
#include <stdlib.h>
#include <iostream>
#include <sstream>
using namespace std;
/**
* partition the given array [iFrom,iTo) into: less than pivot / pivot / greater than pivot.
* @return an iterator right after the partition point.
*/
template <class Iterator, typename T> Iterator partition (Iterator iFrom, Iterator iTo, T pivot) {
while (iFrom<iTo) {
if (*iFrom<pivot)
++iFrom;
else if (*iTo>pivot)
--iTo;
else if (*iFrom>*iTo) { /* pivot <= iFrom and *iTo <= pivot */
swap(*iFrom, *iTo);
++iFrom;
} else { /* pivot == *iFrom == *iTo == pivot */
++iFrom;
}
}
return iFrom;
}
/**
* partition the given array [iFrom,iTo) into: less than pivot / greater than pivot
* @return the index where the pivot element should be inserted
*/
template <class Iterator> void quicksort (Iterator iFrom, Iterator iTo) {
int size = iTo-iFrom;
//cout << prefix << "quicksorting " << size << " elements: "; print(iFrom, iTo);
if (size<=1) return;
Iterator pivot = iFrom+rand()%size;
Iterator pivotAfterPartition = partition(iFrom, iTo-1, *pivot);
//cout << prefix << "partitioning by " << *pivot << " at place " << (pivotAfterPartition-iFrom) << endl;
if (pivotAfterPartition==iFrom) { // pivot is minimum
quicksort(iFrom+1, iTo);
} else if (pivotAfterPartition==iTo) { // pivot is maximum
quicksort(iFrom, iTo-1);
} else {
quicksort(iFrom, pivotAfterPartition);
quicksort(pivotAfterPartition , iTo);
}
//cout << prefix << "--------------------------- "; print(iFrom, iTo);
}
/* find the element whose position in the sorter array is "rank" (rank >= 0) */
template <class Iterator> Iterator ithElement(Iterator iFrom, Iterator iTo, int rank) {
int size = iTo-iFrom;
//cout << prefix << "quicksorting " << size << " elements: "; print(iFrom, iTo);
if (rank>=size) {
stringstream error;
error << "tried to find element " << rank << " but there are only " << size << " elements!";
throw (error.str());
} else if (size==1) {
return iFrom;
}
Iterator pivot = iFrom+rand()%size;
Iterator pivotAfterPartition = partition(iFrom, iTo-1, *pivot);
int numBeforePivot = pivotAfterPartition-iFrom;
if (rank < numBeforePivot)
return ithElement(iFrom, pivotAfterPartition, rank);
else
return ithElement(pivotAfterPartition, iTo, rank-numBeforePivot);
}
template <class Iterator> void print (Iterator iFrom, Iterator iTo) {
for (; iFrom<iTo; ++iFrom) {
cout << *iFrom << " ";
}
cout << endl;
}
template <class Iterator> void assertSorted(Iterator iFrom, Iterator iTo) {
for (; iFrom<iTo-1; ++iFrom) {
if (*iFrom > *(iFrom+1)) {
cerr << "array is out of order: " << *iFrom << " > " << *(iFrom+1) << endl;
}
}
cout << endl;
}
void checkPartition(int array[], int size, int pivot) {
cout << "before: "; print (array, array+size);
int* pivotAfterPartition = partition(array, array+size-1, pivot);
cout << "after (position of "<<pivot<<" = " << (pivotAfterPartition-array) << "): "; print (array, array+size);
//assertSorted(array, array+size);
}
void checkQuicksort(int array[], int size) {
cout << "before: "; print (array, array+size);
quicksort(array, array+size);
cout << "after: "; print (array, array+size);
assertSorted(array, array+size);
}
void checkIthElement(int array[], int size) {
for (int i=0; i<size; ++i) {
cout << "Element #" << i << ": " << (*ithElement(array, array+size, i)) << endl;
}
}
#include <time.h>
int main() {
srand(time(NULL));
int size=20;
int* a = new int[size];
for (int i=0; i<size; ++i)
a[i] = rand()%100;
checkPartition(a, size, rand()%100);
checkIthElement(a,size);
checkQuicksort(a, size);
}
LyoqCiAqIHBhcnRpdGlvbiwgcXVpY2tzb3J0LCBpdGggZWxlbWVudAogKiBUZW1wbGF0ZSBmdW5jdGlvbnMKICoKICogQXV0aG9yOiBFcmVsIFNlZ2FsCiAqIERhdGU6IDIwMTAtMTAtMTcKICovCgojaW5jbHVkZSA8c3RkbGliLmg+CiNpbmNsdWRlIDxpb3N0cmVhbT4KI2luY2x1ZGUgPHNzdHJlYW0+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7CgoKLyoqCiogcGFydGl0aW9uIHRoZSBnaXZlbiBhcnJheSBbaUZyb20saVRvKSBpbnRvOiBsZXNzIHRoYW4gcGl2b3QgLyBwaXZvdCAvIGdyZWF0ZXIgdGhhbiBwaXZvdC4KKiBAcmV0dXJuIGFuIGl0ZXJhdG9yIHJpZ2h0IGFmdGVyIHRoZSBwYXJ0aXRpb24gcG9pbnQuCiovCnRlbXBsYXRlIDxjbGFzcyBJdGVyYXRvciwgdHlwZW5hbWUgVD4gSXRlcmF0b3IgcGFydGl0aW9uIChJdGVyYXRvciBpRnJvbSwgSXRlcmF0b3IgaVRvLCBUIHBpdm90KSB7CgkJCXdoaWxlIChpRnJvbTxpVG8pIHsKCQkJCQkJCWlmICgqaUZyb208cGl2b3QpCgkJCQkJCQkJCQkJKytpRnJvbTsKCQkJCQkJCWVsc2UgaWYgKCppVG8+cGl2b3QpCgkJCQkJCQkJCQkJLS1pVG87CgkJCQkJCQllbHNlIGlmICgqaUZyb20+KmlUbykgeyAgIC8qIHBpdm90IDw9IGlGcm9tIGFuZCAqaVRvIDw9IHBpdm90ICovCgkJCQkJCQkJCQkJc3dhcCgqaUZyb20sICppVG8pOwoJCQkJCQkJCQkJCSsraUZyb207CgkJCQkJCQl9IGVsc2UgeyAgICAgLyogcGl2b3QgPT0gKmlGcm9tID09ICppVG8gPT0gcGl2b3QgKi8KCQkJCQkJCQkJCQkrK2lGcm9tOwoJCQkJCQkJfQoJCQl9CgkJCXJldHVybiBpRnJvbTsKfQoKCi8qKgoqIHBhcnRpdGlvbiB0aGUgZ2l2ZW4gYXJyYXkgW2lGcm9tLGlUbykgaW50bzogbGVzcyB0aGFuIHBpdm90IC8gZ3JlYXRlciB0aGFuIHBpdm90CiogQHJldHVybiB0aGUgaW5kZXggd2hlcmUgdGhlIHBpdm90IGVsZW1lbnQgc2hvdWxkIGJlIGluc2VydGVkCiovCnRlbXBsYXRlIDxjbGFzcyBJdGVyYXRvcj4gdm9pZCBxdWlja3NvcnQgKEl0ZXJhdG9yIGlGcm9tLCBJdGVyYXRvciBpVG8pIHsKCWludCBzaXplID0gaVRvLWlGcm9tOwoJLy9jb3V0IDw8IHByZWZpeCA8PCAicXVpY2tzb3J0aW5nICIgPDwgc2l6ZSA8PCAiIGVsZW1lbnRzOiAiOyBwcmludChpRnJvbSwgaVRvKTsKCWlmIChzaXplPD0xKSByZXR1cm47CglJdGVyYXRvciBwaXZvdCA9IGlGcm9tK3JhbmQoKSVzaXplOwoJSXRlcmF0b3IgcGl2b3RBZnRlclBhcnRpdGlvbiA9IHBhcnRpdGlvbihpRnJvbSwgaVRvLTEsICpwaXZvdCk7CgkvL2NvdXQgPDwgcHJlZml4IDw8ICJwYXJ0aXRpb25pbmcgYnkgIiA8PCAqcGl2b3QgPDwgIiBhdCBwbGFjZSAiIDw8IChwaXZvdEFmdGVyUGFydGl0aW9uLWlGcm9tKSA8PCBlbmRsOwoJaWYgKHBpdm90QWZ0ZXJQYXJ0aXRpb249PWlGcm9tKSB7IC8vIHBpdm90IGlzIG1pbmltdW0KCQlxdWlja3NvcnQoaUZyb20rMSwgaVRvKTsKCX0gZWxzZSBpZiAocGl2b3RBZnRlclBhcnRpdGlvbj09aVRvKSB7IC8vIHBpdm90IGlzIG1heGltdW0KCQlxdWlja3NvcnQoaUZyb20sIGlUby0xKTsKCX0gZWxzZSB7CgkJcXVpY2tzb3J0KGlGcm9tLCBwaXZvdEFmdGVyUGFydGl0aW9uKTsKCQlxdWlja3NvcnQocGl2b3RBZnRlclBhcnRpdGlvbiAsIGlUbyk7Cgl9CgkvL2NvdXQgPDwgcHJlZml4IDw8ICItLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gIjsgcHJpbnQoaUZyb20sIGlUbyk7Cn0KCgovKiBmaW5kIHRoZSBlbGVtZW50IHdob3NlIHBvc2l0aW9uIGluIHRoZSBzb3J0ZXIgYXJyYXkgaXMgInJhbmsiIChyYW5rID49IDApICovCnRlbXBsYXRlIDxjbGFzcyBJdGVyYXRvcj4gSXRlcmF0b3IgaXRoRWxlbWVudChJdGVyYXRvciBpRnJvbSwgSXRlcmF0b3IgaVRvLCBpbnQgcmFuaykgewoJaW50IHNpemUgPSBpVG8taUZyb207CgkvL2NvdXQgPDwgcHJlZml4IDw8ICJxdWlja3NvcnRpbmcgIiA8PCBzaXplIDw8ICIgZWxlbWVudHM6ICI7IHByaW50KGlGcm9tLCBpVG8pOwoJaWYgKHJhbms+PXNpemUpIHsKCQlzdHJpbmdzdHJlYW0gZXJyb3I7CgkJZXJyb3IgPDwgInRyaWVkIHRvIGZpbmQgZWxlbWVudCAiIDw8IHJhbmsgPDwgIiBidXQgdGhlcmUgYXJlIG9ubHkgIiA8PCBzaXplIDw8ICIgZWxlbWVudHMhIjsKCQl0aHJvdyAoZXJyb3Iuc3RyKCkpOwoJfSBlbHNlIGlmIChzaXplPT0xKSB7CgkJcmV0dXJuIGlGcm9tOwoJfQoJSXRlcmF0b3IgcGl2b3QgPSBpRnJvbStyYW5kKCklc2l6ZTsKCUl0ZXJhdG9yIHBpdm90QWZ0ZXJQYXJ0aXRpb24gPSBwYXJ0aXRpb24oaUZyb20sIGlUby0xLCAqcGl2b3QpOwoJaW50IG51bUJlZm9yZVBpdm90ID0gcGl2b3RBZnRlclBhcnRpdGlvbi1pRnJvbTsKCWlmIChyYW5rIDwgbnVtQmVmb3JlUGl2b3QpCgkJcmV0dXJuIGl0aEVsZW1lbnQoaUZyb20sIHBpdm90QWZ0ZXJQYXJ0aXRpb24sIHJhbmspOwoJZWxzZQoJCXJldHVybiBpdGhFbGVtZW50KHBpdm90QWZ0ZXJQYXJ0aXRpb24sIGlUbywgcmFuay1udW1CZWZvcmVQaXZvdCk7Cn0KCgoKdGVtcGxhdGUgPGNsYXNzIEl0ZXJhdG9yPiB2b2lkIHByaW50IChJdGVyYXRvciBpRnJvbSwgSXRlcmF0b3IgaVRvKSB7Cglmb3IgKDsgaUZyb208aVRvOyArK2lGcm9tKSB7CgkJY291dCA8PCAqaUZyb20gPDwgIiAiOwoJfQoJY291dCA8PCBlbmRsOwp9Cgp0ZW1wbGF0ZSA8Y2xhc3MgSXRlcmF0b3I+IHZvaWQgYXNzZXJ0U29ydGVkKEl0ZXJhdG9yIGlGcm9tLCBJdGVyYXRvciBpVG8pIHsKCWZvciAoOyBpRnJvbTxpVG8tMTsgKytpRnJvbSkgewoJCWlmICgqaUZyb20gPiAqKGlGcm9tKzEpKSB7CgkJCWNlcnIgPDwgImFycmF5IGlzIG91dCBvZiBvcmRlcjogIiA8PCAqaUZyb20gPDwgIiA+ICIgPDwgKihpRnJvbSsxKSA8PCBlbmRsOwoJCX0KCX0KCWNvdXQgPDwgZW5kbDsKfQoKCgp2b2lkIGNoZWNrUGFydGl0aW9uKGludCBhcnJheVtdLCBpbnQgc2l6ZSwgaW50IHBpdm90KSB7CgkJCWNvdXQgPDwgImJlZm9yZTogIjsgcHJpbnQgKGFycmF5LCBhcnJheStzaXplKTsKCQkJaW50KiBwaXZvdEFmdGVyUGFydGl0aW9uID0gcGFydGl0aW9uKGFycmF5LCBhcnJheStzaXplLTEsIHBpdm90KTsKCQkJY291dCA8PCAiYWZ0ZXIgKHBvc2l0aW9uIG9mICI8PHBpdm90PDwiID0gIiA8PCAocGl2b3RBZnRlclBhcnRpdGlvbi1hcnJheSkgPDwgIik6ICI7IHByaW50IChhcnJheSwgYXJyYXkrc2l6ZSk7CgkJCS8vYXNzZXJ0U29ydGVkKGFycmF5LCBhcnJheStzaXplKTsKfQoKCnZvaWQgY2hlY2tRdWlja3NvcnQoaW50IGFycmF5W10sIGludCBzaXplKSB7CgkJCWNvdXQgPDwgImJlZm9yZTogIjsgcHJpbnQgKGFycmF5LCBhcnJheStzaXplKTsKCQkJcXVpY2tzb3J0KGFycmF5LCBhcnJheStzaXplKTsKCQkJY291dCA8PCAiYWZ0ZXI6ICI7IHByaW50IChhcnJheSwgYXJyYXkrc2l6ZSk7CgkJCWFzc2VydFNvcnRlZChhcnJheSwgYXJyYXkrc2l6ZSk7Cn0KCgp2b2lkIGNoZWNrSXRoRWxlbWVudChpbnQgYXJyYXlbXSwgaW50IHNpemUpIHsKCWZvciAoaW50IGk9MDsgaTxzaXplOyArK2kpIHsKCQljb3V0IDw8ICJFbGVtZW50ICMiIDw8IGkgPDwgIjogIiA8PCAoKml0aEVsZW1lbnQoYXJyYXksIGFycmF5K3NpemUsIGkpKSA8PCBlbmRsOwoJfQp9CgoKI2luY2x1ZGUgPHRpbWUuaD4KaW50IG1haW4oKSB7CgkJCXNyYW5kKHRpbWUoTlVMTCkpOwoJCQlpbnQgc2l6ZT0yMDsKCQkJaW50KiBhID0gbmV3IGludFtzaXplXTsKCQkJZm9yIChpbnQgaT0wOyBpPHNpemU7ICsraSkKCQkJCQkJCWFbaV0gPSByYW5kKCklMTAwOwoJCQljaGVja1BhcnRpdGlvbihhLCBzaXplLCByYW5kKCklMTAwKTsKCQkJY2hlY2tJdGhFbGVtZW50KGEsc2l6ZSk7CgkJCWNoZWNrUXVpY2tzb3J0KGEsIHNpemUpOwp9Cg==