排序算法java快速排序_排序算法学习06_快速排序(Java)

快速排序

前言:在博客写这些文章的目的用于记录所学,怕以后忘了,如果哪里写的不对欢迎指正,谢谢!!

学习目标:掌握快速排序算法的原理和思想

一、前提知识

排序算法概念、时间复杂度。可前往此网址 排序算法学习01_算法基础介绍阅读

二、快速排序介绍

快速排序(英语:Quicksort),属于交换排序的一种。又称分区交换排序(partition-exchange sort),我们一般简称为快排

三、快速排序工作原理

首先了解一下分治法:分治法将问题分解为规模更小的子问题,然后将这些子问题逐个击破,再将已解决的子问题合并,得出母问题的解

快速排序使用分治法策略,首先它要排序多次,但每次排序时并不真正的对每个数进行排序,而是从序列里找一个基准值将序列分成两个部分(子序列),此时这个基准值需所处在序列“中间”,一边序列放置比基准值小的元素,另一边序列则要比基准值大。

然后把比基准值小\大的部分的序列里再找一个基准值又分成两个部分,重复此逻辑。最终将得到一个排序好的结果

四、快速排序算法设计思路

设计一个快速排序算法,需要思考以下这几点:

基准值选择和移动(前面说过,分成俩部分后,比基准值小的在一边,大的在一边)

如何让比基准值小的部分和大的部分在基准值两边分开放置

接下来就是重点了,当采用以下方案时,基准值的选择有两种:第一种:序列最左边元素作为基准值。第二种序列最右边作为基准值

(还有一种方案是基准值直接选择中间位置的,那就是另一种思路了,这里就不讲了)

首先,我们就要再引入两个变量:

一个为startIndex,该变量用于从序列最左边往右扫描。当要做升序时,扫描时遇到比基准值大,停止

一个为endIndex,该变量用于从序列最右边往左扫描。扫描时遇到比基准值小,停止

当两次扫描停止时,交换元素

当两个指针相遇时,该位置索引上的值与基准值互换

指针相遇后,则代表某个子序列排序完毕

我们此时要做的操作是:从基准值另一边的子序列进行排序,基准值重新选取。

当子序列元素为1时

当进入排序时,发现startIndex和endIndex重合就能结束了,也就是只有一个元素,就可结束了,去判断其他序列

当所有子序列都排序完毕,最终结果也就出来了

从上面思路我们也可以了解到,排序时,都是从大的序列排序,再慢慢到小的序列排序,左边序列排序完毕,排右边,这种分治思想,使用递归可以完美解决

五、过程详解

现在选择第一种,选取序列最左边元素作为基准值,此时进行图解如下

e8a6200c09911b585194999b571316fa.png

开始扫描,当选取最左边元素作为基准值时,那么需从最右边开始扫描,取右则相反

endIndex开始扫:扫到0,比3小,直接停止

startIndex开始扫:扫2不是,扫到11比3大,停止

ce76b3f7611065f28ec38748d6bb0aee.png

两者扫描停止,互换元素,如下图:

f7bcce9be2e3bcd4d0050af93d71fb5b.png

指针还没相遇,则继续扫,依然是endIndex先开始扫

第二次扫

36e997598c2c0b3e196e4d47dfb08f4c.png

f44debb5c6a3eb21fe7c0ab86eccea2f.png

第三次扫

27d53369d0597c94fc67a6b52eb357e8.png

5dd067e26e805071f7f5aabf69db4167.png

第四次,指针相遇,与基准值互换

c5b54b63941e25514cd868517ba9c780.png

23440c84fb931394a8bf473da4e9e1a4.png

至此,我们第一轮排序结束,基准值左边的都是小的,右边都是大的

接下来则排序基准值左边的子序列,你也可以先判断右边的

639c61d82a0fb77cffc309a5d59aa712.png

执行逻辑都是一样的

直到什么时候结束捏

当某个子序列结束后,

c282cc3d555e43ac4da557476b5c83af.png

想再往某个基准值的一边排序时,

696eaaf9c06051ae8ea6d5c7948ab535.png

传值过来发现startIndex和endIndex重合,则表明这个子序列排序完毕

六、代码实现

对该数列进行递增排序 {3,2,11,5,1,7,9,4,-1,-8,0}

package com.migu.sortingAlgorithm;

import java.util.Arrays;

public class QuickSort{

public static void main(String[] args){

int array[] = {3,2,11,5,1,7,9,4,-1,-8,0};

//从两端开始往里找

quickSort(array,0,array.length-1);

}

//采用分治思想

public static void quickSort(int [] array,int startIndex,int endIndex){

if(startIndex >= endIndex) return; // 当传入左右索引相遇时,则表明某个序列以排序完毕

int pivotIndex = sort(array, startIndex, endIndex); // sort方法,用于实现排序.并返回一个基准值,用于判断其他范围的序列

quickSort(array,startIndex,pivotIndex-1); // 这是基准值左边的序列

quickSort(array,pivotIndex+1,endIndex); // 这是右边的序列

}

//排序实现

private static int sort(int[] array,int startIndex,int endIndex){

// 定义四个变量: left:某个序列最左边索引,right:某个序列最右边索引。作用就是找大小

// pivot:基准值 temp:辅助交换

int left,right,pivot,temp;

pivot = array[startIndex]; // 该算法需要选某个序列最左/右边的元素为基准值

left = startIndex; // 从某个序列最左边,往右走

right = endIndex; // 从某个序列最右边,往左走

while (true){

// 基准值在左边,那么从右边开始找,当left和right重合时停止扫描

while (array[right] >= pivot && left < right) right--; // 找到小于基准值退出

while (array[left] <= pivot && left < right) left++; // 找到大于基准值退出

//得到一大一小进行交换

temp = array[left];

array[left] = array[right];

array[right] = temp;

if(left >= right) break; // 指针相遇退出循环

}

// 指针相遇,相遇位置的元素和基准值交换

temp = array[startIndex];

array[startIndex] = array[left];

array[left] = temp;

// 返回基准值此时所在的索引,以便排序其他子序列

return left;

}

}

复制代码

七、时间复杂度

在平均状态下:该算法排序n个项目复杂度为O(n log n),极端情况下可能会想冒泡排序一样为O(n^2),一般不可能发生

八、总结

快速排序算法,采用分治法,实现跳跃式的'冒泡排序来对数据进行排序。

理清基准值两边元素是如何放置的,即可轻松掌握快速排序

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值