Quick Sort Quick Sort Algorithm

Table of Contents

  1. Foreword
  2. Algorithm steps
  3. Select the hub yuan
  4. Striped array
  5. Algorithm
  6. Small arrays and insertion sort
  7. Epilogue

Foreword

A quick sort algorithm should be the most common sorting algorithm used in many languages ​​built-in sorting algorithms are direct or indirect use of this algorithm.

Therefore, it is necessary that we learn fast sorting algorithm.

Algorithm steps

Before looking at the detailed algorithm steps we can first look at the quick sort algorithm complexity of the algorithm:

Time complexity (average) Time complexity (worst) Space complexity
$ O (nlog_2n) $ $ O (n ^ 2) $ $ O (1) $

By the algorithm complexity of quick sort algorithm, we can guess that it might be a divide and conquer algorithm, but the fact is true.

When sorting algorithm by flash array \ (A \) when sorting, we need to be recursively processed into different sections, the basic steps of:

  1. If the array \ (A \) the number of elements is 1 or 0, the direct return
  2. Array Select \ (A \) of any element \ (P \) as the hub element
  3. The array \ (A \) elements divided into two parts: all elements less \ (P \) portion \ (A_1 \) and all elements greater than or equal \ (P \) portion \ (A_2 \)
  4. Back [ \ (the QuickSort (A_1) \) , \ (P \) , \ (the QuickSort (A_2) \) ]

You can see, the basic steps fast sorting algorithm is not difficult to realize the main problem with this algorithm to consider is the hub yuan selection and how to split an array.

Select the hub yuan

Common hub yuan choice is probably the way to select the array middle of that element, straightforward and effective.

After selecting the hub element, typically it requires values at both ends and the hub element sort, which can slightly increase the efficiency of the algorithm and to avoid unforeseen circumstances 1 :

public static int selectPivot(int[] arr, int left, int right) {  // 包含右边界
  int mid = (left + right) / 2;

  if (arr[left] > arr[mid]) {
    swap(arr, left, mid);
  }

  if (arr[left] > arr[right]) {
    swap(arr, left, right);
  }

  if (arr[mid] > arr[right]) {
    swap(arr, mid, right);
  }

  /* arr[left] <= arr[mid] <= arr[right] */

  swap(arr, mid, right - 1);

  return arr[right - 1];
}

After the values are sorted at both ends and the hub element, the leftmost value must be less than or equal to the value at the hub element, the value must be the rightmost element at the hub of greater than or equal value, then we need to split array will become [left + 1, right - 1].

Then, the dollar and exchange hub right - 1element at that hub yuan leave the array to be divided in 2 , then, we need to split the array will become [left + 1, right - 2].

Introduced over common practice, not here introduce a common approach and a common mistake in practice:

  • The hub is a randomly selected element is not common practice, because the cost of generating a random number value is compared to a calculated cost much more expensive
  • Directly select a first element as a hub element is a common mistake, when the input array is pre-sorted, all the elements will be assigned to a single group, and continue recursively, so that the time complexity becomes \ ( O (n ^ 2) \)

Striped array

When splitting array, necessary to first select the element and the end of the hub element exchange position, and then from left to right traversal of all the elements is less than the hub elements, all the elements greater than the right to left traverse hub membered, or greater than when both met when the hub yuan less than the elemental stop, then exchanging elements encountered, then continue to traverse until staggered:

        初始状态:
            8  1  4  9  0  3  5  2  7  6
            i                       j  p

        交换前:
            8  1  4  9  0  3  5  2  7  6
            i                    j     p

        交换后:
            2  1  4  9  0  3  5  8  7  6
            i                    j     p

After interleaving the ielements at the end of the hub element and exchanged, this time, the left element hub element which are less than or equal, the elements are greater than or equal to the right it:

        交错后:
            2  1  4  5  0  3  9  8  7  6
                           j  i        p

        交换后:
            2  1  4  5  0  3  6  8  7  9
                              i        p

A traversal issue to be considered is: encountered and hub yuan equal elements how to deal with? It is stopped or not stopped?

