📜  Java快速排序实现各种类型的分区(1)

📅  最后修改于: 2023-12-03 15:32:03.458000             🧑  作者: Mango

Java快速排序实现各种类型的分区

快速排序是一种高效的排序算法,它采用分治策略,将原问题分解成多个子问题,然后分别解决,最后将子问题的解合并起来得到原问题的解。本文将介绍如何用Java实现快速排序,并实现对不同类型数据的分区。

快速排序基本思想

快速排序的基本思路是通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有元素都比另一部分的所有元素都小,然后再按此方法对这两部分分别进行快速排序,以达到整个序列有序的目的。

具体实现过程如下:

  1. 从数列中挑出一个元素,称为基准(pivot)。
  2. 根据基准元素把待排序列分成两个子序列,所有小于基准元素的放在左边,所有大于基准元素的放在右边。
  3. 分别对左右两个子序列进行递归排序,直到所有子序列的长度为1。
Java快速排序实现
代码片段

下面是Java快速排序的代码实现:

public static void quickSort(int[] arr, int left, int right) {
    if (left >= right) {
        return;
    }
    int i = left, j = right;
    int pivot = arr[left];
    while (i < j) {
        while (i < j && arr[j] >= pivot) {
            j--;
        }
        if (i < j) {
            arr[i++] = arr[j];
        }
        while (i < j && arr[i] <= pivot) {
            i++;
        }
        if (i < j) {
            arr[j--] = arr[i];
        }
    }
    arr[i] = pivot;
    quickSort(arr, left, i - 1);
    quickSort(arr, i + 1, right);
}
代码解释

快速排序的实现可以分为两个步骤:分区和递归排序。

分区

在分区时需要从待排序数组的左右两端 i 和 j 开始扫描,当 j 指向的元素大于等于基准元素时,一直向左移动 j。当 i 指向的元素小于等于基准元素时,一直向右移动 i。如果 i<j 说明左右两端的元素没有交叉,交换 arr[i] 和 arr[j] 的位置即可。

int i = left, j = right;
int pivot = arr[left];
while (i < j) {
    while (i < j && arr[j] >= pivot) {
        j--;
    }
    if (i < j) {
        arr[i++] = arr[j];
    }
    while (i < j && arr[i] <= pivot) {
        i++;
    }
    if (i < j) {
        arr[j--] = arr[i];
    }
}
arr[i] = pivot;

递归排序

分区结束后需要对左右两个子数组进行递归排序,直到子序列长度为1。

quickSort(arr, left, i - 1);
quickSort(arr, i + 1, right);
不同数据类型的分区实现

不同类型的数据在快速排序的实现上有一些不同之处。

整型数组

对于整型数组,我们可以采用与快排基础实现相同的方式进行分区。

public static void quickSort(int[] arr, int left, int right) { /*省略代码*/ }
字符串数组

对于字符串数组,我们需要对比较算法进行改进,将比较字符串的方式从 compareTo() 换成了 compareToIgnoreCase() ,使其忽略大小写。

public static void quickSort(String[] arr, int left, int right) {
    /*省略代码*/
    int i = left, j = right;
    String pivot = arr[left];
    while (i < j) {
        while (i < j && arr[j].compareToIgnoreCase(pivot) >= 0) {
            j--;
        }
        if (i < j) {
            arr[i++] = arr[j];
        }
        while (i < j && arr[i].compareToIgnoreCase(pivot) <= 0) {
            i++;
        }
        if (i < j) {
            arr[j--] = arr[i];
        }
    }
    arr[i] = pivot;
    quickSort(arr, left, i - 1);
    quickSort(arr, i + 1, right);
}
自定义类型

对于自定义类型,我们需要实现 Comparable 接口,并在 compareTo() 方法中指定排序规则。

public class Person implements Comparable<Person> {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public int compareTo(Person p) {
        if (age > p.age) {
            return 1;
        } else if (age < p.age) {
            return -1;
        } else {
            return name.compareTo(p.name);
        }
    }

    public String toString() {
        return name + ":" + age;
    }
}

在排序时直接调用 Arrays.sort() 方法即可。

Person[] arr = new Person[3];
arr[0] = new Person("Tom", 18);
arr[1] = new Person("Jerry", 20);
arr[2] = new Person("Lisa", 18);
Arrays.sort(arr);
总结

快速排序是一种高效的排序算法,通过递归的分治策略能够在最坏情况下达到 O(nlogn) 的时间复杂度。不同的数据类型需要采用不同的分区策略,可以通过实现 Comparable 接口来指定排序规则。