本篇主要记录冒泡排序,选择排序,插入排序。
冒泡排序
算法思想:
如下图,先比较0与1位置上的运动员身高,若0位置身高大于1位置身高,则0与1位置上的运动员交换位置,然后从1位置开始,比较1与2位置上运动员的身高,以此类推,直至到位置9。此时,9已经是最高的了,属于有序状态,所以下次比较的时候,只需要从0位置开始比较,直至位置8即可。
不变性:
我们发现,每次经过一轮比较后,总会有一个运动员的位置不再改变了,也就是说第一次比较,你得到的是0-9位置运动员中身高最高的,并且放置在位置9,第二次比较,注意咯,此时只需要比较0-8位置上的运动员身高,得到0-8最高运动员,并且放置在位置8上,以此类推,直至无法改变。
冒泡排序效率:
通过观察可以发现,0-9个运动员,第一次需要比较9次,第二次需要比较8次,第三次7次……直到最后一趟比较一次。对于10个数据项,就是9+8+7+6+5+4+3+2+1=45,对于N项来说,就是(N-1)+(N-2)+…+1=N*(N-1)/2,而交换的次数少于比较的次数,交换次数平均大约 N2/4 次。所以,冒泡排序运行需要 O(N2) 时间级别。
核心代码:
//arr代表的是需要排序的数组
public void bubble(){
for(int out=arr.length-1;out>1;out--){
for(int inner=0;inner<out;inner++){
if(arr[inner]>=arr[inner+1]){ //比较相邻位置数据的大小
//满足条件则交换数据
int temp=0;
temp=arr[inner+1];
arr[inner+1]=arr[inner];
arr[inner]=temp;
}
}
}
}
选择排序
选择排序改进了冒泡排序,将必要的交换次数从
O(N2)
减少到
O(N)
算法思想:
进行选择排序就是把所有的队员扫描一遍,从中挑出最矮的一个运动员。最矮的运动员和站在队列最左端的队员交换位置,即站到0号位置,这是0号位置是最矮的,即下次排序并不需要参加,下次排序仅需要从1位置开始扫描。
选择排序前三次的示意图:
不变性:
每次排序后的最左端的n个数据总是有序的且位置不再改变
算法效率:
选择排序和冒泡排序执行了相同的比较次数,但是交换次数却大大减少
核心代码:
//选择排序
public void select_sort(){
int min; //记录最小数值的下标
int i,j;
for( i=0;i<arr.length-1;i++){
min=i;
for(j=i+1;j<arr.length;j++){
if(arr[j]<arr[min])
min=j; //满足条件则将下标改变为j
}
//扫描一遍后交换位置,即最小的
int temp;
temp=arr[i];
arr[i]=arr[min];
arr[min]=temp;
}
}
插入排序
算法思想:
插入排序算法是一个对少量元素进行排序的有效算法。插入排序的工作原理与打牌时整理手中的牌的做法类似,开始摸牌时,我们的左手是空的,接着一次从桌上摸起一张牌,并将它插入到手的正确位置。为了找到这张牌的正确位置,要将它与手中已有的牌从右到左进行比较,无论什么时候手中的牌都是排序好的。
示意图:
当发现”被标记”队员大于左边某个运动员的身高时,这个”被标记”的运动员先出列,腾出位置,让那些运动员往后移,腾出一个位置给这个”被标记”的运动员入列。
不变性:
在每趟结束时,在将temp(“被标记”的运动员的信息)位置的项插入后,左侧的数据项是局部有序的
算法效率:
复制的次数大致等于比较的次数。然而,一次复制与一次交换的时间耗费不同,所以相对于随机数据,插入算法比冒泡排序快一倍,比选择排序略快。
在任意情况下,对于随机顺序的数据排序进行插入排序需要 O(N2) 的时间级。
如果数据基本有序,插入排序几乎只需要 O(N) 。
然而,对于逆序排序的数据,每次比较和移动都会执行,所以插入排序不比冒泡排序快。
核心代码:
//插入排序算法
public void insert_sort(){
int in;
for(in=1;in<arr.length;in++){//从位置1开始
int temp=arr[in];
while(in>0&&arr[in-1]>=temp){ //位置in与位置in-1元素大小比较
arr[in]=arr[in-1]; //满足条件,依次向右移动
--in;
}
arr[in]=temp; //补位置,填坑
}
}
几种简单排序之间的比较:
选择排序虽然把交换次数降到了最低,但比较的次数仍然很大。当数据量很小,并且交换数据相对于比较数据更加耗时的情况下,可以应用选择排序。
在大多数情况下,假设当数据量比较小或基本上有序时,插入排序算法是三种简单排序算法中最好的选择。对于更大数据量的排序来说,快速排序通常是最快的方法。
PS:不变性指在算法运行时保持不变的条件。
参考资料:Java数据结构和算法(第二版)