冒泡、选择、插入排序算法
排序大家都很熟了,很古老的算法,古老才有必要回炉再看一遍,经典才值得研究。
1.冒泡排序
从字面意思理解,水泡从水底冒出到水面的过程中,由小慢慢大,最后大泡泡冒出水面,了解这个物理现象就可,整个代码实现的思路也就是这样的。
步骤:
1.比较相邻元素。(若第一个比第二个大,换位)
2.每对相邻元素依次做同样工作,直到最后一对。(一轮结束,最后的元素最大,第一波冒泡完成)
3.对所有元素重复1、2步骤,除了最后一个数。
4.对越来越少的元素重复上面步骤,直到没有一对数字需要比较。
java代码
public class BubbleSort {
public static int[] sort(int[] array){
//这里for循环表示总共需要比较多少轮
for(int i = 1 ; i < array.length; i++){
//设定一个标记,若为true,则表示此次循环没有进行交换,也就是待排序列已经有序,排序已经完成。
boolean flag = true;
//这里for循环表示每轮比较参与的元素下标
//对当前无序区间array[0......length-i]进行排序
//j的范围很关键,这个范围是在逐步缩小的,因为每轮比较都会将最大的放在右边
for(int j = 0 ; j < array.length-i ; j++){
if(array[j]>array[j+1]){
int temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
flag = false;
}
}
if(flag){
break;
}
//第 i轮排序的结果为
System.out.print("第"+i+"轮排序后的结果为:");
display(array);
}
return array;
}
//遍历显示数组
public static void display(int[] array){
for(int i = 0 ; i < array.length ; i++){
System.out.print(array[i]+" ");
}
System.out.println();
}
public static void main(String[] args) {
int[] array = {4,2,8,9,5,7,6,1,3};
//未排序数组顺序为
System.out.println("未排序数组顺序为:");
display(array);
System.out.println("-----------------------");
array = sort(array);
System.out.println("-----------------------");
System.out.println("经过冒泡排序后的数组顺序为:");
display(array);
}
}
时间复杂度:
T(n)=O(n2).
2.选择排序
从字面意思理解,先选择需要的数,再将其放置需要的位置。
思路是每一次选择待排序集合中最小的数,将其放置序列起始位置,直到所有待排元素都被排完。
步骤:
1.带排序列中,找到关键字最小元素;
2.若最小元素不是待排序序列的第一个元素,将其和第一个元素互换;
3.余下元素中,找到关键字最小的元素,重复2步骤;
4.重复3步骤,直到排序结束。
Java代码:
public class ChoiceSort {
public static int[] sort(int[] array){
//总共要经过N-1轮比较
for(int i = 0 ; i < array.length-1 ; i++){
int min = i;
//每轮需要比较的次数
for(int j = i+1 ; j < array.length ; j++){
if(array[j]<array[min]){
min = j;//记录目前能找到的最小值元素的下标
}
}
//将找到的最小值和i位置所在的值进行交换
if(i != min){
int temp = array[i];
array[i] = array[min];
array[min] = temp;
}
//第 i轮排序的结果为
System.out.print("第"+(i+1)+"轮排序后的结果为:");
display(array);
}
return array;
}
//遍历显示数组
public static void display(int[] array){
for(int i = 0 ; i < array.length ; i++){
System.out.print(array[i]+" ");
}
System.out.println();
}
public static void main(String[] args){
int[] array = {4,2,8,9,5,7,6,1,3};
//未排序数组顺序为
System.out.println("未排序数组顺序为:");
display(array);
System.out.println("-----------------------");
array = sort(array);
System.out.println("-----------------------");
System.out.println("经过选择排序后的数组顺序为:");
display(array);
}
}
时间复杂度:
T(n)=O(n2) (复杂度数量级相同,但是比冒泡要快,当n较小且交换时间比选择时间大的多时,相当快)
3.插入排序
直接插入排序基本思想是每一步将一个待排序的记录,插入到前面已经排好序的有序序列中去,直到插完所有元素为止。
这里介绍最简单的插入排序,其他高级的插入排序后面会题到。
步骤:
1.取出一个待排序元素,根据关键字大小将其放置到有序序列中。
2.再取出一个待排元素,根据关键字大小将其放置到有序序列中。
3.重复步骤2,直到没有待排元素为止。
Java代码
public class InsertSort {
public static int[] sort(int[] array){
int j;
//从下标为1的元素开始选择合适的位置插入,因为下标为0的只有一个元素,默认是有序的
for(int i = 1 ; i < array.length ; i++){
int tmp = array[i];//记录要插入的数据
j = i;
while(j > 0 && tmp < array[j-1]){//从已经排序的序列最右边的开始比较,找到比其小的数
array[j] = array[j-1];//向后挪动
j--;
}
array[j] = tmp;//存在比其小的数,插入
}
return array;
}
//遍历显示数组
public static void display(int[] array){
for(int i = 0 ; i < array.length ; i++){
System.out.print(array[i]+" ");
}
System.out.println();
}
public static void main(String[] args){
int[] array = {4,2,8,9,5,7,6,1,3};
//未排序数组顺序为
System.out.println("未排序数组顺序为:");
display(array);
System.out.println("-----------------------");
array = sort(array);
System.out.println("-----------------------");
System.out.println("经过插入排序后的数组顺序为:");
display(array);
}
}
时间复杂度:
T(n)=O(n2)
总结
经过介绍,对这三种排序会更好的理解,冒泡排序最慢,选择排序将交换次数降到最低,但是比较次数多,当数据量小,并且交换数据相对于比较数据更加耗时的情况下,可以应用选择排序。
在大多数情况下,假设数据量比较小或基本有序时,插入排序是三种算法中最好的选择。