快速排序原理:分治法,快速排序在每一轮挑选一个基准元素,比它大的在一边,比它小的在另一变,拆解成两部分。双边循环法和单边循环法实现。

    1. package com.algorithm.sort;
    2. import java.util.Arrays;
    3. /**
    4. * 快速排序原理:分治法,快速排序也属于交换排序,快速排序在每一轮挑选一个基准元素,并让其他比它大的元素移动到数列一边,比它小的元素移动到数列
    5. * 的另一边,从而把数列拆解成两个部分。基准元素、比基准元素大的元素、比基准元素小的元素 这种思路叫分治法
    6. * <p>
    7. * 双边循环法:left 和 right 左右两个指针分别指向数列的最左和最右,从right指针开始>=基准元素 向左移动,< 基准元素right停止移动 进行数据交换,
    8. * 切换到left指针,如果 <= 基准元素 left指针向右移动,否则left指针停止移动 进行数据交换。
    9. * 如果left和right 两个指针重合则将该位置的数据和基准元素进行交换。 实现了左右两侧 分治
    10. */
    11. public class FastSort {
    12. public static void main(String[] args) {
    13. int[] arr = new int[]{4, 4, 6, 5, 3, 2, 8, 1};
    14. FastSort.quickSort(arr, 0, arr.length - 1);
    15. System.out.println(Arrays.toString(arr));
    16. }
    17. /**
    18. * 单边循环分治法
    19. * 1. 选定基准元素
    20. * 2. mark 指针表示小于基准元素的区域边界
    21. * 如果遍历的元素大于基准元素,继续向后遍历。
    22. * 如果遍历的元素小于基准元素,把mark指针右移动一位,因为小于基准元素的区域增大了;遍历到的元素和mark指针所在的位置进行交换,遍历到的元素
    23. * 归属于小于基准元素的区域。
    24. * 最后将基准元素和mark指针所在的位置进行交换,实现了分治
    25. *
    26. * @param arr
    27. * @param startIndex
    28. * @param endIndex
    29. */
    30. private static int partition2(int[] arr, int startIndex, int endIndex) {
    31. int pivot = arr[startIndex];
    32. int mark = startIndex;
    33. for (int i = startIndex + 1; i <= endIndex; i++) {
    34. if (arr[i] < pivot){
    35. mark++;
    36. int temp = arr[mark];
    37. arr[mark] = arr[i];
    38. arr[i] = temp;
    39. }
    40. }
    41. //基准元素和mark位置交换
    42. arr[startIndex] = arr[mark];
    43. arr[mark] = pivot;
    44. return mark;
    45. }
    46. public static void quickSort(int[] arr, int startIndex, int endIndex) {
    47. if (startIndex >= endIndex) return;
    48. //得到基准元素的位置
    49. int pivotIndex = partition2(arr, startIndex, endIndex);
    50. //根据基准元素分成两部分进行递归排序
    51. //小于基准元素的 进行分治排序
    52. quickSort(arr, startIndex, pivotIndex - 1);
    53. //大于基准元素的 进行分治排序
    54. quickSort(arr, pivotIndex + 1, endIndex);
    55. }
    56. /**
    57. * 分治:双边循环法
    58. *
    59. * @param arr
    60. * @param startIndex
    61. * @param endIndex
    62. * @return
    63. */
    64. private static int partition(int[] arr, int startIndex, int endIndex) {
    65. int pivot = arr[startIndex];
    66. int left = startIndex;
    67. int right = endIndex;
    68. while (left != right) {
    69. //控制right指针比较并左移动
    70. while (left < right && arr[right] > pivot) {
    71. right--;
    72. }
    73. while (left < right && arr[left] <= pivot) {
    74. left++;
    75. }
    76. //交换元素
    77. if (left < right) {
    78. int p = arr[left];
    79. arr[left] = arr[right];
    80. arr[right] = p;
    81. }
    82. }
    83. //指针发生重合
    84. arr[startIndex] = arr[left];
    85. arr[left] = pivot;
    86. //一轮循环结束 返回基准元素的位置
    87. return left;
    88. }
    89. }