ps:快排会有边界问题,所以背一个模板
static void QuickSort(int[] q,int l,int r) {if(l >= r) {return;}int i = l-1;int j = r+1;int medium = nums[l];while (i<j) {do i++; while (q[i]<medium); !!这里是易忘点do j--; while (q[j]>medium);if (i < j) {int temp = q[i];q[i] = q[j];q[j] = temp;}}//递归排序左边QuickSort(q, l, j);//递归排序右边QuickSort(q, j + 1, r);}
应用层面剖析
方法形参传值都传边界,创建指针时向外拓一位(也就是左边界-1,右边界+1)方便进行判断
判断的值是 取当前数组的左边界
条件判断
只有指针穿过,或相等,整个数组才是被指针划分开左右两个理想区域(理想区域就是左边都比比较值小,右边都比比较值大)
如果他们卡在了两边的不同点
为什么卡住?
我们先分析一下为什么会卡住,因为指针发现了目标,把指针想象成两个过滤网,有过滤不掉的东西,它就会卡住不走。左指针是因为碰到大的(因为它的任务是将左区域过滤成小的),右指针是因为碰到小的(因为它的任务是把右区域过滤成大的),这个大和小是相对于比较值而言。
卡住了怎么办?
既然左右两个过滤网都碰到了不属于自己的东西,那就互相交换咯(if判断就是来做这个事的)
递归区域划分
右指针最后指到哪,那个地方以及前面整个都是左区域(因为J停的地方就是小的它才会停,如果比比较值大的话它就不会停那了),我们比较值都用了数组左边界,所以 其实它就是不断在排序右区域
注意
中间值不能用右边界,会出现溢出问题,用左边界稳妥。
个人整理
判断
递归总有一个结束判断,当左边界>=有边界,证明数组为空,结束返回
构造指针和中间值
指针往外拓一位(方便移动的时候判断)
比较值为数组左边界索引值(防止溢出)
移动过滤(直到两指针交汇才算这一轮过滤成功)
左指针就是左滤网,它专筛比“比较值”小的值 注:用比较值和指针指向的数组值进行比较
右指针则相反,它专筛比“比较值”大的值
筛完以后如果左指针小于右指针,说明他们遇到茬了,马上交换数组的这两个值。注:交换完了还要再循环,确保交换完以后彻底筛干净
左右区域递归
递归调用方法,分别调用左边界到右指针的,和右指针右边的。
番外
在这个排序思想中,两个指针相等或者越过都是理想情况,因为只有他们两个过滤网都成功过滤了,才会相等或传过。所以如果左指针<=右指针,就是两个过滤网都遇到茬了,交换。简单记忆:判断,构造,移动,递归
ps:今天有点心得,发现c++的指针其实可以用参数来代替,指针就是索引
代码
package com.company;import java.util.Scanner;public class QuickSortRepeat {static void QuickSort(int[] nums,int l,int r){/*判断*/if(l>=r){return;}/*构造指针和比较值*/int i = l-1;int j = r+1;int x = nums[l];/*移动指针并判断*/while (i<j){do{ i++;}while(nums[i]<x);do{ j--;}while(nums[j]>x);if (i<j){int temp = nums[i];nums[i] = nums[j];nums[j] = temp;}}/*左右区域递归*/QuickSort(nums,l,j);QuickSort(nums,j+1,r);}public static void main(String[] args) {/*外界输入*/Scanner sc = new Scanner(System.in);int ListSize = sc.nextInt();int[] nums = new int[ListSize];String[] strs = sc.next().trim().split(",");for (int i=0;i<ListSize;i++){nums[i] = Integer.parseInt(strs[i]);}/*调用方法*/QuickSort(nums,0,nums.length-1);/*查询*/for (int i:nums) {System.out.print(i+",");}}}
