一:冒泡排序
算法原理:顾名思义,冒泡,最大的元素可理解成通过冒泡的形式筛选出来。对于一个数组来说,a[0]、a[1]、a[2]、a[3]....a[n],从a[0] a[1]、a[1] a[2]、a[2] a[3]....a[n-1] a[n]进行两两比较,如果前面的元素值比后面的大,则进行交换处理,例如a[0]>a[1],则进行int temp = a[0],a[0]=a[1] a[1]=temp处理,通过一轮的比较之后,a[n]就是整个数组中最大的元素了;同样进行第二轮的比较,则a[n-1]就是整个数组中第二大的元素...进行第三轮,a[n-2]的元素为数组中第三大的元素;最后进行第n-1轮,a[2]元素为数组中第n-1大的元素。(优化:如果某一轮的比较中,没有元素交换,即数组已经是有序的,可退出for循环,结束整个冒泡排序)
原始数列:6,5,4,3,2,1
第一次冒泡排序 5,4,3,2,1,6
第二次冒泡排序 4,3,2,1,5,6
第三次冒泡排序 3,2,1,4,5,6
第四次冒泡排序 2,1,3,4,5,6
第五次冒泡排序 1,2,3,4,5,6
代码:
/**
* 冒泡排序
* @param originalArray
* @return
*/
public Integer[] bubblingSort(Integer[] originalArray){
int length = originalArray.length;
for (int i = length -1; i > 0; i--) {
//提前退出冒泡循环的标记位
boolean flag = false;
for (int j = 0; j < i ; j++) {
int a = originalArray[j];
int b = originalArray[j + 1];
if (a > b){
int temp = a;
originalArray[j] = originalArray[j+1];
originalArray[j+1] = temp;
flag = true; //有数据交换
}
}
printArray(originalArray);
System.out.println();
//没有数据交换,提前退出
if (!flag){
break;
}
}
System.out.print("最终的排序结果");
printArray(originalArray);
return originalArray;
}
运行结果:
空间复杂度:只涉及相邻数据的交换操作,只需要常量级的临时空间,空间复杂度为o(1),是一个原地排序算法。
时间复杂度:
最好时间复杂度:元素本身是有序排列的(从小到大),只需进行一次冒泡比较即可,所以时间复杂度为O(n)。
最坏时间复杂度:元素刚好是倒序排列的(从大到小),时间复杂度为O(n(n-1)/2),即为O(n2)。
平均时间复杂度:由上面最坏时间复杂的情形可知,需要比较n(n-1)/2次,可以取个中间值n(n-1)/4,n足够大,就可理解成n2,所以平均时间复杂度为O(n2)。
二:插入排序
算法原理:一个无序的数组,依次取a[1]和a[0]进行比较,按照从小到大排成一个有序数组,a[2]和前面的a[1]进行比较且记录value=a[2],如果value>a[1],则a[2]插入的位置不变,如果value<a[1],则a[2]=a[1],a[2]的值插入到a[1]的位置;继续进行比较value<a[0], 则a[1]=a[0],最后a[0]=value,依次类推
代码:
/**
* 插入排序
* @param a
* @param n
*/
public void insertionSort(Integer[] a,int n){
printArray(a);
System.out.println("插入排序");
for (int i = 1; i < n; i++) {
int value = a[i];
int j = i -1;
for (; j >= 0 ; j--) {
if (a[j] > value){
a[j+1] = a[j];//数据移动
}else{
printArray(a);
break;
}
}
//发生插入排序,往前,给相应的元素赋值
a[j + 1] = value;
printArray(a);
}
}
运行结果:
空间复杂度:插入排序算法不需要额外的存储空间,所以空间复杂度是O(1),也是个原地排序算法。
最好时间复杂度:元素本身是有序的,从尾到头在有序数组里面查找插入位置,每次只需比较一个数据就能确定插入的位置,所以为O(n)。
最坏时间复杂度:元素是倒序的,比较1次、2次、3次....n-1次,为O(n2)
平均时间复杂度:也为o(n2)
三:选择排序
算法原理:分有序区和无序区,在无序区中找到最小的元素,和有序区后的第一个元素进行替换。例如原始数组为4,5,6,3,2,1
第一次选择排序:1,5,6,3,2,4(1和4交换)
第二次选择排序:1,2,6,3,5,4(2和5交换)
第三次选择排序:1,2,3,6,5,4(3和6交换)
第四次选择排序:1,2,3,4,5,6(4和6交换)
第五次选择排序:1,2,3,4,5,6(5和6不用交换)
代码:
/**
* 选择排序
* @param a
* @param n
*/
public static void selectionSort(Integer[] a,int n){
printArray(a);
System.out.println("插入排序");
for (int i = 0; i < n; i++) {
int min = i;
for (int j = i + 1; j < n; j++) {
//前后元素进行比较,后面的元素小于前面的元素,记录出最小元素的下标
if (a[min] > a[j]){
min = j;
}
}
//最小元素的下标大于前面比较元素的下标,元素值进行交换
if (i < min){
int temp = a[min];
a[min] = a[i];
a[i] = temp;
}
printArray(a);
}
}
运行结果:
空间复杂度为O(1),最好、最坏以及平均时间复杂度均为O(n2)