1.时间:2022.03.10
2.目的:学习,作业
3.概念:
1.每个(未排序)的部分
2.将第一个元素设为 pivot
3.存储索引 = pivot索引 +1
4.从 i=pivot指数 +1 到 最右索引 的遍历
5.如果 a[i] < a[pivot]
6.交换 (i, 存储索引); 存储索引++;
7.交换(pivot, 存储索引 - 1)
我的理解就是把数组的第一个数和后面的比较,比它大的数放在它的右边,比它小的数放在它的左边。然后一直用这种方式(递归)将它的左右2部分排序成功。
4.图解概念:
5.文字思路:
总目标:将数组以第一个数为中心(基准值)分成大于和小于基准值的两部分,然后将这两部分继续以第一个数为中心分成大于和小于这组第一个数的两部分,一直如此,直达排序正确。
举例数组:int[ ] array = { 6,5,2,8,4,3,7}
第一轮:设类似于指针的i,j 的2个变量,第一个数6为基准值,并且让i指向6(基准值),j指向7。准备工作结束,然后开始第一轮,先i 不动,j往前移动,当j先为7时,7>6,所以j继续往前移,当j = 3时,3<6,j停止移动。i 开始移动了,i 为6时,6=6,i 继续前进;i = 5,5<6,i继续移动;当2时,2<6,i 继续移动;当i = 8时,6<8 ,i 停止移动,此时i j 都处于停止状态,所以交换数值。即现在数组变为:{6,5,2,3,4,8,7}。然后 j 就开始重新移动了,j 此时等于8>6,所以继续前进;当 j = 4 时,4<6,j 停止移动。i 开始移动,此时等于3,3<6,所以i 继续移动,i= 4;与j 相遇,交换基准值和i j 相遇位置的值即现在数组为:{4,5,2,3,6,8,7} 。自此第一轮循环结束。
第二轮:经过第一轮排序已经分为了在6左边比6小的数和在6右边比6大的数两部分。现在我们就需要分别对{4,5,2,3}和{8,7}进行和第一轮排序相同的方法进行排序。举例:对{4,5,2,3}进行排序,设4为基准值,i 指向4,j指向3,开始j与基准值比较,3<4,j停止已经移动,i开始移动,i=4,4 = 4,i 继续移动,i= 5,5>4,所以i 停止移动,并且i j 交换位置,数组变成{4,3,2,5},交换结束,i j 继续开始移动 ,j = 2,2<4,j停止移动 ,i开始移动,i = 2 ,i j相遇 i j 都停止 交换基准值4和相遇位置的值,数组现在变为:{2,3,4,5},然后对{8,7}进行快排,以8为基准值,i指向8,j指向7,j开始移动,j = 7 ,7<8 ,j 停止移动 ,i开始移动i= 7,i j 相遇 i j 都停止移动。交换i j 相遇位置和基准值位置,即现在数组变为{7,8},数组有序。自此第二轮排序结束。本轮结束后数组变成2部分{2,3,4,5}和 {7,8}。
目前,举例数组已经全部有序,因此排序结束(如果遇到没有排序的情况,只需模仿第一和第二轮的思想进行排序,即可。)
6.代码:
public class quickSort {
public static void main(String[] args) {
int[] arr = {6,5,2,8,4,3,7};
quick(arr,0,arr.length-1);
for (int i = 0;i<arr.length-1;i++){
System.out.println(arr[i]+" ");
}
}
public static void quick(int[] arr, int left,int right){
//如果左边索引序号大于右边,直接返回。
if (left>right){
return;
}
//将数组的第一位设置为基准值即左边第一位
int base = arr[left];
//将i指向left,类似与指针,i现在在数组第一个数上
int i = left;
//将j指向right,类似与指针,j现在在数组的最右边一个数上
int j = right;
//如果 i 和 j 不指向同一个位置,循环继续
while (i != j){
//从右边开始(与基准值相反的位置开始),如果arr【j】所指的值大于或者等于base(基准值)
// 并且i<j ,循环继续,j继续往左移动。
while (arr[j]>=base && i<j){
j--;
}
//从左边开始(基准值那一侧),如果arr【i】所指的值小于或者等于base(基准值)
// 并且i<j ,循环继续,i继续往右移动。
while (arr[i]<=base && i<j){
i++;
}
//如果不符合上面2个while循环的条件(即i j 都停下来了)就会交换位置i j 的位置
// 通过一次次的交换i j 的位置,将比基准值大的全部移到右边,而基准值小的都移到左边。
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
//跳出循环时,必定是i j 相遇的位置
//交换这个相遇位置和基准数的值
arr[left] = arr[i];//将相遇位置的值赋给基准位置的值(第一轮即数组的第一个元素)
arr[i] = base;//将基准位置的值赋值给相遇位置的值
//递归调用
quick(arr,left,i-1);
quick(arr,j+1,right);
}
}
1.理解思路:代码注释很详细了,应该可以。说明一下,循环用while而不是for是因为不知道会循环多少次即条件不知道,所以用while最合适,然后就是递归调用 ,简单来说就是一直重复调用我们写的方法,然后将上面所说的每一个小部分排序(即比基准值大或者小的左右两部分)进行排序。
7.结尾:
这个算法理解总体来说比我之前学习的个(冒泡,插入,选择)感觉难一点,但是更容易理解思(遇题不绝,先画图),思路理解了加上一个递归,就还是能解决的。