1

there is a lot of info on StackOverflow but I couldn't exactly figure it out the way I need it.

I'm trying to implement a quickSelect algorithm with a median of medians but not exactly making it work.

the algorithm is supposed to find the i-th smallest element in the array with the input of n>1 elements using these steps :

  1. if n==1 return the element in the array.

  2. divide the n elements in the array into groups of "groupSize" and one more group of "groupSize" -1 elements at most. the original algorithm is groups of 5 but i want it to be modular.

  3. find the median of each of the (ceiling value) of n/groupSize by using insertion sort and picking the median of the sort sub-array.

  4. call Select recursively to find the median "x" of ceiling value n/groupSize medians found in step 3. given that number of medians is even - "x" would be the bottom median.

  5. this is the part i found trickiest - divide the input array around the median of medians "x" using partition (possibly hoare-parititon). place in k the number of elements in the lower area of the partition so "x" would be the k-th smallest element and the upper are of the partition will hold n-k elements.

  6. if i=k return "x" , if i<k call Select recursively to find the i-th smallest element in the lower sub-array, if i>k call select to find the (i-k) smallest in the upper sub-array.

i don't exactly know how to execute section 5 and i feel this is the part that figures everything here

this is my Select

    if(right-left+1==1) return array[left];
    // full steps are the count of full groups in size of groupSize(left of decimal point)
    int fullSteps = array.length/groupSize;
    int semiSteps = (int)((double)(array.length)%groupSize);
    int i;
    //array of medians is the size of number of groups needed
    int medianArraySize = (int) Math.ceil (((double)(array.length))/groupSize);
    int [] medianArray = new int [medianArraySize];
    print(medianArray);
    // sort the entire array by cutting it to chunks of defined size
        for(i=0;i<medianArraySize;i++){
            insertionSort(array, i*groupSize,i*groupSize+groupSize);
            //place the median of sorted sub-array into median array in place i
            medianArray[i]=findMidean(array, i*groupSize, i*groupSize+groupSize);
            //implement insertion sort on full groups to find median - ceilling value
        }
        int medianOfMedians = select(medianArray,0,medianArraySize-1,groupSize,medianArray[(medianArraySize-1)/2]);
        //find median of medians without using recursion
//        int medianOfMedians = medianArray[(medianArraySize-1)/2];
        //   System.out.println("median of medians is :" +medianOfMedians);

        int pivot = hoarePartition(array,left,right,medianOfMedians);
        int k = left-pivot +1;
        if (pivot==k-1) return array[pivot];
        else
            if (pivot<k-1) return select(array,pivot +1,right,groupSize,ithSmallest);
        else return select(array,left,pivot-1,groupSize,ithSmallest-k);

    }

helper function - find median

*
 * returns the median value for the desginated range in given array.
 */
private static int findMidean(int [] array,  double start,int end){
    int stopper = Math.min(array.length,end);
    int index =(int)(Math.ceil(start+stopper-1)/2.0);
    return array[index];
}

partition algorithm

public static int hoarePartition(int[] arr, int low, int high,int pivot)
    {
        int i = low, j = high;

        while (true) {
            // Find leftmost element greater
            // than or equal to pivot

            while (i<j && arr[i] < pivot){
                i++;
            }

            // Find rightmost element smaller
            // than or equal to pivot
            while (j>i && arr[j] > pivot){
                j--;
            }
            // If two pointers met.
            if (i >= j)
                return j;
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
            // swap(arr[i], arr[j]);
        }
    }

and insertion sort

public static void insertionSort(int [] arr,int placeHolder,int end)
    {
        int stopper = Math.min(arr.length,end);
        for (int i = placeHolder; i < stopper; ++i) {
            int key = arr[i];
            int j = i - 1;
            /* Move elements of arr[0..i-1], that are
               greater than key, to one position ahead
               of their current position */
            while (j >= 0 && arr[j] > key) {
                arr[j + 1] = arr[j];
                j = j - 1;
            }
            arr[j + 1] = key;
        }
    }

1 Answers1

0

If Hoare partition scheme is used, then the pivot and all elements equal to the pivot can end up anywhere. This means the case of i == k can't be used, and instead quickselect will have to recursively call itself until the base case of a single element is reached.

If Lomuto partition scheme is used, then the pivot is put in place and the index of the pivot is returned, so the i == k case can be used.

rcgldr
  • 27,407
  • 3
  • 36
  • 61