学习Java中快速排序算法的实现

125 阅读4分钟

在这篇文章中,我们将学习Java中快速排序算法的实现。

目录:

  1. 快速排序的工作原理
  2. 算法
  3. 使用Naive分区的Jave代码
  4. 使用Hoare分区的Java代码
  5. 使用Lomuto分区的Java代码
  6. 实施的详细解释
  7. Java中的Arrays.sort
  8. 常见问题

快速排序的工作原理

快速排序是一种基于分而治之方法的排序算法。让我们简单了解一下快速排序算法的工作原理。

1.枢轴元素的选择
最重要的事情是选择数组中的枢轴元素。现在,这可以通过两种方式完成:
*Naive partition。*在这种情况下,任何元素都可以被选为支点,但需要O(n)的额外空间。
*Hoare分区。*在这种情况下,第一个元素被选为支点。枢轴元素并不保持在固定位置,它只是对数组进行分割。
Lomuto分割
法。
在这种情况下,最后一个元素被选为支点。遍历只做一次,空间复杂度不变。

2.重新排列数组
阵列被重新排列,小于支点的元素被放在左边,大于支点的元素被放在支点的右边。

3.分割子数组
阵列重新排列后,再次选择支点元素,重复步骤2,直到阵列完全排序。

算法

1步:开始
第2步:根据你想要的分区类型选择支点,天真分区以索引为基础,Hoare分区以第一个元素为基础,Lomuto分区以最后一个元素为基础。
第3步:现在取两个变量表示阵列的左边和右边,不包括支点。
3
步:继续向右移动,直到左边的元素小于支点。
4步:继续向左移动,直到右边的元素大于支点。
第5步:如果第4步和第5步不匹配,那么简单地交换左边和右边。
第6步:如果左边大于或等于右边,那么它们的交汇点就成为新支点。
第7步:停止。

因此,对于实现部分,我们将创建一个Java类,其成员方法包括int partition()void quick_sort()void main()。让我们探讨一下int partition()方法,它的返回类型是int,因为它将在每次执行后返回枢纽元素的位置。现在,void quick_sort实际上是根据partition方法返回的枢轴,在数组的两半上执行快速排序算法。在main方法中,我们只是创建了一个数组,并调用这些方法对数组按升序排序。

使用Naive partition的Java代码

public class Opengenus_QuickSort_NaivePartition {
public int partition(int[] arr, int low, int high) {
    int temp[] = new int[(high - low) + 1];
    int pivot = arr[high];
    int index = 0;

    // smaller number
    for (int i = low; i <= high; ++i) {
        if (arr[i] < pivot) {
            temp[index++] = arr[i];
        }
    }
    int pos = index;
    temp[index++] = pivot;

    for (int i = low; i <= high; ++i) {
        if (arr[i] > pivot) {
            temp[index++] = arr[i];
        }
    }
    for (int i = low; i <= high; ++i) {
        arr[i] = temp[i - low];
    }
    return pos;
}
public void quick_sort(int[] arr, int l, int h){
    if(l < h){
        int pivot = partition(arr, l, h);
        quick_sort(arr, l, pivot - 1);
        quick_sort(arr, pivot+1, h);
    }
}
public static void main(String[] args){
    int[] arr = {0, 5, 16, 10, 9, 8, 12};
    Opengenus_QuickSort_NaivePartition obj = new Opengenus_QuickSort_NaivePartition();
    obj.quick_sort(arr, 0, 6);
    System.out.print("Sorted Array: ");
    for(int i = 0 ; i < arr.length ; i++)
        System.out.print(arr[i] + " ");
}
}

输出

Sorted Array: 0 5 8 9 10 12 16 

就像Naive的实现一样,这里我们有int partition_Hoare和*void quick_sort()*方法,分别返回pivot索引和执行快速排序。唯一不同的是,这里我们选择了第一个元素作为枢纽元素。

使用Hoare分区的Java代码

public class Opengenus_QuickSort_HoarePartition {
public int partition_Hoare(int[] arr, int low, int high) {
    int pivot = arr[low];
    int i = low - 1, j = high + 1;
    while (true) {
        do {
            i++;
        } while (arr[i] < pivot);
        do {
            j--;
        } while (arr[j] > pivot);
        if (i >= j)
            return j;
        // swapping the two values
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}

public void quick_sort(int[] arr, int l, int h){
    if(l < h){
        int pivot = partition_Hoare(arr, l, h);
        quick_sort(arr, l, pivot);
        quick_sort(arr, pivot+1, h);
    }
}
public static void main(String[] args){
    int[] arr = {0, -5, 16, 10, 9, 8, 12};
    Opengenus_QuickSort_HoarePartition obj = new Opengenus_QuickSort_HoarePartition();
    obj.quick_sort(arr, 0, 6);
    System.out.print("Sorted Array: ");
    for(int i = 0 ; i < arr.length ; i++)
        System.out.print(arr[i] + " ");
}
}

输出

Sorted Array: -5 0 8 9 10 12 16 

就像Naive实现一样,这里我们有int partition_Lomuto和*void quick_sort()*方法,分别返回支点索引和执行快速排序。唯一的区别是,这里我们把最后的第一个元素作为枢轴元素。

使用Lomuto分区的Java代码

public class Opengenus_QuickSort_LomutoPartition {
public int lomuto_partition(int[] arr, int low, int high){
    int pivot = arr[high];
    int i = low - 1;
    for(int j = low; j <= high - 1; j++){
        if(arr[j] < pivot){
            i++;
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
    }
    int temp = arr[i+1];
    arr[i+1] = arr[high];
    arr[high] = temp;
    return i+1; // returning index of the pivot element
}
public void quick_sort(int[] arr, int l, int h){
    if(l < h){
        int pivot = lomuto_partition(arr, l, h);
        quick_sort(arr, l, pivot - 1);
        quick_sort(arr, pivot+1, h);
    }
}
public static void main(String[] args){
    int[] arr = {0, 5, 16, 10, 9, 8, 12};
    Opengenus_QuickSort_LomutoPartition obj = new Opengenus_QuickSort_LomutoPartition();
    obj.quick_sort(arr, 0, 6);
    System.out.print("Sorted Array: ");
    for(int i = 0 ; i < arr.length ; i++)
        System.out.print(arr[i] + " ");
}
}

输出

Sorted Array: 0 5 8 9 10 12 16 

实施的详细解释

让我们用一个例子来深入了解一下实现方法,假设我们有一个元素为8,4,7,9,3,10,5的数组,使用Lomuto的分割法对数组进行排序。

Untitled-3

以上显示的快速排序工作可以与二进制树相关,其中枢轴元素的索引是根,Quick_Sort(arr,l,p-1)代表左子树,Quick_Sort(arr,p+1,h)代表右子树。
我们看到,在上述给定的树中,每次递归调用后,都会从堆栈中返回值,然后阵列最终按非递减顺序进行排序。

Java中的Arrays.sort

Array是一个内建的java类,用于对数组进行搜索、排序、比较和插入操作。sort()Arrays类中的一个方法,用于对数组进行非递减排序。它使用快速排序算法对数组元素进行排序。下面是它的实现:

import java.util.Arrays;

public class Opengenus_Arrays_Demo {
public static void main(String[] args){
    int[] arr = {8, 4, 7, 9, 3, 10, 5};
    Arrays.sort(arr);
    System.out.println("Sorted Array: ");
    for(int i = 0 ; i < 7 ; i++){
        System.out.print(arr[i] + " ");
    }
}
}

输出:

Sorted Array: 
3 4 5 7 8 9 10