前几天浏览网页,看到过一个帖子,问:html
下面有100多的回答,浏览了一些,有的是根本没听过,涉及到了多个领域的优秀算法,其中有一个回答是快排,并且还有很生动的动图演示。java
后来作算法题时,就遇到了数组排序的问题,再去那网页找那个快排时,就没再看到那个动图TOT,多是太多回答我没找太细,这里留一下网址:https://www.zhihu.com/question/26934313。算法
没找到后悔不已啊,只能本身百度去找相关详细的介绍了。数组
下面记录一下数组排序的几种方法:dom
一、最简单方便使用的就是 Arrays 自带的 Arrays.sort(array);这里不过多描述。学习
import java.util.Arrays; public class SortTest { public static void main (String[] args) { int[] arr = new int[10]; for(int i = 0; i < arr.length; i ++) { arr[i] = (int)(Math.random()*100); } Arrays.sort(arr); System.out.println(Arrays.toString(arr)); } }
二、冒泡排序ui
这个想必你们学语言的都学习过,当初脑子笨,逻辑很差,还记了很久才读懂原理,还好如今回想起来仍是很简单的,不知道何时脑壳就开窍了,哈哈。spa
它的原理嘛,就是遍历数组,而后比较临近两个数的值的大小,最后将最小或者最大的数置换到最左边或者最右边。code
下面来记录方法:htm
public void bubbleSort () { for(int i = 0; i < numArr.length; i ++) { for(int j = 0; j < numArr.length - 1 - i; j ++) { if(numArr[j] > numArr[j + 1]) { numArr[j] = numArr[j] + numArr[j + 1]; numArr[j + 1] = numArr[j] - numArr[j + 1]; numArr[j] = numArr[j] - numArr[j + 1]; } } } }
外层循环控制比较次数,内层从 0 下标开始循环,而后进行先后两个数值的比较,这里注意,内层循环到数组长度 -i 处下标便可。拿方法中的第一次循环来讲:0 下标会与 1 下标元素比较大小,较大的数会被放到 1 下标位置,而后下标 1 与下标 2 比较,较大数再存储到 下标 2 中。这样内层循环到最后,最后一个元素存储的值一定是大于等于其余元素值的存在。外层第二次循环时,内层就不须要所有比对一遍了,由于最后一个值已是最大的了,只要比较剩余的元素值便可,因此内部循环此数作 -i 处理。越到后面比起内层所有循环节省的循环此数越多哦~
或许也能够变成这样,直接使用 i 进行控制内层循环的次数,数组有多少个就会两两间比较 长度-1 次,每次内层循环出来又会减小一次,嗯,简化成这样能够了:
public void bubbleSort () { for(int i = numArr.length - 1; i > 0; i --) { for(int j = 0; j < i; j ++) { if(numArr[j] > numArr[j + 1]) { numArr[j] = numArr[j] + numArr[j + 1]; numArr[j + 1] = numArr[j] - numArr[j + 1]; numArr[j] = numArr[j] - numArr[j + 1]; } } } }
三、选择排序
这种排序也是遍历寻找最小或者最大的值,而后单提出来存储到一个最小或最大值变量中,作排序题时,忘了诸多排序方法,只能本身想出一个最笨的方法,结果竟然也有名字:选择排序。
public void selectSort (int[] numArr) { int minSub; boolean isChange; for(int i = 0; i < numArr.length; i ++) { isChange = false; minSub = i; for(int j = i + 1;j < numArr.length; j ++) { if(numArr[minSub] > numArr[j]) { isChange = true; minSub = j; } } if(isChange) { numArr[minSub] = numArr[i] + numArr[minSub]; numArr[i] = numArr[minSub] - numArr[i]; numArr[minSub] = numArr[minSub] - numArr[i]; } } }
这个排序的思路是最简单易懂的:感受有点相似冒泡的感受,只不过多一个变量来进行存储最大或最小的值。好比当前方法:将 0 下标元素值当成最小值进行下标存储,而后遍历其后元素,寻找小于当前存储的变量值的元素,若是有,则对其下标进行存储,直到内层循环完成后,将存储的最小值下标与当前 0 下标值互换。最终获得升序排序的数组。
四、插入排序
简单理解,就是将一个数据插入到已经排好序的有序数组中,从而获得一个新的,个数 +1 的数组。核心思想就是将数组分红两部分,一部分包含了数组全部元素,将最后一个元素除外;第二部分就只有一个元素。然后第一部分排序完成后,再将最后元素插入到已排好序的第一部分中。
public void insertSort () { for(int i = 1; i < numArr.length; i ++) { for(int j = i; j > 0; j --) { if(numArr[j - 1] > numArr[j]) { numArr[j - 1] = numArr[j - 1] + numArr[j]; numArr[j] = numArr[j - 1] - numArr[j]; numArr[j - 1] = numArr[j - 1] - numArr[j]; } } } }
首先将数组分红两个部分,一部分有序,另外一部分无序。看方法:首次循环,第一部分实际上是没有的,直到找到最小值压入 0 下标位置,第一部分才造成,以后每次循环都将当次循环的下标值当成待排数,然后经过遍历已经排好的数组,判断该值是否大于前数,若是大于就前移一位,若是不大于,则不动,放置有序数组的最后一位。
这个也还好理解吧?
五、快速排序
听说是效率最快的,不过不如其它排序方法稳定,有可能相同值会有屡次相对位置变更,由于它的大体实现是:
选择一个标志值(一般为数组第一个元素),根据这个标志值同时从先后遍历查找大于或小于该值的数,将数组分红小于标志值和大于标志值两部分,通过一次快排后,左边为小于标志值元素,右边为大于标志值数,接着左右两边分别再进行快排,重复刚开始的步骤。最后直到变成有序数组。
public void quickSort (int firstSub, int lastSub) { int i = firstSub; int j = lastSub; int key = numArr[i]; while(i < j) { while(i < j && numArr[j] >= key) j--; if(i < j){ numArr[i] = numArr[i] + numArr[j]; numArr[j] = numArr[i] - numArr[j]; numArr[i] = numArr[i] - numArr[j]; i++; } while(i < j && numArr[i] <= key) i++; if(i < j){ numArr[j] = numArr[i] + numArr[j]; numArr[i] = numArr[j] - numArr[i]; numArr[j] = numArr[j] - numArr[i]; j--; } } if(i > firstSub)quickSort(firstSub , i - 1); if(j < lastSub)quickSort(i + 1, lastSub); }
这个有点复杂,得仔细理解一下~