Quick sort

The quick sort algorithm is an updated version of the merge sort algorithm with faster in-memory sorting capability. It is widely used in average-case as against worst-case scenarios. It is also efficient in terms of memory utilization, as it does not require the secondary vector when performing the merge operation. Quick sort can be accessed in R using functions such as sort (base) and quick sort (rje). It is also called partition-exchange sort. Like merge sort, quick sort also requires recursive implementation for effective execution.

The following is the three-step execution methodology of the quick sort algorithm for a given input vector V with n elements:

  1. Select the pivot or root element of the given input vector. The pivot element is used to partition the entire vector into two subvectors such that all the elements in the first vector or left vector are less than the pivot, and all the elements in the second vector or right vector are greater than or equal to the pivot. However, the elements within both the partitioned subvectors need not be sorted. Usually, the element with the median value is considered for pivot. However, in our algorithm, we have considered the last element as the pivot for the corresponding vector. The pivot is said to be best when the partitioned subvectors are of the same length, and worst when one of the subvectors is empty.
  2. Perform recursive sorting on each of the subvectors (excluding the pivot) obtained after the split.
  3. Join the first sorted subvector, the pivot, and the second sorted subvector to obtain the final sorted output.

The following R code implements the recursive form of the quick sort algorithm:

Quick_Sort <- function(V,n) { 
  if (n <= 1) return(V) 
  left <- 0 ##start from left prior first element 
  right <- n  ##start from rightmost element 
  v <- V[n] ## initialize last element as pivot element 
 
  ## Partition implementation 
  repeat { 
    while (left < n && V[left+1]  < v) left <- left+1 
    while (right > 1 && V[right-1] >= v) right <- right-1 
    if (left >= right-1) break 
    ## Swap elements 
    temp <- V[left+1] 
    V[left+1] <- V[right-1] 
    V[right-1] <- temp 
  } 
 
  ## Recursive implementation of Quick sort 
  if (left == 0) return(c(V[n], Quick_Sort(V[1:(n-1)],n=(n-1)))) 
  if (right == n) return(c(Quick_Sort(V[1:(n-1)],n=(n-1)), V[n])) 
  return( c(Quick_Sort(V[1:left],n=left), V[n],    Quick_Sort(V[(left+1):(n-1)],n=(n-left-1)))) 
}

The R code begins with initializing the left and right indices. The left index represents the position of an element prior to the first element in the vector, and the right index represents the position of the last element in the vector. Then, the last element is considered as the pivot element for the corresponding input vector. Consider the following numeric vector with 16 elements:

Quick sort

Figure 5.7: An example of a 16-elements numeric vector

Now, the left and right indices start moving inward under the repeat loop till the indices meet. The inner while loops checks for bounds along with the pivot element prior to updating the left and right indices. Subsequently, the elements are swapped such that all elements toward the left of the pivot are lower than the pivot element, and all the elements toward the right are higher than the pivot element. However, the elements within the left and right subvectors need not be ordered. Figure 5.8 illustrates the first swap iterations being performed under the repeat loop:

Quick sort

Figure 5.8: Illustration of swap iterations

Once the left index meets the right index, the repeat loop breaks, and the recursive implementation of quick sort begins. Here, the pivot element is correctly positioned, and the remaining elements within the left and right subvectors are subject to recursive sorting. Figure 5.9 illustrates the complete implementation of the quick sort algorithm:

Quick sort

Figure 5.9: Illustration of quick sort

Let's analyze the asymptote of the quick sort algorithm in detail based on the number of operations performed at each step. Consider an input vector V of length n. A total of n moves are required to complete the traversing of both the left and right indices, till they meet each other. The repeat loop can be executed at most n times, and the while loop can fail at most n times. Hence, the asymptote of partition based on the pivot element is θ(n).

Consider a worst-case scenario wherein one of the subvectors has no elements upon partitioning. If this scenario occurs at each partition step, then the asymptote of the algorithm becomes θ(n2). In our algorithm, the worst-case scenario is bound to happen only when the input vector possesses all the elements in the descending order. However, this situation can be minimized upon random selection of the pivot value.

Consider a best-case scenario wherein for each iteration (of the repeat loop), the pivot value partitions the vector into two equal subvectors. Such a perfect kind of pivot will result in log n levels of partitions and n levels of traversing (by the left and right indices), which corresponds to an asymptote of θ(nlog n).

Consider an average-case scenario. Here, the behavior of the partition is between the best and worst-case scenarios, and there is an equal likelihood for any type of subvector partition. The asymptote which satisfies the recurrence relation can be defined as follows:

Quick sort

Thus, the closed form solution for the average-case scenario is also θ(nlog n), which is similar to that of the best-case scenario.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.82.4