先来个总结
以军训为背景,选择排序:把一队最矮的丢在最左边,然后把一队第二矮的丢在左边第二个位置,…
冒泡排序,教官抓住队伍二个人,把他们对比升高,矮的丢在左边,然后刚刚换了顺序的矮子左边判断
插入排序法:先把最右边的人拖出来,然后站在队伍面前,找到合适身高的位置,把它丢进去
选择排序
选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是每一次从待排序的数据元素中选出最小(或最
大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。
选择排序(从小到大),选出最小的放入元素的起始位置;
1:外循环,遍历要循环的数组;
2;内循环,从最后一位开始,逐步与数组第一位对比,如果小就交换,最终最小的值传入a[0]
3:结束后从外循环开始,要放置的位置变为数组第二位(i++)
程序选择最小的数字,放入开头,时间复杂度为O(n^2-(1+n)n/2
=O(n^2)
public static void selectionSort(int[] array) {
int tmp=0;
int leng=array.length-1;
int sum=0;
for(int i=0;i<=leng;i++) {
for(int j=leng;j>i;j--) {
if(array[j]<array[i]) {
tmp=array[j];
array[j]=array[i];
array[i]=tmp;
}
sum++;
}
}
System.out.println(sum);
}
冒泡排序
指针重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越大的元素会经由交换慢慢“浮”到数列的顶端,故名
外循环控制轮数,交换最终都会在内循环内进行完
内循环把最大的数丢在数组最末端,(因为最末端已经使用.那么我们修改下一次循环不经过最右端)
for(int i=0;i<leng-1;;i++)
for(int j=0;j<leng-1;j++)程序依旧可以进行,只是会有多余的循环
public static void bubbleSort(int[] array) {
int tmp=0;
int sum=0;
int leng=array.length;
for(int i=leng-1;i>0;i--) {
for(int j =0;j<i;j++) {
if(array[j]>array[j+1]) {
tmp=array[j];
array[j]=array[j+1];
array[j+1]=tmp;
}sum++;
}}
System.out.println(sum);
}
冒泡与选择
选择排序是每次都和最顶端或者最末端比较,然后交换最(大/小)的数;
冒泡是在每次只和旁边的数比,把(大于/小于)的数交换;
乍一看貌似没什么区别,通过程序运行次数后得都是36次;测试数组({ 23, 1, 32, 63, 7 ,32,61,3,8}?
但冒泡可以优化!
我们知内循环是交换旁边的值,但是如果整个内循环没有一次交换? 那么是不是代表程序已经完成了,不需要有多余的循环了!
public static void bubbleSort(int[] array) {
int tmp=0;
int sum=0;
int leng=array.length;
boolean lock = true;
for(int i=leng-1;i>0&&lock;i--) {
lock = false;
for(int j =0;j<i;j++) {
if(array[j]>array[j+1]) {
tmp=array[j];
array[j]=array[j+1];
array[j+1]=tmp;
lock = true;
}sum++;
}}
System.out.println(sum);
}
给程序加锁后,发现次数减少2次,数组改为 { 1,2,3,4,5,6,7,8,9,10,11,12};时候,冒泡仅仅运行11次,而选择需要66次,得出结论,如果不加锁,那么冒泡和选择排序是一样的时间O(n^2),但是加完锁后,如果后面顺序是对的,那么会直接跳过;
插入排序法
直接插入排序是一种简单的插入排序法,其基本思想是:把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列。
一个排序好的数组为a={1,2,3,4,5},设要插入的数为2,那么通过遍历数组,找到比2小的数组坐标,a{0},
那么插入为{1,2,2,3,4,5};
插入排序假设数组是顺序是对的,然后以坐标a[i]为要插入的值,依次进行大小对比,找到要插入的位置
外循环从下标1开始,表示要插入的数,tmp和j分别记录数值和要插入的下标
内循环首先要求J>0,不能下标越界, 判断前一个数是否大于要插入的数tmp
如果是的,那么把前一个 数放在后一个坐标位置 ,然后下标j-1,再与前前的数对比.
如果没有大于的值了,那么把数插入当前下标a[J]
简化
从下标a[i]开始.把下标a[i]当做要插入的数,下标a[i]前面的数为已经排序好的数组,即可
public static void insertSrot(int[] array) {
int tmp=0;
int j=0;
for(int i =1;i<array.length;i++) {
tmp=array[i];
j=i;
while(j>0&&array[j-1]>=tmp) {
array[j]=array[--j];
}
array[j]=tmp;
}
}