1.直接插入排序
算法思想:直接插入排序把序列分为有序区与无序区,刚开始时,只有第一个元素处于有序区,后面的元素都位于无序区。
然后对于第i+1个元素,依次与前面的i个元素相比较,如果小于第i个元素,则把第i个元素后移,再与第i-1的元素比较,如果小于,再后移...
如果大于第i个元素,就把此元素插入到第i+1的位置。
下面是直接插入排序的实例:
i=1 [46] 58 15 45 90 18 10 62
↓
i=2 [46 58] 15 45 90 18 10 62
┌——┘
↓
i=3 [15 46 58] 45 90 18 10 62
┌——┘
↓
i=4 [15 45 46 58] 90 18 10 62
↓
i=5 [15 45 46 58 90] 18 10 62
┌—————┘
↓
i=6 [15 18 45 46 58 90] 10 62
┌————————┘
↓
i=7 [10 15 18 45 46 58 90] 62
┌—┘
↓
i=8 [10 15 18 45 46 58 62 90]
当i=1时,只有46处于有序区,其它的是无序区。当i=2时,由于58>46,所以直接放到46的后面。当i=3时,15比58小,因此58后移,15比46小,46后移。然后将15插入到正确的位置,依次类推,排完整个序列。
直接插入排序的JAVA实现:
public class InsertSort {
/**
* 插入排序算法 插入排序分为两个区:有序区和无序区,刚开始时,只有一个元素
* 把第i+1个元素插入到前i个元素中去,分别比较第i,i-1,i-2,....0个元素 当第i+1个元素小于第i个元素,就把第i个元素后移
* 当第i+1个元素大于第i个元素就把他插入到第i+1的位置
*
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
String[] s = { "d", "c", "b", "a", "h", "p", "f", "1", "a" };
s = insertsort(s);
System.out.println("直接插入排序的结果为:");
for (String s1 : s) {
System.out.print(s1 + " ");
}
}
private static String[] insertsort(String[] s) {
String[] res;
int i = 0;
int j = 0;
char temp = 0;
for (i = 0; i < s.length; i++) {
j = i;
temp = s[i].charAt(0);
for (; j > 0; j--) {
if (temp < s[j - 1].charAt(0)) {
s[j] = s[j - 1];// 元素s[j-1]右移
}
else
break;
}
s[j] = String.valueOf(temp);
}
res = s;
return res;
}
}
时间复杂度分析:
从上述的排序过程可以看出,直接插入排序外循环n-1个元素,元素移动的次数为n,所以时间复杂度为O(n2).
空间复杂度:
在元素交换的过程中,只需要一个元素的辅助空间,因此空间复杂度为O(1).
稳定性:对于直接插入排序而言,如果两个相同的元素前一个元素插入后的位置一定在后一个元素的前面。因此,直接插入排序是稳定的。
2.冒泡排序
基本思想:从第1个关键字开始,对n-1对相邻关键字进行两两比较,如果前面的关键字大于后面的关键字,则进行交换。经过一趟起泡排序之后,最大的关键字沉入到最底端。这样,经过n-1趟排序之后,关键字就从小到大进行排列。在某趟两两比较的过程中,只要交换没有发生的话,表明已经有序,则可以结束。
下面是冒泡排序的一个实例:
原始序列: d c b a f z g
第一趟冒泡排序:c b a d f g z
第二趟冒泡排序:b a c d f g z
第三趟冒泡排序:a b c d f g z
第四趟冒泡排序:a b c d f g z
冒泡排序的Java实现:
public class bubble {
/**
* 冒泡排序算法
*
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
String[] s = { "d", "c", "b", "a", "f", "z", "g" };
sort(s);
for (String s1 : s) {
System.out.println(s1);
}
}
private static void sort(String[] s) {
int swap;
for (int i = 0; i < s.length; i++) {
swap = 0;
for (int j = 0; j < s.length - 1 - i; j++) {
if (s[j].charAt(0) > s[j + 1].charAt(0)) {
String temp = s[j];
s[j] = s[j + 1];
s[j + 1] = temp;
swap = 1;// 如果交换产生swap=1,如果没有发生交换,说明已经是有序序列,排序结束
}
}
for (int k = 0; k < s.length; k++) {
System.out.print(s[k] + " ");
}
System.out.println();
if (swap == 0)//如果在某趟排序过程中没有交换发生,则排序结束。
break;
}
}
}
当swap=0时,即上述冒泡排序例子最后一趟没有交换发生,因此,已经有序了,排序结束.因此,此算法是一个智能的冒泡排序算法。最多需要n-1趟冒泡。
时间复杂度分析:
冒泡排序每一趟比较的次数最多为n-1,排序的趟数最多为n-1,因此时间复杂度为O(n2).
空间复杂度分析:
只需要一个元素的辅助空间用于交换,因此辅助空间为O(1).
稳定性分析:
冒泡排序只是把最大元素沉入底端,如果关键字相同,那么前面的不比后面的大,因此不进行交换把后面的往下沉。这样,相同关键字的相对位置会保持不变。因此,冒泡排序是一种稳定排序算法。
关于直接插入排序与冒泡排序的JAVA实现就总结到这了,以后会接着总结一下其它的排序算法。