一、算法时间复杂度分析
1、我们考虑一个排序算法的好坏,我们首先是应该考虑的点,
有最好时间复杂度,最坏时间复杂度,平均时间复杂度。
2、时间复杂度的系数,常数 和低阶。
3、比较的次数和交换的次数。
4、额外空间复杂度。(原地排序)
5、稳定性。
冒泡排序的核心思想:我们进行相邻的元素进行比较,把最大的元素往后移动,直到全部有序。
1、冒泡排序是一个原地排序,不需要额外的空间。
2、冒泡排序是稳定的。(当我们有两个元素相等的时候,我们不进行交换顺序)。
3、最好的时间复杂度是O(n) 如果有序,我们只需要便利所有的元素一次就可以。
4、最坏的时间复杂度是O(n^2),如果是倒序,我们每一个元素比较,都需要交换位置。
5、平均的时间复杂度是O(n^2).比较的次数,就是逆序对的个数。平均逆序对的个数是n(n-1)/4
我们用有序对和逆序对,来计算时间复杂度。
有序元素对:a[i] <= a[j], 如果 i < j;
逆序元素对:a[i] > a[j], 如果 i < j。
满有序度 :n*(n-1)/2 n表示的是元素的个数。
逆序度 = 满有序度 - 有序度。
交换的次数就是逆序对的个数。
最坏情况下,初始状态的有序度是 0,所以要进行 n*(n-1)/2 次交换。
最好情况下,初始状态的有序度是 n*(n-1)/2,就不需要进行交换。
我们可以取个中间值 n*(n-1)/4,来表示初始有序度既不是很高也不是很低的平均情况。
插入排序的核心思想:取未排序区间中的元素,在已排序区间中找到合适的插入位置将其插入, 并保证已排序区间数据一直有序。
一种是元素的比较,一种是元素的移动。
1、插入排序是一个原地排序,不需要额外的空间。
2、插入排序是稳定的,当我们插入元素的时候,如果遇到相等的情况下,我们不进行移动操作。
3、最好的情况是,有序的,我们不需要进行移动操作。
4、坏的时间复杂度是O(n^2),如果是倒序,我们每一个元素比较,都需要进行移动。
5、平均情况也是O(n^2)
选择排序的核心思想:从第一个元素开始,在后面的元素找到一个最小的和我们当前元素进行比较,把最下的放在
最前面。
1、选择排序是一个原地排序,不需要额外的空间。
2、插入排序是不稳定的,它是交换位置。
3、最好 最坏 平均情况都是O(n^2)
二、代码实现
package com.ipp.test;
public class Test {
/**
* 冒泡排序
*
* @param array
*/
public void bubbleSort(int[] array) {
for (int i = 0; i < array.length - 1; i++) { //总共要比较多少趟
boolean flag = false;
for (int j = 0; j < array.length - 1 - i; j++) { //每一趟比较多少次
if (array[j] > array[j + 1]) {
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
flag = true;
}
}
if (!flag) return;
}
}
//1、基本思想是,我们相邻的两个数,进行比较,每次比较把最大的元素,放到最后的位置。
/**
* 选择排序
*/
public void selectSort(int[] array) {
for (int i = 0; i < array.length; i++) {
int index=i; //表示的是最下的元素。
for (int j = i + 1; j < array.length; j++) { //找出最小的元素和前面的元素交换位置
if (array[index] > array[j]) {
index=j;
}
}
if(i!=index){ //如果存在这样的点,我们就进行交换。
int temp = array[index];
array[index] = array[i];
array[i] = temp;
}
}
}
//1、基本思想是:我们从数组第一个元素开始,我们从后面找到一个最小的元素和它进行交换。
/**
* 插入排序
* 这个是赋值操作的比较
* @param array
*/
public static void insertSort(int []array){
for(int i=1;i<array.length;i++){ //我们从第二个元素开始比较
int current=array[i]; //表示的是要插入的元素
int index=i;//表示的是要插入的元素下标
for(int j=i-1;j>=0;j--){ //每次和前面的元素进行比较
if(array[j]>current){ //如果前面的元素大。
array[index]=array[j];
index=j;
}else{ //如果小,就直接结束
break;
}
}
if(i!=index){ //最后插入该元素
array[index]=current;
}
}
}
//基本思想:第一个元素,我们进行不动,我们从第二个元素开始,和前面的元素开始比较,如果这个元素比它小,我们就不动,如果是比它大。 我们交换它们的位置。然后继续比较,直到前面的元素比它要小或者等于。
/**
* 这个是基于比较的插入函数
* @param array
*/
public static void insertSort2(int []array){
for(int i=1;i<array.length;i++){ //我们从第二个元素开始比较
int k=i;
for(int j=i-1;j>=0;j--){ //每次和前面的元素进行比较
if(array[j]>array[k]){ //如果前面的元素大。
int temp=array[j];
array[j]=array[k];
array[k]=temp;
k=j;
}else{ //如果小,就直接结束
break;
}
}
}
}
public static void main(String[] args) {
int array[]={12,3,4,7,2,5,6};
insertSort2(array);
for(int i=0;i<array.length;i++){
System.out.println(array[i]);
}
}
}