您的位置:首页 > 编程语言 > Java开发

Java算法实现之冒泡排序及优化

2017-02-14 15:14 483 查看
冒泡排序,是一种很简单的排序算法。原理就不过多介绍了,直接入手demo。

需求:输入一组数据,用冒泡排序进行排序。

先用最直接的方法进行排序,代码如下:

//对一组数进行冒泡排序
public class Bubble01 {
public static void main(String[] args) {
int flag = 0;//用于记录次数
int num[] = {1,23,54,5,21,51,41,23,15,47};//模拟输入数组
for (int i = 0; i < num.length - 1; i++) {//外层循环,用于控制循环次数。一共需要循环n(数组大小)-1次
for (int j = 1; j < num.length - i; j++) {//内层循环,用于数据比较第一次比0~n的数第二次0~n-1……
if(num[j] < num[j-1]){
int temp = num[j];
num[j] = num[j-1];
num[j-1] = temp;
}
flag++;//记录次数
}
}
for (int i : num) {
System.out.print(i + " ");//输出目标数组
}
System.out.println("\n循环次数:" + flag);//输出循环次数
}
}
输出结果:

1 5 15 21 23 23 41 47 51 54 
循环次数:45
但是,这种效率是很低的,我们仔细想想,如果数组是 1 2 4 3 5 6 7 8 9,按照上面的方法,第一次循环,在3和4交换之后,数组变成 1 2 3 4 5 6 7 8 9,按照第一种方法来说,接下来会进行 1 2 3 4 5 6 7 8的第二次循环,可是我们可以明显知道,接下来是不应该继续下去了,已经成为了有序数列。那么我们应该怎么样减少“浪费”的循环呢?于是我们可以设置一个循环标记isExit,在下一次循环之前,我们把这个标记设为false,如果在下一次循环里面有数字的交换,那么说明下一次循环之后的结果不一定是排序好的结果,直到接下来循环没有出现过数字的交换的时候,那么这次一定为排序后的序列。

理解起来很简单,优化方式一,代码如下:

//冒泡排序优化版本1
public class Bubble02 {
public static void main(String[] args) {
int flag = 0;//用于记录次数
int num[] = {1,23,54,5,21,51,41,23,15,47};//模拟输入数组
boolean isExit = true;//是否继续循环标志
int j = num.length;//下次循环截止位置
while(isExit){
isExit = false;//如果for循环完成之后,该标记未改变说明数组已经为有序,则退出循环。
for (int i = 1; i < j; i++) {
if(num[i] < num[i-1]){
int temp = num[i];
num[i] = num[i-1];
num[i-1] = temp;
isExit = true;//如果for循环完成之后,该标记已经改变说明数组可能还未有序,则继续循环。
}
flag++;//记录次数
}
j--;//下一次就减少一位
}
for (int i : num) {
System.out.print(i + " ");//输出目标数组
}
System.out.println("\n循环次数:" + flag);//输出循环次数

}
}
输出结果:

1 5 15 21 23 23 41 47 51 54 
循环次数:42
哈哈,循环次数确实减少了呢!但是我们再仔细想一想,数组1 2 4 3 5 6 7 8 9,第一次循环交换结束后为 1 2 3 4 5 6 7 8 9,则接下来进行第二次循环,循环范围为 1 2 3 4 5 6 7 8,按照第一种优化方式,我们会把数组 1 2 3 4 5 6 7 8全部比一遍,发现已经没有数字交换了,那么应该为排序数组了,符合了要求。但是我们第二次有必要去把 1 2 3 4 5 6
7 8全部比一遍吗?我们交换了 4 3的位置,后面的5 6 7 8 9并没有交换,则可以默认交换位置之后的数列为有序数列,所以第二次其实只需要看1 2 3 4 是不是有序数列就可以了,这样也减少了大量的次数呢!

优化方式二,代码如下。

//冒泡排序优化版本2
public class Bubble03 {
public static void main(String[] args) {
int flag = 0;//用于记录次数
int num[] = {1,23,54,5,21,51,41,23,15,47};//模拟输入数组
boolean isExit = true;//是否继续循环标志
int j = num.length;//下次循环截止位置
int k = 0;//记录最后一次交换的位置,k之后的说明已经是排好顺序的了
while(isExit){
isExit = false;
for (int i = 1; i < j; i++) {
if(num[i] < num[i-1]){
int temp = num[i];
num[i] = num[i-1];
num[i-1] = temp;
k = i;//记录交换位置
isExit = true;
}
flag++;//记录次数
}
j = k;//下次循环的截止位置应该是为最后一次交换的位置
}
for (int i : num) {
System.out.print(i + " ");//输出目标数组
}
System.out.println("\n循环次数:" + flag);//输出循环次数
}
}
输出结果:

1 5 15 21 23 23 41 47 51 54 
循环次数:38


优化方式是自己摸索出来的,也不知道是否正确,如有不正确的地方,欢迎点评。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: