快排 java_快速排序 java实现 (原理-优化) 三路快排

一、基本的快速排序

在数组中选取一个元素为基点,然后想办法把这个基点元素移动到它在排好序后的最终位置,使得新数组中在这个基点之前的元素都小于这个基点,而之后的元素都大于这个基点,然后再对前后两部分数组快速排序,直到数组排序完成。

ac2ed5ec8759a8f00e047fe080bee1a3.png

代码实现:

public void quickSorted ( intarr[] ) {int n = arr.length - 1; //闭区间 [0...n]

__quickSorted (arr, 0, n);

}private __quickSorted( int arr[], int L, intR) {if ( (L >=R) {return;

}//将基点移动到最终位置的方法

int p =__partioner(arr, L, R);//递归拆分数组

__quickSorted(arr, L, p - 1);

__quickSorted(arr, p+ 1, R);

}

那么最大的问题就是怎么把这个基点移动到它最终应该所在的位置。

81f93fcd34bbfbd69c98c5d6314bd254.png

代码实现:

private int __partioner ( int arr[], int L, intR ) {int v =arr[L];//[L + 1, j] < v ; [j + 1, i) > v;

int j =L;for ( int i = L + 1; i <= R; i++) {if ( arr[i]

int tmp = arr[j + 1];

arr[j+ 1] =arr[i];

arr[i]=tmp;

j++;

}

}//交换 arr[j] 和arr[L]

int tmp =arr[j];

arr[j]=arr[L];

arr[L]=tmp;returnj;

}

最终实现:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public void quickSorted ( intarr[] ) {int n = arr.length - 1; //闭区间 [0...n]

__quickSorted (arr, 0, n);

}private __quickSorted( int arr[], int L, intR) {if ( (L >=R) {return;

}//将基点移动到最终位置的方法

int p =__partioner(arr, L, R);//递归拆分数组

__quickSorted(arr, L, p - 1);

__quickSorted(arr, p+ 1, R);

}private int __partioner ( int arr[], int L, intR ) {int v =arr[L];//[L + 1, j] < v ; [j + 1, i) > v;

int j =L;for ( int i = L + 1; i <= R; i++) {if ( arr[i]

int tmp = arr[j + 1];

arr[j+ 1] =arr[i];

arr[i]=tmp;

j++;

}

}//交换 arr[j] 和arr[L]

int tmp =arr[j];

arr[j]=arr[L];

arr[L]=tmp;returnj;

}

View Code 快速排序完整代码

二、快速排序的优化

1.  快速排序的第一次优化,减小递归的深度,转而使用 选择排序

private __quickSorted( int arr[], int L, intR) {//if ( (L >= R) {//return;//}//快速排序的第一次优化,减小递归的深度,转而使用 选择排序

if ( R - L <= 15) {

insertSorted(arr, L, R);return;

}

//将基点移动到最终位置的方法

int p =__partioner(arr, L, R);//递归拆分数组

__quickSorted(arr, L, p - 1);

__quickSorted(arr, p+ 1, R);

}//减小递归的深度转而使用选择排序

private void insertSorted(int arr[], int L, intR) {for (int i = L + 1; i <= R; i++) {int i =arr[i];intj;for (j = i; j > L && arr[j - 1] > e; j--) {

arr[j]= arr[j - 1];

}

}return;

}

2. 优化二,基点的选择随机化

private int __partioner ( int arr[], int L, intR ) {//第二次优化,将基点的选择随机化

int rand = (new Random().nextInt(R + 1)) +L;//交换最左侧和随机点的元素

int tmp =arr[rand];

arr[rand]=arr[L];

arr[L]=tmp;

int v =arr[L];//[L + 1, j] < v ; [j + 1, i) > v;

int j =L;for ( int i = L + 1; i <= R; i++) {if ( arr[i]

int tmp = arr[j + 1];

arr[j+ 1] =arr[i];

arr[i]=tmp;

j++;

}

}//交换 arr[j] 和arr[L]

int tmp =arr[j];

arr[j]=arr[L];

arr[L]=tmp;returnj;

}

三、两路快排

解决排序的数组中存在多数重复元素的情况

2f7058b76687a41b74391bc23c15fced.png

代码实现

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public void quickSorted ( intarr[] ) {int n = arr.length - 1; //闭区间 [0...n]

__quickSorted (arr, 0, n);

}private __quickSorted( int arr[], int L, intR) {//if ( (L >= R) {//return;//}//快速排序的第一次优化,减小递归的深度,转而使用 选择排序

if ( R - L <= 15) {

insertSorted(arr, L, R);return;

}//将基点移动到最终位置的方法

int p =__partioner(arr, L, R);//递归拆分数组

__quickSorted(arr, L, p - 1);

__quickSorted(arr, p+ 1, R);

}private int __partioner ( int arr[], int L, intR ) {//第二次优化,将基点的选择随机化

int rand = (new Random().nextInt(R + 1)) +L;//交换最左侧和随机点的元素

int tmp =arr[rand];

arr[rand]=arr[L];

arr[L]=tmp;int v =arr[L];//两路快排的实现过程

int i = L + 1;int j =R ;while (true) {while (i <= R && arr[i]

i++;

}while (j >= L + 1 && arr[j] >v) {

j--;

}if (i >j) {break;

}//交换 i 和 j 的位置

inttmp arr[i];

arr[i]=arr[j];

arr[j]=tmp;

}inttmp arr[L];

arr[L]=arr[j];

arr[j]=tmp;returnj;

}//减小递归的深度转而使用选择排序

private void insertSorted(int arr[], int L, intR) {for (int i = L + 1; i <= R; i++) {int i =arr[i];intj;for (j = i; j > L && arr[j - 1] > e; j--) {

arr[j]= arr[j - 1];

}

}return;

}

View Code 两路快排代码实现

四、三路快排

7a276b238c4ade46c3b00519912964c7.png

代码实现:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public static void quickSorted3Ways(intarr[]) {int n = arr.length -1;//arr[0, n] 闭区间

__quickSorted3Ways(arr, 0, n);

}private static void __quickSorted3Ways(int[] arr, int L, intR) {//if (L >= R) {//return;//}//快速排序的第一次优化,减小递归的深度,转而使用 选择排序

if ( R - L <= 15) {

insertSorted(arr, L, R);return;

}//第二次优化,将基点的选择随机化

int rand = (new Random().nextInt(R + 1)) +L;//交换最左侧和随机点的元素

int tmp =arr[rand];

arr[rand]=arr[L];

arr[L]=tmp;int v =arr[L];//partioner//这三个变量的初始值 , 相当重要

int lt = L; //arr[L + 1, lt] < v

int gt = R + 1; //arr[gt, R] > v

int i =L + 1; //arr[lt + 1, i ) ==v//此处的 i 的比较对象

while (i

SortedHandler.swap(arr, i, lt+ 1);

lt++;

i++;

}else if (arr[i] >v) {

SortedHandler.swap(arr, i, gt- 1);

gt--;

}else{

i++;

}

}

SortedHandler.swap(arr, lt, L);

__quickSorted3Ways(arr, L, lt-1);

__quickSorted3Ways(arr, gt, R);

}

View Code 三路快排

最后附上整篇 关于快速排序从实现到逐步优化的思路图 (画到我怀疑人生了....)

65b0bb43ceff47cf1990f0f0544d1a82.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值