(1)O(n^2)的时间复杂度是比较大的,所以不适用于大量数据。
(2)这三种方法都是基于比较和移动的,基于比较和移动的排序算法时间复杂度主要考虑比较和移动的次数
(3)这三种方法都是内部排序,元素的存储和额外的空间开销都在内存内。外部排序指的是需要同时利用外存和内存,元素在外存和内存间移动。(可能元素的数量比较大)
(4)稳定性:对于序列中相等的两个元素i,j,如果排序后元素i,j顺序颠倒了,这个算法就是不稳定的,反之稳定
(1)插入排序概念:对于每一个待排序序列分解为已排序的序列s和一个元素e,把e按照大小顺序插入到已排序序列s中。
(2)直接插入排序
设表为L[1,2,…,n],每次都把L[i]插入到有序表L[1,2,3,…,i-1]中构成新的有序表L[1,2,3,…,i],直到n=i(插入前提必须是L[i-1]和L[i]逆序)
[1]平均时间复杂度和最坏时间复杂度都是O(n^2),如果列表本来就有序,即最好的情况下时间复杂度为O(n)
[2]空间复杂度O(1)
[3]稳定性:触发插入的前提是L[i-1]和L[i]逆序,所以不可能改变相等元素的相对次序,所以是稳定的
Java语言代码实现:
Java比较大小有3种情况:
[1]基本类型int,float,long,double,这时候使用>(=) or <(=)就可以
[2]待比较对象实现了Comparable接口,调用o1.compareTo(o2)方法就可以,如果o1比o2小,则返回负数,大则返回正数,相等则返回0,int、float、long和double可以自动装箱为Integer、Float、Long和Double,它们都实现了Comparable接口
Integer a = 1;
Integer b = 2;
//打印 -1
System.out.println(a.compareTo(b));
[3]写一个Comparator比较器,重写compare方法,最终效果上类似于Comparable接口
‘小’是人为定义的,假如我刚好想要从大到小排序整数,下面这个比较器就可以,‘越大越小’
Comparator<Integer> c = new Comparator<Integer>() {
@Override
public int compare(Integer i1, Integer i2) {
if (i1 < i2) {
return 1;
} else if (i1 > i2) {
return -1;
} else {
return 0;
}
}
};
为了简化实现,就用int举个例子:
public static void insertSort(int[] array) {
for (int i = 1; i < array.length; i++) {
//逆序时候才触发
if (array[i - 1] > array[i]) {
//取出这个元素
int elem = array[i];
int j;
for (j = i - 1; j >= 0; j--) {
if (array[j] > elem) {
array[j + 1] = array[j];
} else {
break;
}
}
array[j + 1] = elem;
}
}
}
@Test
public void test() {
int[] a = {1, 2, 3, 10, -1, 8, 7};
System.out.println(Arrays.toString(a));
insertSort(a);
System.out.println(Arrays.toString(a));
}
控制台打印结果:
(1)冒泡排序属于交换排序,根据元素比较结果交换元素,最终达到排序的目的。
(2)冒泡排序的过程:
设列表L[1,2,3,…,n]
第1趟,L[1-n]中从后向前两两比较,如果前者大于后者,则交换,最终结果L[1]是最小值,如果没有逆序情况直接结束
第2趟,L[2-n]中从后向前两两比较,如果前者大于后者,则交换,最终结果L[2]是次小值,如果没有逆序情况直接结束
…
第n-1趟,L[n-1,n]执行相同的操作完成排序
[1]空间复杂度O(1)
[2]时间复杂度最好情况下O(n),最坏的情况和平均的情况都是O(n^2)
[3]稳定性:两两比较,如果前者大于后者,则交换,相等情况下不可能交换,所以这个算法是稳定的
代码实现如下:
public static void bubbleSort(int[] array) {
// n-1趟,i表示每一趟的起始元素值
for (int i = 0; i < array.length - 1; i++) {
boolean swap = false;
for (int j = array.length - 1; j > i; j--) {
if (array[j] < array[j - 1]) {
int tmp = array[j];
array[j] = array[j - 1];
array[j - 1] = tmp;
swap = true;
}
}
// 如果没交换过说明有序
if (!swap) {
break;
}
}
}
@Test
public void testBubbleSort() {
int[] a = {1, 2, 3, 10, -1, 8, 7};
System.out.println(Arrays.toString(a));
bubbleSort(a);
System.out.println(Arrays.toString(a));
}
(1)属于选择排序,选择排序指的是第i趟,在n-i+1个元素中选择最小值,加入到新序列中。
(2)简单选择排序过程:
设列表L[1,2,3,…,n]
第1趟,在L[1-n]个元素中选择最小值索引j,L[j]和L[1]交换
第2趟,在L[2-n]个元素中选择最小值索引j,L[j]和L[2]交换
…
第n-1趟,在L[n-1 - n]个元素中选择最小值索引j,L[j]和L[2]交换
[1]空间复杂度O(1)
[2]时间复杂度最好最坏平均都是O(n^2),不论交换的次数,选择的次数不会变化
[3]稳定性:如果L={x11,x12,x2}(x11=x12>x2),算法运行结束后结果变成了L={x2,x12,x11},相等元素位置先后顺序交换了,所以简单选择排序是不稳定的
代码实现:
public static void simpleSort(int[] array) {
for (int i = 0; i < array.length - 1; i++) {
int min = array[i];
int minIndex = i;
for (int j = i + 1; j < array.length; j++) {
if (array[j] < min) {
min = array[j];
minIndex = j;
}
}
int tmp = array[i];
array[i] = array[minIndex];
array[minIndex] = tmp;
}
}
@Test
public void testSimpleSort() {
int[] a = {1, 2, 3, 10, -1, 8, 7};
System.out.println(Arrays.toString(a));
simpleSort(a);
System.out.println(Arrays.toString(a));
}
控制台结果:
以后还会介绍一些时间复杂度到达O(n^1.5) or O( n*log(n) ) or O(n)的排序算法。
转载请注明出处,谢谢合作