Elements of the input assumptions are equal, we look at the last possible two strategies:

        都停止:
            8  8  8  8  8  8  8  8  8
                     j  i           p

        都不停止:
            8  8  8  8  8  8  8  8  8
            i                    j  p

When you can see, the use of all stop strategy, although it will produce some unnecessary exchange, but not stopped, it will split the array of extremely uneven, which would make the time complexity is very high.

Therefore, a better choice is in the face and hub yuan equal elements are stopped.

Algorithm

In determining the method of selecting an array of segmentation strategy and hub yuan, you can try to achieve a quick-sort algorithm:

public static void quickSort(int[] arr) {
  quickSort(arr, 0, arr.length - 1);
}

public static void quickSort(int[] arr, int left, int right) {  // 包含右边界
  if  (left >= right) {  // 元素小于等于 1 个
    return;
  }

  int i = left, j = right - 1, pivot = selectPivot(arr, left, right);

  while (i < j) {
    while (arr[++i] < pivot) {}
    while (arr[--j] > pivot) {}

    if (i < j) {
      swap(arr, i, j) ;
    }
  }

  swap(arr, i, right - 1);

  quickSort(arr, left, i - 1);
  quickSort(arr, i + 1, right);
}

public static int selectPivot(int[] arr, int left, int right) {
  int mid = (left + right) / 2;

  if (arr[left] > arr[mid]) {
    swap(arr, left, mid);
  }

  if (arr[left] > arr[right]) {
    swap(arr, left, right);
  }

  if (arr[mid] > arr[right]) {
    swap(arr, mid, right);
  }

  /* arr[left] <= arr[mid] <= arr[right] */

  swap(arr, mid, right - 1);

  return arr[right - 1];
}

public static void swap(int[] arr, int i, int j) {
  int tmp = arr[i];
  arr[i] = arr[j];
  arr[j] = tmp;
}

Algorithm implementation is not difficult, but it should be noted that a piece of code is:

while (i < j) {
  while (arr[++i] < pivot) {}
  while (arr[--j] > pivot) {}

  if (i < j) {
    swap(arr, i, j) ;
  }
}

If this code will be modified in the following form, it will make in the face of arr[i] = arr[j] = pivotthe situation into an infinite loop:

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

  if (i < j) {
    swap(arr, i, j) ;
  }
}

Small arrays and insertion sort

Quick sort performance in a small array not as good insertion sort, therefore, when implementing quick sort, often smaller array will be sorted by insertion sort, such as OpenJDK implementation of this is.

Achieve improved as follows:

public static void insertSort(int[] arr, int left, int right) {  // 包含右边界
  for (int p = left + 1; p <= right; p++) {
    int tmp = arr[p];
    for (int j = p; j > left && arr[j - 1] > tmp; j--) {
      arr[j] = arr[j - 1];
    }
    arr[j] = tmp;
  }
}

public static void quickSort(int[] arr) {
  quickSort(arr, 0, arr.length - 1);
}

public static void quickSort(int[] arr, int left, int right) {
  if  (left + 20 >= right) {  // 小数组
    insertSort(arr, left, right);
    return;
  }

  int i = left, j = right - 1, pivot = selectPivot(arr, left, right);

  while (i < j) {
    while (arr[++i] < pivot) {}
    while (arr[--j] > pivot) {}

    if (i < j) {
      swap(arr, i, j) ;
    }
  }

  swap(arr, i, right - 1);

  quickSort(arr, left, i - 1);
  quickSort(arr, i + 1, right);
}

Epilogue

Most of the contents of this blog are derived from the "data structure and algorithm analysis - C language description," a book of 7.7 Festival, are interested can take a look @ _ @

Footnotes

1 unexpected situations Reference - Problem of the book "Analysis of data structures and algorithms described in the C language" 7.38

2 I did not get the reason and explanation of this practice, just know that this approach allows a striped array safer (to avoid making mistakes or inefficiencies)

Guess you like

Origin www.cnblogs.com/rgbit/p/11069585.html