1、求数组中的最大值
emm…先来个简单点的算法热热身.奥利给
//求数组的最大值和最小值public class Test5{ public static void main(String[] args){
int[]num={12,3,54,67,88,34}; int max=max(num); int min=min(num);
System.out.println(max);
System.out.println(min);
} public static int max(int[] num){ int max=num[0]; int numLen=num.length; for(int i=1;i<numLen;i++){ if(num[i]>max)
max=num[i];
} return max;
} public static int min(int[] num){ int min=num[0]; int numLen=num.length; for(int i=1;i<numLen;i++){ if(num[i]<min)
min=num[i];
} return min;
}
}
2、冒泡排序
数组排序在面试中也会经常会遇到到,面试官通过基本的排序算法来了解你对程序基本算法的了解,我们先学习一下最稳定的排序方式冒泡排序!
//冒泡排序第一版public class Test6{ /*
比较相邻的元素。如果第一个比第二个大,就交换他们两个。
对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
针对所有的元素重复以上的步骤,除了最后一个。
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法。
5 8 6 3 9 2 1 7 一堆乱序的数字,对他排序
5 6 3 8 2 1 7 9 第一轮
5 3 6 2 1 7 8 第二轮
3 5 2 1 6 7 第三轮
3 2 1 5 6 第四轮
2 1 3 5 第五轮
1 2 3 第六轮 现在顺序已经出来了 但是我们不能保证其他数组排到 第六轮 就能排出来
1 2 第七轮
*/
public static void main(String[] args){
int[] nums={5,8,6,3,9,2,1,7}; //外循环控制轮数
int times=nums.length-1;//轮数等于数组长度减1
for(int i=0;i<times;i++){ for(int j=0;j<times-1-i;j++){ if(nums[j]>nums[j+1]){//交换位置
nums[j]=nums[j]+nums[j+1];
nums[j+1]=nums[j]-nums[j+1];
nums[j]=nums[j]-nums[j+1];
}
}
} //输出结果
for(int n:nums){
System.out.println(n);
}
}
}
我们发现第六轮已经排完了,第七轮就没有必要排了嘛,但是算法还是认真的执行了第七轮比较了下去,在这种情况下我们可衣判断一下数组是否有序,如果有序就直接结束循环,,提高效率
//冒泡排序第二版public class Test6{ /*
我们用一个bool来标记是否有序,初始值为true
*/
public static void main(String[] args){
int[] nums={5,8,6,3,9,2,1,7}; boolean isSorted=true; //外循环控制轮数
int times=nums.length-1;//轮数等于数组长度减1
for(int i=0;i<times;i++){ for(int j=0;j<times-1-i;j++){ if(nums[j]>nums[j+1]){//交换位置
nums[j]=nums[j]+nums[j+1];
nums[j+1]=nums[j]-nums[j+1];
nums[j]=nums[j]-nums[j+1];
isSorted=flase;//如果发生了数组交换,所以数组不是有序把 标志变成false
}
} if(isSorted){ break;
}
} //输出结果
for(int n:nums){
System.out.println(n);
}
}
}
这只是冒泡排序的一个点,为了说明问题我们用一个新数列来讲解一下,
3 4 2 1 5 6 7 8
这个数列后四个是有序的,前边四个是无序的但是,我们每一轮排序的时候,后边四个都需要比较
第一轮
3和4比较 4和2比较 4和1比较 4和5比较 5和6比较 6和7比较 7和8比较
第一轮结果
3 2 1 4 5 6 7 8
第二轮
3和2比较 3和1比较 3和4比较 4和5比较 5和6比较 6和7比较 7和8比较
第二轮结果
2 1 3 4 5 6 7 8
第三轮
2和1比较 2和3比较 3和4比较 4和5比较 5和6比较 6和7比较 7和8比较
第三轮结果
1 2 3 4 5 6 7 8
我们发现什么了 发现后边都有顺序了但是我们还是比较了很多次,冒泡排序第二个优化的点就是数列有序区的界定
我们可以在每一轮排序后,记录一下数组最后一次交换的位置,该位置就是无序数列的边界,再往后就是有序区了,直接上代码
//冒泡排序第三版public class Test6{ /*
我们用一个bool来标记是否有序,初始值为true
*/
public static void main(String[] args){
int[] nums={3,4,2,1,5,6,7,8}; boolean isSorted=true; //外循环控制轮数
//无序序列的边界,每次比较到这里就可以了
int sortedBorder=nums.length-1; int times=nums.length-1;//轮数等于数组长度减1
for(int i=0;i<times;i++){ for(int j=0;j<sortedBorder;j++){ if(nums[j]>nums[j+1]){//交换位置
nums[j]=nums[j]+nums[j+1];
nums[j+1]=nums[j]-nums[j+1];
nums[j]=nums[j]-nums[j+1];
isSorted=flase;//如果发生了数组交换,所以数组不是有序把 标志变成false
sortedBorder=j
}
} if(isSorted){ break;
}
} //输出结果
for(int n:nums){
System.out.println(n);
}
}
}
为什么说冒泡是稳定的排序算法呢,如果数组中有相同的元素的话 排序完他俩的位置没有改变,
5 8 8 3 9 2 1 7,现在我们给第一个8标号 1, 第二个8标号2 ,使用冒泡排完序,数组的第1个位置还是1号的8,第2个位置还是2号的8,所以它的排序是稳定,既然有稳定的排序方式,那么就有不稳定的排序方式,来我们继续。。
3、选择排序
//选择排序public class Test7{ /*每一趟从待排序的数据元素中选出最小(或最大)的一个元素,
顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完。
选择排序是不稳定的排序方法。
34,4,56,17,90,65
4 34 56 17 90 65 第一轮
4 17 56 34 90 65 第二轮
4 17 34 56 90 65 第三轮
4 17 34 56 90 65 第四轮
4 17 34 56 65 90 第五轮
*/
public static void main(String[] args){
int[] nums={34,4,56,17,90,65};//待排序的数列
int minIndex=0;//用于记录每次比较的最小值下标
int times=nums.length-1; //控制轮数
for(int i=0;i<times;i++){
minIndex=i;//每轮假设一个最小值下标
for(int j=i+1;j<nums.length;j++){ if(nums[minIndex]>nums[j]){
minIndex=j;
}
} //判断需要交换的数下标是否为自己
if(minIndex!=i){
nums[minIndex]=nums[minIndex]+nums[i];
nums[i]=nums[minIndex]-nums[i];
nums[minIndex]=nums[minIndex]-nums[i];
}
} //输出结果
for(int n:nums){
System.out.println(n);
}
}
}
选择排序,它比较的次数和冒泡是一样的但是一轮就交换了一次,所以它效率比较高,但是它不稳定,很有可能两个相同的元素他们位置会互换,如果不考虑稳定性,建议使用选择排序!
选择排序排完,咱们趁热打铁,直接插入排序..
4、直接插入排序算法
插入排序思路: 34,4,56,17,90,65
第一轮
从下标1 开始 把下标1当做操作数,把操作数用一个临时变量存起来,然后和前一个比较,如果第0个数大于操作数,那么整个数列往后移,怎么个移法呢,就是操作数的下标位置等于 第0个数 4变成34,第一轮就算结束了,然后看发生变化的变量是操作数自己吗不是就吧操作数赋给它
第二轮
操作数变成了56, 操作数和34比 34小,所以操作数一定大于34 前边的所有的数,所以就不用比较了,第二轮结束,也不用交换变量
第三轮
操作数变成了17, 操作数和56 比 操作数比较小,所以56往后移,17位置的数变成56,然后操作数再和34比,比34还小,那么34往后移最开始的56变成34,操作数和4比,操作数大于4,结束第三轮 然后最后往后移的数的位置变成操作数,也就是17,第三轮结束,依次往下进行,我们看代码
//插入排序public class Test8{ /*
34,4,56,17,90,65
*/
public static void main(String[] args){
int[] nums={34,4,56,17,90,65};//待排序的数列
int times=nums.length; for(int i=1;i<times;i++){ int temp=nums[i];//记录操作数
int j=0; for(j=i-1;j>=0;j--){ if(nums[j]>temp){
nums[j+1]=nums[j];
}else{ break;
}
} //判断需要交换的数下标是否为自己
if(nums[j+1]!=temp){
nums[j+1]=temp;
}
} //输出结果
for(int n:nums){
System.out.println(n);
}
}
}
小结
这几种常用的排序算法,先介绍到这里,肯定有小伙伴问?有没有比冒牌要快的排序算法呢?那是当然有啦,比如快速排序,归并排序和堆排序等等.由于有写算法设计到数据结构,所以不打算在这个系列里写,但是肯定会写的.