冒泡排序的三种实现(Java)
冒泡排序是非常好理解的,以从小到大排序为例,每一轮排序就找出未排序序列中最大值放在最后。
设数组的长度为N:
(1)比较前后相邻的二个数据,如果前面数据大于后面的数据,就将这二个数据交换。
(2)这样对数组的第0个数据到N-1个数据进行一次遍历后,最大的一个数据就“沉”到数组第N-1个位置。
(3)N=N-1,如果N不为0就重复前面二步,否则排序完成。
以上就是冒泡排序的基本思想,按照这个定义很快就能写出代码:
/**
* 冒泡排序的第一种实现, 没有任何优化
* @param a
* @param n
*/
public static void bubbleSort1(int [] a, int n){
int i, j;
for(i=0; i<n; i++){//表示n次排序过程。
for(j=1; j<n-i; j++){
if(a[j-1] > a[j]){//前面的数字大于后面的数字就交换
//交换a[j-1]和a[j]
int temp;
temp = a[j-1];
a[j-1] = a[j];
a[j]=temp;
}
}
}
}// end
给出一个测试代码:
public static void main(String[] args) {
int[] arr = {1,1,2,0,9,3,12,7,8,3,4,65,22};
BubbleSort.bubbleSort1(arr, arr.length);
for(int i:arr){
System.out.print(i+",");
}
}
运行结果:
0,1,1,2,3,3,4,7,8,9,12,22,65,
下面开始考虑优化,如果对于一个本身有序的序列,或则序列后面一大部分都是有序的序列,上面的算法就会浪费很多的时间开销,这里设置一个标志flag,如果这一趟发生了交换,则为true,否则为false。明显如果有一趟没有发生交换,说明排序已经完成。
/**
* 设置一个标志,如果这一趟发生了交换,则为true,否则为false。明显如果有一趟没有发生交换,说明排序已经完成。
* @param a
* @param n
*/
public static void bubbleSort2(int [] a, int n){
int j, k = n;
boolean flag = true;//发生了交换就为true, 没发生就为false,第一次判断时必须标志位true。
while (flag){
flag=false;//每次开始排序前,都设置flag为未排序过
for(j=1; j<k; j++){
if(a[j-1] > a[j]){//前面的数字大于后面的数字就交换
//交换a[j-1]和a[j]
int temp;
temp = a[j-1];
a[j-1] = a[j];
a[j]=temp;
//表示交换过数据;
flag = true;
}
}
k--;//减小一次排序的尾边界
}//end while
}//end
运行测试main函数结果:
0,1,1,2,3,3,4,7,8,9,12,22,65,
再进一步做优化。比如,现在有一个包含1000个数的数组,仅前面100个无序,后面900个都已排好序且都大于前面100个数字,那么在第一趟遍历后,最后发生交换的位置必定小于100,且这个位置之后的数据必定已经有序了,也就是这个位置以后的数据不需要再排序了,于是记录下这位置,第二次只要从数组头部遍历到这个位置就可以了。如果是对于上面的冒泡排序算法2来说,虽然也只排序100次,但是前面的100次排序每次都要对后面的900个数据进行比较,而对于现在的排序算法3,只需要有一次比较后面的900个数据,之后就会设置尾边界,保证后面的900个数据不再被排序。
public static void bubbleSort3(int [] a, int n){
int j , k;
int flag = n ;//flag来记录最后交换的位置,也就是排序的尾边界
while (flag > 0){//排序未结束标志
k = flag; //k 来记录遍历的尾边界
flag = 0;
for(j=1; j<k; j++){
if(a[j-1] > a[j]){//前面的数字大于后面的数字就交换
//交换a[j-1]和a[j]
int temp;
temp = a[j-1];
a[j-1] = a[j];
a[j]=temp;
//表示交换过数据;
flag = j;//记录最新的尾边界.
}
}
}
}
这种方法是我看到的最优化的冒泡排序了。
运行测试例子结果:
0,1,1,2,3,3,4,7,8,9,12,22,65,
- 1
可知运行结果正确。
冒泡排序的三种实现(Java)的更多相关文章
- c#之冒泡排序的三种实现和性能分析
冒泡排序算法是我们经常见到的尤其是子一些笔试题中. 下面和大家讨论c#中的冒泡排序,笔者提供了三种解决方案,并且会分析各自的性能优劣. 第一种估计大家都掌握的,使用数据交换来实现,这种就不多说了,园子 ...
- 文件上传的三种模式-Java
文件上传的三种方式-Java 前言:因自己负责的项目(jetty内嵌启动的SpringMvc)中需要实现文件上传,而自己对java文件上传这一块未接触过,且对 Http 协议较模糊,故这次采用渐进的方 ...
- 三种迭代Java ArrayList方法及比较
闲来无事,研究一下Java Collection,首先是ArrayList. 通过三种方式遍历了长度为100000的ArrayList. import java.util.*; public clas ...
- 冒泡排序算法的C++,Java和Python实现和冒泡排序算法三种语言效率的比较
冒泡排序原理: 这一篇百度经验讲得很好,我不多说了 https://jingyan.baidu.com/article/6525d4b13f920bac7d2e9484.html 他讲的是C语言,没有 ...
- rabbitmq direct、fanout、topic 三种Exchange java 代码比较
Producer端 1.channel的创建 无论是才用什么样的Exchange,创建channel代码都是相同的,如下 ConnectionFactory factory = new Connect ...
- Java中获取键盘输入值的三种方法
Java中获取键盘输入值的三种方法 Java程序开发过程中,需要从键盘获取输入值是常有的事,但Java它偏偏就没有像c语言给我们提供的scanf(),C++给我们提供的cin()获取键盘输入值 ...
- 三种方式上传文件-Java
前言:负责,因为该项目他(jetty嵌入式开始SpringMvc)实现文件上传的必要性,并拥有java文件上传这一块还没有被曝光.并 Http 更多晦涩协议.因此,这种渐进的方式来学习和实践上载文件的 ...
- Java并发编程:Java创建线程的三种方式
目录 引言 创建线程的三种方式 一.继承Thread类 二.实现Runnable接口 三.使用Callable和Future创建线程 三种方式的对比 引言 在日常开发工作中,多线程开发可以说是必备技能 ...
- Java的三种循环:1、for循环 2、while循环 3、do...while循环
Java的三种循环 Java三种循环结构: 1.for循环 2.while循环 3.do...while循环 循环结构组成部分:1.条件初始化语句,2.条件判断语句 , 3.循环体语句,4.条件控制语 ...
随机推荐
- HDOJ 1534 Schedule Problem 差分约束
差分约数: 求满足不等式条件的尽量小的值---->求最长路---->a-b>=c----> b->a (c) Schedule Problem Time Limit: 2 ...
- react-native 常见问题 及 解决方案
一.报错 Warning:Navigator:isMounted is deprecated. Instead, make sure to clean up subscriptions and pen ...
- ESLint检测JavaScript代码
1.安装 有2中安装方式:全局安装和局部安装. 局部安装方式为: (1)cnpm install -g eslint (2)打开项目目录.配置eslint文件 eslint --init (3)执行e ...
- linux生成指定大小的文件(转)
# dd if=/dev/zero of=50M.file bs=1M count=50在当前目录下生成一个50M的文件 虚拟块设备文件更通用的名称是硬盘镜像文件(Hard Disk Image),但 ...
- nginx 直接返回状态码
server { listen 80; server_name service.aaa.com; location / { add_header Content-Type "text/pla ...
- Unmapped Spring configuration files found.
© 版权声明:本文为博主原创文章,转载请注明出处 1.问题描述: 搭建SSH框架后,IDEA弹出如下提示: 2.解决方案: File --> Project Structure --> M ...
- Linux系统下如何监测磁盘的使用空间
不管是我们在安装软件还是监测软件的使用性能,我们都要随时掌握系统磁盘的使用情况. 使用df命令 df df命令用于显示磁盘分区上的可使用的磁盘空间.默认显示单位为KB.可以利用该命令来获取硬盘被占用了 ...
- Verilog利用$fdisplay命令往文件中写入数据
最近在做的事情是,用FPGA生成一些满足特定分布的序列.因此为了验证我生成的序列是否拥有预期的性质,我需要将生成的数据提取出来并且放到MATLAB中做数据分析. 但是网上的程序很乱,表示看不懂==其实 ...
- .net验证控件,导航控件
一.客户端验证(用户体验,减少服务器端压力) 二.服务器端验证(防止恶意攻击,客户端js很容易被绕过) 验证控件:RequiredFieldValidator:字段必填:RangeValidator: ...
- AccessibilityService 官网介绍
AccessibilityService extends Service java.lang.Object ↳ android.content.Context ↳ android.co ...