问题
I've been poring over various tutorials and articles that discuss quicksort and quickselect, however my understanding of them is still shaky.
Given this code structure, I need to be able to grasp and explain how quickselect works.
// return the kth smallest item
int quickSelect(int items[], int first, int last, int k) {
int pivot = partition(items, first, last);
if (k < pivot-first) {
return quickSelect(items, first, pivot, k);
} else if (k > pivot) {
return quickSelect(items, pivot+1, last, k-pivot);
} else {
return items[k];
}
}
I need a little help with breaking down into pseudo-code, and while I haven't been provided with the partition function code, I'd like to understand what it would do given the quickselect function provided.
I know how quicksort works, just not quickselect. The code I just provided is an example we were given on how to format quick select.
EDIT: The corrected code is
int quickSelect(int items[], int first, int last, int k)
{
int pivot = partition(items, first, last);
if (k < pivot-first+1)
{ //boundary was wrong
return quickSelect(items, first, pivot, k);
}
else if (k > pivot-first+1)
{//boundary was wrong
return quickSelect(items, pivot+1, last, k-pivot);
}
else
{
return items[pivot];//index was wrong
}
}
Courtesty: @Haitao
回答1:
The important part in quick select is partition. So let me explain that first.
Partition in quick select picks a pivot
(either randomly or first/last element). Then it rearranges the list in a way that all elements less than pivot
are on left side of pivot and others on right. It then returns index of the pivot
element.
Now here we are finding kth smallest element. After partition cases are:
k == pivot
. Then you have already found kth smallest. This is because the way partition is working. There are exactlyk - 1
elements that are smaller than thekth
element.k < pivot
. Then kth smallest is on the left side ofpivot
.k > pivot
. Then kth smallest is on the right side of pivot. And to find it you actually have to findk-pivot
smallest number on right.
回答2:
btw, your code has a few bugs..
int quickSelect(int items[], int first, int last, int k) {
int pivot = partition(items, first, last);
if (k < pivot-first+1) { //boundary was wrong
return quickSelect(items, first, pivot, k);
} else if (k > pivot-first+1) {//boundary was wrong
return quickSelect(items, pivot+1, last, k-pivot);
} else {
return items[pivot];//index was wrong
}
}
回答3:
Partition is pretty simple: it rearranges the elements so those less than a selected pivot are at lower indices in the array than the pivot and those larger than the pivot are at higher indices in the array.
I talked about the rest it in a previous answer.
回答4:
int quickSelect(int A[], int l, int h,int k)
{
int p = partition(A, l, h);
if(p==(k-1)) return A[p];
else if(p>(k-1)) return quickSelect(A, l, p - 1,k);
else return quickSelect(A, p + 1, h,k);
}
// partition function same as QuickSort
回答5:
int partition(vector<int> &vec, int left, int right, int pivotIndex)
{
int pivot = vec[pivotIndex];
int partitionIndex = left;
swap(vec[pivotIndex],vec[right]);
for(int i=left; i < right; i++) {
if(vec[i]<pivot) {
swap(vec[i],vec[partitionIndex]);
partitionIndex++;
}
}
swap(vec[partitionIndex], vec[right]);
return partitionIndex;
}
int select(vector<int> &vec, int left, int right, int k)
{
int pivotIndex;
if (right == left) {
return vec[left];
}
pivotIndex = left + rand() % (right-left);
pivotIndex = partition(vec,left,right,pivotIndex);
if (pivotIndex == k) {
return vec[k];
} else if(k<pivotIndex) {
/*k is present on the left size of pivotIndex*/
return partition(vec,left,pivotIndex-1, k);
} else {
/*k occurs on the right size of pivotIndex*/
return partition(vec, pivotIndex+1, right, k);
}
return 0;
}
来源:https://stackoverflow.com/questions/10846482/quickselect-algorithm-understanding