数组中的排序是非常重要的,每一种排序方法都是一种算法。
基础的排序有: 选择排序,冒泡排序,插入排序;
初次之外比较高级的排序方法有: 快速排序,归并排序,堆排序,希尔排序;
在将这些排序之前,我们先介绍一个Arrays的排序方法,已经封装好的。 Arrays.sort(数组名);
package Sort;
import java.util.Arrays;
public class ArraysSort {
public static void main(String[] args) {
int[] a = {43,32,4,432,54,5,5,5,324,34,34,5,56,7,65};
//自动从小到大排序
Arrays.sort(a);
//打印数组
System.out.println(Arrays.toString(a));
}
}
此时打印的结果为
[4, 5, 5, 5, 5, 7, 32, 34, 34, 43, 54, 56, 65, 324, 432]
选择排序
1.先选择,再交换;
2.在所有元素中找到最的大的元素的下标,并记录下来;
3.将最大的下标中的元素与第一个元素进行交换
4.重复以上步骤(最大与剩余最前面的下标)
package Sort;
import java.util.Arrays;
public class ChoosingSort {
public static void main(String[] args) {
int[] a = {1,3,324,45,56,67,78,4,7,8,43,76,98,3,67};
for(int i =0;i<=a.length-2;i++) {
int temp = i;//temp用来记住数组下标
for(int j=i+1;j<=a.length-1;j++) {
if(a[j]<a[temp]) {
temp = j;//如果找到比temp位置更小的数,则记录此数所在的位置(temp更新)
}
}
//System.out.println(a[temp]); 可以验证下交换是否正确
if(temp!=i) {
//如果temp的值发生了该表则交换两个值
int temp2 = a[i];
a[i] = a[temp];
a[temp] = temp2;
}
}
//重新输出打印该数组,查看结果
System.out.println(Arrays.toString(a));
}
}
此时,打印结果为
[1, 3, 3, 4, 7, 8, 43, 45, 56, 67, 67, 76, 78, 98, 324]
冒泡排序
冒泡排序是要符合两两交换的原则,假设我们从小到大排序,那么我们需要相邻 两个比较大小,如果后者比前者小,则交换位置,从头到尾可确定最后一个是最大的,进行数组个数减一次相邻元素比较即可。
package Sort;
import java.util.Arrays;
public class BubbleSort {
public static void main(String[] args) {
int[] a = {1,3,324,45,56,67,78,4,7,8,43,76,98,3,67};
for(int i = a.length-2;i>=0;i--) {
for(int j = 0;j<=i;j++) {
if(a[j]>a[j+1]) {
int temp = a[j];
a[j] = a[j+1];
a[j+1] =temp;
}
}
}
System.out.println(Arrays.toString(a));
}
}
插入排序
插入排序的核心算法是将待排序的元素插入到已排序集合中的指定位置;
{45},78,2,77,23,1,19
{45,78},2,77,23,1,19
{2,45,78},90,23,1,19
{2,45,77,78},23,1,19
{2,23,45,77,78},1,19
{1,2,23,45,77,78},19
{1,2,19,23,45,77,78}
package Sort;
import java.util.Arrays;
public class InsertSort {
public static void main(String[] args) {
int[] a = {1,3,324,45,56,67,78,4,7,8,43,76,98,3,67};
for(int i =1; i<=a.length-1;i++) {
for(int j = i;j>=0;j--) {
if(a[j]<a[j-1]) {
int temp = a[j];
a[j] = a[j-1];
a[j-1] = temp;
}else {
//在比较过程中一旦满足比前一个大了,就不用继续向前面进行比较了
break;
}
}
}
System.out.println(Arrays.toString( a));
}
}
下面是其他算法难度比较大的排序,小编也是做了很多调整和修改和思考才总结出来的…(忽略小编是个菜J)
快速排序
快速排序是所有排序算法中运算速度最高的,效率最高的排序算法,快速排序的算法被称为是20世纪最伟大的十大算法之一。但是它的算法思想还是比较难掌握的。
主要思想:
***把要进行排序的数组分成两部分,保证前一部分比后一部分整体要笑,分别对两组数据再使用相同的方法进行排序(递归),直到所有的数据有序为止。
**
目的:
**首先先在要排序的数组中取一个基准值(key),我们需要把所有小于key 的值放在key之前,把所有大于key的值放在key之后。
操作:
先取一个索引值key(一般取第一个数),在定义起始位置start,和终止位置end,将索引end先从后向前遍历,如果遇到小于key 的数则交换end和start索引处的值,然后再用索引start 从前向后遍历,遇到比key大的值再次交换end 和start对应位置的数,直到start和end 的值相等时候,key之前的数都比key小,之后的数都比key大。完成一次排序。
key分割成的两部分分别采取此方法不断递归。。
package Sort;
import java.util.Arrays;
public class FastSort {
public static void main(String[] args) {
int[] a = {1,3,324,45,56,67,78,4,7,8,43,76,98,3,67};
method(a,0,a.length-1);
System.out.println(Arrays.toString(a));
}
static void method(int[] a,int startIndex,int endIndex) {
int keyValue = a[startIndex];
int start = startIndex;
int end = endIndex;
while(end>start) {
//从后往前比较
while(end>start&&a[end]>=keyValue) {
//如果从后往前值一直比基准值key大,则继续向前遍历
end--;
}
if(a[end]<=keyValue) {
//遇到比基准值key要小的,就交换索引为start和end的两个位置
int temp = a[end];
a[end] = a[start];
a[start] = temp;
}
while(end>start&&a[start]<=keyValue) {
//如果从前往后值一直比基准值key小,则继续向后遍历
start++;
}
if(a[start]>=keyValue) {
//遇到比基准值key要大的,就交换索引为start和end的两个位置
int temp = a[start];
a[start] = a[end];
a[end] = temp;
}
}
//此时第一次循环比较结束,基准值key左边的元素都比基准值小,右边的元素都比基准值大
//但是key左边和右边的值还有可能不是排好序的
//因此使用递归
if(start>startIndex) {
method(a,startIndex,start-1);
}
if(end<endIndex) {
method(a,end+1,endIndex);
}
}
}
归并排序,
思想:
归并排序是说先把数组按照索引顺序分成不能再分的两个一组的单元,每个单元之间排好顺序,然后再不断归并,下面是关于归并排序的一张思维导图
操作方法:
这个方法肯定要用到递归,但是其中的难点在于如何归并,对于任意两个长度相同, 各自按顺序排好的数组,我们总结出一个归并的算法:
对两列数组分别进行取最小值,被取走后的数组指针索引自增加一。最后会有一个数组中的元素有剩余,将它取走即可。
package Sort;
import java.util.Arrays;
public class MergeSort {
public static void main(String[] args) {
int[] a = {1,3,324,45,56,67,78,4,7,8,43,76,98,3,67};
method(a,0,a.length -1);
System.out.println(Arrays.toString(a));
}
//定义一个排序的递归方法
static void method(int[] array,int start,int end) {
int middle = (start+end)/2;
if(start<end) {
//对分好的左边进行排序
method(array,start,middle);
//对分好的右边进行排序
method(array,middle+1,end);
//两边分别排序完成后进行归并
merge(array,start,middle,end);
}
}
static void merge(int[] array,int start,int middle,int end) {
//定义一个新数组进行装取元素
int[] temp = new int[end-start+1];
//左边数组的变化索引定义为i
int i = start;
//右面数组的变化索引定义为j
int j = middle+1;
//定义k为新数组的变化索引
int k =0;
//开始装元素,把小的全部统统装入
while(i<=middle&&j<=end) {
if(array[i]<array[j]) {
temp[k++] = array[i++];//这里的自增是先取值在自增,比如一开始先是对temp[0]进行取值
}else {
temp[k++]=array[j++];
}
}
//由于左右两个数组肯定会有一个没有全部被装入,所以最后进行补装
while(i<=middle) {
temp[k++]=array[i++];
}
while(j<=end) {
temp[k++]=array[j++];
}
//最后再将装好的数组覆盖掉出传入的原来的数组,这样得到的数组就是排好序的了
for(int l =0;l<=temp.length -1;l++) {
array[start+l] = temp[l];
}
}
}