【主要内容】插入排序、冒泡排序、选择排序的通俗易懂的解释;插入排序、冒泡排序、选择排序的代码(一律用java演示);插入排序、冒泡排序、选择排序的对比。
一、插入排序
1.通俗易懂的解释
举个例子,假如说你和你的朋友正在玩斗地主,你朋友发牌,你一张一张拿牌,拿一张牌就要把它放在手里合适的位置。假设你喜欢从小到大放,那么他给你发一张牌,你只需要把这张牌和你手中已经排好序的牌组两两作比较,插入到合适的位置中(当然眼尖的一般就直接插到排好序的牌组里了)。这就是插入排序,即每次都要遍历这个数组,从前往后把待排序的号插到前面已经排好的数组中,前面已排好的序列永远是有顺序的。
2.什么?没懂?那画个图康康
3.还没懂?那来看代码吧
package sort;
import java.util.Arrays;
public class Insort {
public static void main(String[] args) {
// TODO Auto-generated method stub
int a[] = new int[8];
a[0]=42;
a[1]=20;
a[2]=17;
a[3]=13;
a[4]=28;
a[5]=14;
a[6]=23;
a[7]=15;
a = innsort(a);
}
static int[] innsort(int a[])
{
int n = a.length;
int tem[] = new int[2];
for(int i=1;i<n;i++)
{
for(int j=i;j>0&&prior(a[j],a[j-1]);j--)
{
tem = swap(a[j],a[j-1]);
a[j] = tem[0];
a[j-1] = tem[1];
}
System.out.println("现在是第"+i+"次排序,排序结果如下:");
System.out.println(Arrays.toString(a));
}
return a;
}
static Boolean prior(int a,int b)
{
return a<b;
}
static int[] swap(int a,int b)
{
int tem = a;
a = b;
b = tem;
return new int[]{a,b};
}
}
输出结果:
现在是第1次排序,排序结果如下:
[20, 42, 17, 13, 28, 14, 23, 15]
现在是第2次排序,排序结果如下:
[17, 20, 42, 13, 28, 14, 23, 15]
现在是第3次排序,排序结果如下:
[13, 17, 20, 42, 28, 14, 23, 15]
现在是第4次排序,排序结果如下:
[13, 17, 20, 28, 42, 14, 23, 15]
现在是第5次排序,排序结果如下:
[13, 14, 17, 20, 28, 42, 23, 15]
现在是第6次排序,排序结果如下:
[13, 14, 17, 20, 23, 28, 42, 15]
现在是第7次排序,排序结果如下:
[13, 14, 15, 17, 20, 23, 28, 42]
4.时间复杂度分析
可以看到,主要影响代码运行速度的是innsort方法。在最差情况下(即原先数组是逆序的),他需要每一个元素都要进行比较和交换,所以时间复杂度为Θ(n²),在最佳情况下(即数组已经排好序了),他不需要进内层for循环,故时间复杂度为Θ(n),平均下来则为Θ(n²)
二、冒泡排序
1.通俗易懂的解释
冒泡排序其实这里是不太好理解的,这样吧我说一遍过程,结合下图看食用效果更佳。遍历整个数组(从后往前,这里和插入排序不一样,插入排序是从前往后,切记不要弄混),只要后面的比前面的元素小,就把小的换到前面去,直到前面的和他一样或者比他小,就停止冒这个元素。然后继续把他前面的元素往前冒,如下图所示(小泡表示值小,大泡表示值大)
2.什么?没懂?那画个图康康
也就是说最小元素第一次就被推到了整个数组的最上面。
3.还没懂?那来看代码吧
package sort;
import java.util.Arrays;
public class Bubsort {
public static void main(String[] args) {
// TODO Auto-generated method stub
int a[] = new int[8];
a[0]=42;
a[1]=20;
a[2]=17;
a[3]=13;
a[4]=28;
a[5]=14;
a[6]=23;
a[7]=15;
System.out.println("排序前:");
System.out.println(Arrays.toString(a));
a = bubsort(a);
}
private static int[] bubsort(int[] a) {
// TODO Auto-generated method stub
int n = a.length;
int tem[] = new int[2];
for(int i=0;i<n-1;i++)
{
for(int j=n-1;j>i;j--)
{
if(prior(a[j],a[j-1]))//j比j-1要小
{
tem = swap(a[j],a[j-1]);
a[j] = tem[0];
a[j-1] = tem[1];
}
}
System.out.println("现在是第"+(i+1)+"次排序,排序结果如下:");
System.out.println(Arrays.toString(a));
}
return a;
}
static Boolean prior(int a,int b)
{
return a<b;
}
static int[] swap(int a,int b)
{
int tem = a;
a = b;
b = tem;
return new int[]{a,b};
}
}
输出结果:
排序前:
[42, 20, 17, 13, 28, 14, 23, 15]
现在是第1次排序,排序结果如下:
[13, 42, 20, 17, 14, 28, 15, 23]
现在是第2次排序,排序结果如下:
[13, 14, 42, 20, 17, 15, 28, 23]
现在是第3次排序,排序结果如下:
[13, 14, 15, 42, 20, 17, 23, 28]
现在是第4次排序,排序结果如下:
[13, 14, 15, 17, 42, 20, 23, 28]
现在是第5次排序,排序结果如下:
[13, 14, 15, 17, 20, 42, 23, 28]
现在是第6次排序,排序结果如下:
[13, 14, 15, 17, 20, 23, 42, 28]
现在是第7次排序,排序结果如下:
[13, 14, 15, 17, 20, 23, 28, 42]
4.时间复杂度分析
可以看到,主要影响代码运行速度的是bubsort方法。不管在最好最差平均情况下他都要进内循环,故复杂度为Θ(n²)
三、选择排序
1.通俗易懂的解释
这个就比较好解释了,还是拿插入排序的例子来讲,你和你朋友玩斗地主,但是这回不是发一张牌就拿一张,你是等发完牌了之后把所有牌拿起来之后整理。还是从小到大排序,这次你是选一张牌出来之后插到之前已经排好序的牌堆里。这就是选择排序。在第i次排序的时候,把未排序的里面号出来此时最小的放在第i的位置上,这个时候0~i的位置已经是整个排序序列里第0、1、2、...i小的元素。它的比较次数和冒泡一样,交换次数却只有(n-1)次。
2.什么?没懂?那画个图康康(我觉得这个就不用画图康康了吧,好吧其实是我不想画了)
假装这里有图
3.还没懂?那来看代码吧
package sort;
import java.util.Arrays;
public class Selsort {
public static void main(String[] args) {
// TODO Auto-generated method stub
int a[] = new int[8];
a[0]=42;
a[1]=20;
a[2]=17;
a[3]=13;
a[4]=28;
a[5]=14;
a[6]=23;
a[7]=15;
System.out.println("排序前:");
System.out.println(Arrays.toString(a));
a = selsort(a);
}
private static int[] selsort(int[] a) {
// TODO Auto-generated method stub
int n = a.length;
int lowindex=0;
int tem[] = new int[2];
for(int i=0;i<n-1;i++)
{
lowindex=i;
for(int j=i+1;j<n;j++)//从后往前找
{
if(prior(a[j], a[lowindex]))
{
lowindex = j;
}
}
tem = swap(a[i],a[lowindex]);
a[i] = tem[0];
a[lowindex] = tem[1];
System.out.println("现在是第"+(i+1)+"次排序,排序结果如下:");
System.out.println(Arrays.toString(a));
}
return a;
}
static Boolean prior(int a,int b)
{
return a<b;
}
static int[] swap(int a,int b)
{
int tem = a;
a = b;
b = tem;
return new int[]{a,b};
}
}
输出结果:
排序前:
[42, 20, 17, 13, 28, 14, 23, 15]
现在是第1次排序,排序结果如下:
[13, 20, 17, 42, 28, 14, 23, 15]
现在是第2次排序,排序结果如下:
[13, 14, 17, 42, 28, 20, 23, 15]
现在是第3次排序,排序结果如下:
[13, 14, 15, 42, 28, 20, 23, 17]
现在是第4次排序,排序结果如下:
[13, 14, 15, 17, 28, 20, 23, 42]
现在是第5次排序,排序结果如下:
[13, 14, 15, 17, 20, 28, 23, 42]
现在是第6次排序,排序结果如下:
[13, 14, 15, 17, 20, 23, 28, 42]
现在是第7次排序,排序结果如下:
[13, 14, 15, 17, 20, 23, 28, 42]
4.时间复杂度分析
可以看到,主要影响代码运行速度的是selsort方法。不管在最好最差平均情况下他都要进内循环,故复杂度为Θ(n²)。
四、三种排序对比
看表就完事
插入排序 | 冒泡排序 | 选择排序 | |
比较情况 | |||
最佳情况 | Θ(n) | Θ(n²) | Θ(n²) |
平均情况 | Θ(n²) | Θ(n²) | Θ(n²) |
最差情况 | Θ(n²) | Θ(n²) | Θ(n²) |
交换情况 | |||
最佳情况 | 0 | 0 | Θ(n) |
平均情况 | Θ(n²) | Θ(n²) | Θ(n) |
最差情况 | Θ(n²) | Θ(n²) | Θ(n) |
【絮絮叨叨】近期会不定期更新数据结构、操作系统、java的一些知识点总结,敬请期待。