五、java代码实现快速排序

快速排序思路

  • ①、每一轮排序选择一个基准点进行分区
    让小于基准点的元素进入一个分区,大于基准点的元素进入另一个分区
    当分区完成时,基准点元素的位置就是其最终的位置

  • ②、在子分区内重复以上过程,直至子分区元素个数少于等于1(分治算法)

代码实现(单边循环快排)

  • ①、选择最右边元素作为基准点元素
  • ②、j指针负责找到比基准点小的元素,一旦找到则与i进行交换
  • ③、i指针维护小于基准点元素的边界,也是每次交换的目标索引
  • ④、最后基准点与i交换,i即为分区位置
import java.util.Arrays;

public class Testjava2 {
    public static void main(String[] args) {
        int[] a = {5, 1, 3, 2, 4, 9, 8, 7, 0};
        quick(a, 0, a.length - 1);
    }

    public static void quick(int[] a, int l, int h) {
        if (h <= l) {
            // 当分区只有一个元素的时候 说明已经有序 结束递归
            return;
        }
        int p = partition(a, l, h); // 基准点索引值
        quick(a, l, p - 1); // 左边分区 范围确定
        quick(a, p + 1, h); // 右边分区 范围确定
    }

    /**
     * @param a 待排序数组
     * @param l 左边界
     * @param h 基准点
     * @return 基准点元素所在的正确索引,用它确定下一轮分区的边界
     */
    public static int partition(int a[], int l, int h) {
        int pv = a[h]; // 基准点元素
        int i = l;  // 基准点元素所在的正确索引
        for (int j = l; j < h; j++) {
            if (a[j] < pv) {
                if (i != j) {
                    swap(a, i, j);
                }
                i++;
            }
        }
        // 交换基准点元素
        if (i != h) {
            swap(a, h, i);
        }
        System.out.println(Arrays.toString(a) + "  " + i);
        return i;
    }

    // 交换元素方法
    public static void swap(int[] a, int i, int j) {
        int temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }
}

代码实现(双边循环快排)

  • ①、选择最左边元素作为基准点元素
  • ②、j指针负责从右向左找比基准点小的元素,i指针负责从左往右找比基准点大的元素,一旦找到则交换,直至i,j相交
  • ③、最后基准点与i(此时i与j相等)交换,i即为分区位置
import java.util.Arrays;

public class Testjava3 {
    public static void main(String[] args) {
        int[] a = {5, 1, 3, 2, 4, 9, 8, 7, 0};
        quick(a, 0, a.length - 1);
    }

    public static void quick(int[] a, int l, int h) {
        if (h <= l) {
            // 当分区只有一个元素的时候 说明已经有序 结束递归
            return;
        }
        int p = partition(a, l, h); // 基准点索引值
        quick(a, l, p - 1); // 左边分区 范围确定
        quick(a, p + 1, h); // 右边分区 范围确定
    }

    /**
     * 双边循环
     *
     * @param a 待排序数组
     * @param l 左边界
     * @param h 基准点
     * @return 基准点元素所在的正确索引,用它确定下一轮分区的边界
     */
    public static int partition(int a[], int l, int h) {
        int pv = a[l]; // 基准点元素
        int i = l;  // 基准点元素所在的正确索引
        int j = h;
        while (i < j) {
        	// 必须先从右往左找 再从左往右找
            // j从右找比基准点小的元素
            while (i < j && a[j] > pv) {
                j--;
            }
            // i从左找比基准点大的元素
            while (i < j && a[i] <= pv) {
                i++;
            }
            swap(a, i, j);
        }
        // 交换基准点元素
        swap(a, l, j);
        System.out.println(Arrays.toString(a) + " " + j);
        return j;
    }

    // 交换元素方法
    public static void swap(int[] a, int i, int j) {
        int temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }

}

你可能感兴趣的:(算法知识,java,算法,开发语言)