一)算法介绍
快速排序是对冒泡排序的一种改进算法,属于不稳定排序。
基本思想:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都要比另一部分的所有数据都要小,按照此方法对数据进行快速排序,以达到整个数据变成有序列表。
备注:快速排序是一种适用于数据量越大,数据分布越混乱的算法,一般被认为性能是最好的。
不稳定排序:如果a原本在b的前面,而a=b,排序之后a可能会出现在b的后面;
二)算法原理
基本原理:
第一步:首先设定一个分界值(基数),将数据分割成左右两部分。
第二步:将大于分界值的数据排列到右边,小于分界值的数据排列到左边。
第三步:然后左右两边的数据又可以独立排序,对左侧数据又可以取一个分界值,分割成左右两部分,对右侧数据也取一个分界值,分割成左右两部分。按左边存放比分界值小,右边存放比分界值大的规则进行排序。
第四步:不断重复第三步,对数据进行取分界值(基数),分割成左右部分,按左小右大的规则排序,直到排序完成。
算法步骤图解:
源数据:int[] nums = {83, 23, 333, 24, 534, 234, 81};
先设定一个分界值,一般是假设第0个下标元素为分界值(基数)。
查找规则:从左往右查找比分界值(基数)大的元素,从右往左查找比分界值(基数)小的元素。
第一遍排序:取元素83为分界值(基数)、从右往左比较,83>81,先记录元素81的下标值,再从左往右比较,83<333,先记录元素333的下标值,把元素81和元素333的位置交换。再把分界值(基数)调到中间,把元素24(元素333的后一个元素)和分界值(基数)83交换位置。
排序结果为:[24, 23, 81, 83, 534, 234, 333]
第二遍排序:先把左侧数据进行处理,取元素24为分界值(基数),从右往左比较,24>23,交换24和23的位置,左侧无数据比较。
排序结果为:[23, 24, 81, 83, 534, 234, 333]
第三遍排序:此时左侧的数据都已经排列好,再把右侧数据进行处理,取元素534为分界值(基数)。534>333,交换534和333的位置,再比较333>234,交换333和234的位置。排序完成
最终排序结果为:[23, 24, 81, 83, 234, 333, 534]
算法排序效果图:
算法复杂度:
最差情况:T(n) = O(n^2)
最好情况:T(n) = O(log2N)
O(log2N)的含义:将一个数据集分成两半,然后将分开的每一半再分成两半,依此类推。
O(Nlog2N)的含义:将一个数据集分成两半,然后将分开的每一半再分成两半,依此类推,在此过程中同时遍历每一半数据。
三)算法源码
步骤简介:先取一个分界值(基数),按比基数大排右边,比基数小排左边的规则,不断递归对数据进行取分界值(基数),分割成左右两部分数据,再排序等操作,直到数据排序完成。
/**
* 快速排序
* @param nums
* @return
*/
public static int[] quickSort(int[] nums) {
if (nums == null) {
return null;
}
return quick(nums, 0, nums.length-1);
}
private static int[] quick(int[] nums, int left, int right) {
if (left > right) {
return null;
}
// 取第一个元素作为比较的基数
int base = nums[left];
// 记录第一位和最后一位的临时下标
int low = left;
int high = right;
// 循环
while (low != high) {
// 先从high往low的方向找,如果nums[high]比基数大,就一直往low方向找,直到找到比基数小的值,然后把下标记录起来
while (low < high && nums[high] >= base) {
high--; // 记录的都是比基数值小的下标,需要放置到基数左边的元素
}
// 再从low往high找,如果nums[low]比基数小,就一直往high方向找,直到找到比基数大的值,然后把下标记录起来
while (low < high && nums[low] <= base) {
low++; // 记录的都是比基数值大的下标,需要放置到基数右边的元素
}
// 把比基数大的值(nums[low])和比基数小的值(nums[high])交换位置。比基数大的值排列在左边,比基数小的值排列在右边
if (low < high) {
int temp = nums[low];
nums[low] = nums[high];
nums[high] = temp;
}
}
// 第low的值放置到源数据第left下标位置
nums[left] = nums[low];
// 把基数放置到中间
nums[low] = base;
// 把左侧数据再进行取分界值、分割成左右两部分、进行排序
quick(nums, left, low-1);
// 把右侧数据再进行取分界值、分割成左右两部分、进行排序
quick(nums, low+1, right);
// 返回值
return nums;
}
识别二维码关注个人微信公众号
本章完结,待续、欢迎转载!
本文说明:该文章属于原创,如需转载,请标明文章转载来源!