- 使用 Spring Initializr 创建 Spring Boot 应用程序
- 在Spring Boot中配置Cassandra
- 在 Spring Boot 上配置 Tomcat 连接池
- 将Camel消息路由到嵌入WildFly的Artemis上
冒泡排序(Bubble Sorting)的基本思想是通过对待排序序列从前向后(从下表较小的元素开始),以此比较相邻元素的值,若发现逆序则交换,使值较大的元素逐渐从前向后部,就像水底下的气泡一样逐渐向上冒。
我们举一个具体的案例来说明冒泡排序法,我们将几个无序的数:3,6,4,2,11,10,5 使用冒泡排序法将其排成一个从小到大的有序数列。
看上面的图解可能有些小伙伴不好理解,不过没关系下面我们更详细的给大家列出排序细节。
原始数组为:3,6,4,2,11,10,5 下面进行第一趟排序
3,6,4,2,11,10,5
3,4,6,2,11,10,5
3,4,2,6,11,10,5
3,4,2,6,11,10,5
3,4,2,6,10,11,5
3,4,2,6,10,5,11
第一趟排序的最终结果为:3,4,2,6,10,5,11 下面进行第二趟排序
3,4,2,6,10,5,11
3,2,4,6,10,5,11
3,2,4,6,10,5,11
3,2,4,6,10,5,11
3,2,4,6,5,10,11
需要注意的是每趟运行过后最后一个数就会被确认下来,不在进行比较交换。现在我们重新回到上方排序交换图,是不是思路一下就清晰起来了?
冒泡排序规则总结:
原始数组为:3,6,4,2,11,10,5 下面进行第一趟排序
public static void main(String[] args) {
int arr[] = {3, 6, 4, 2, 11, 10, 5};
//为了容易理解,我们把冒泡排序的演变过程,给大家展示一下。
//第一趟排序,就是将最大的数排在最后
int temp = 0; //临时变量
for (int j = 0; j < arr.length - 1; j++) {
//如果前面的数比后面的数大,则交换
if (arr[j] > arr[j + 1]) {
temp = arr[j];
arr[j] = arr[j + 1];
arr[j+1] = temp;
}
}
System.out.println("第一趟排序后的数组");
System.out.println(Arrays.toString(arr));
}
第一趟排序的最终结果为:3,4,2,6,10,5,11 下面进行第二趟排序
public static void main(String[] args) {
int arr[] = {3, 6, 4, 2, 11, 10, 5};
//为了容易理解,我们把冒泡排序的演变过程,给大家展示一下。
//第一趟排序,就是将最大的数排在最后
int temp = 0; //临时变量
for (int j = 0; j < arr.length - 1; j++) {
//如果前面的数比后面的数大,则交换
if (arr[j] > arr[j + 1]) {
temp = arr[j];
arr[j] = arr[j + 1];
arr[j+1] = temp;
}
}
System.out.println("第一趟排序后的数组");
System.out.println(Arrays.toString(arr));
//第二趟排序,就是将第二大的数排在倒数第二位
for (int j = 0; j < arr.length - 1 - 1; j++) {
//如果前面的数比后面的数大,则交换
if (arr[j] > arr[j + 1]) {
temp = arr[j];
arr[j] = arr[j + 1];
arr[j+1] = temp;
}
}
System.out.println("第二趟排序后的数组");
System.out.println(Arrays.toString(arr));
}
第二次排序后得到得最终结果为:3, 2, 4, 6, 5, 10, 11 以此类推下面我们直接进行六次排序看看最终的结果是否与我们预期的一致。
public static void main(String[] args) {
int arr[] = {3, 6, 4, 2, 11, 10, 5};
//为了容易理解,我们把冒泡排序的演变过程,给大家展示一下。
//第一趟排序,就是将最大的数排在最后
int temp = 0; //临时变量
for (int j = 0; j < arr.length - 1; j++) {
//如果前面的数比后面的数大,则交换
if (arr[j] > arr[j + 1]) {
temp = arr[j];
arr[j] = arr[j + 1];
arr[j+1] = temp;
}
}
System.out.println("第一趟排序后的数组");
System.out.println(Arrays.toString(arr));
//第二趟排序,就是将第二大的数排在倒数第二位
for (int j = 0; j < arr.length - 1 - 1; j++) {
//如果前面的数比后面的数大,则交换
if (arr[j] > arr[j + 1]) {
temp = arr[j];
arr[j] = arr[j + 1];
arr[j+1] = temp;
}
}
System.out.println("第二趟排序后的数组");
System.out.println(Arrays.toString(arr));
//第二趟排序,就是将第三大的数排在倒数第三位
for (int j = 0; j < arr.length - 1 - 2; j++) {
//如果前面的数比后面的数大,则交换
if (arr[j] > arr[j + 1]) {
temp = arr[j];
arr[j] = arr[j + 1];
arr[j+1] = temp;
}
}
System.out.println("第三趟排序后的数组");
System.out.println(Arrays.toString(arr));
//第二趟排序,就是将第四大的数排在倒数第四位
for (int j = 0; j < arr.length - 1 - 3; j++) {
//如果前面的数比后面的数大,则交换
if (arr[j] > arr[j + 1]) {
temp = arr[j];
arr[j] = arr[j + 1];
arr[j+1] = temp;
}
}
System.out.println("第四趟排序后的数组");
System.out.println(Arrays.toString(arr));
//第二趟排序,就是将第五大的数排在倒数第五位
for (int j = 0; j < arr.length - 1 - 4; j++) {
//如果前面的数比后面的数大,则交换
if (arr[j] > arr[j + 1]) {
temp = arr[j];
arr[j] = arr[j + 1];
arr[j+1] = temp;
}
}
System.out.println("第五趟排序后的数组");
System.out.println(Arrays.toString(arr));
//第二趟排序,就是将最小的数排在第一位
for (int j = 0; j < arr.length - 1 - 5; j++) {
//如果前面的数比后面的数大,则交换
if (arr[j] > arr[j + 1]) {
temp = arr[j];
arr[j] = arr[j + 1];
arr[j+1] = temp;
}
}
System.out.println("最后一趟排序后的数组");
System.out.println(Arrays.toString(arr));
}
不知道大家看完六次排序的代码发现什么规律没有,分开写只是方便大家理解实际过程中只需要一个双重循环就可以解决代码冗余的问题。
public static void main(String[] args) {
int arr[] = {3, 6, 4, 2, 11, 10, 5};
int temp = 0; //临时变量
for (int i=0; i< arr.length -1; i++) {
for (int j = 0; j < arr.length - 1 -i; j++) {
//如果前面的数比后面的数大,则交换
if (arr[j] > arr[j + 1]) {
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
System.out.println("第"+(i+1)+"趟排序后的数组");
System.out.println(Arrays.toString(arr));
}
}
当进行六次排序后还有一位数还需不需要进行第七次排序了?答案是不需要,因为确定了六个数据的位置已经没必要知道第七个数据的位置了。对比上图,虽然我们最终的结果正确了,但是大家有么有发现在第三次排序之后已经成功了。后续的数据都是一样的结果,那么针对这种情况怎么优化呢?后面会给大家讲到!
针对上面提出的情况怎么优化呢?因为排序的过程中,各元素不断接近自已的位置,如果一趟比较下来没有进行过交换,就说明序列有序,因此要在排序过程中设置一个标志flag判断元素是否进行过交换。从而减少不必要的比较。话不多说直接上代码!
public static void main(String[] args) {
int arr[] = {3, 6, 4, 2, 11, 10, 5};
System.out.println("排序前");
System.out.println(Arrays.toString(arr));
//测试冒泡排序
bubbleSort(arr);
System.out.println("排序后");
System.out.println(Arrays.toString(arr));
}
public static void bubbleSort(int[] arr){
boolean flag = false; //标识变量,表示是否进行过交换
int temp = 0; //临时变量
for (int i=0; i< arr.length -1; i++) {
for (int j = 0; j < arr.length - 1 -i; j++) {
//如果前面的数比后面的数大,则交换
if (arr[j] > arr[j + 1]) {
flag = true; //表示交换过
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
if (!flag){ //在一趟排序中,一次交换都没有发生过
break;
}else {
flag = false; //重置flag,进行下次判断
}
}
}
优化后的代码,在for循环的运行中没有进行交换就会走到break退出代码。
冒泡排序的速度为O(n的二次方),假如我们给数据组加入80000条数据我们来测试一下冒泡排序的性能到底如何。
public static void main(String[] args) {
// int arr[] = {3, 6, 4, 2, 11, 10, 5};
int arr[] = new int[80000];
for (int i = 0;i<arr.length;i++){
arr[i] = (int) (Math.random() * 8000000); //生成一个0-8000000的数
}
Date date1 = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date1Str = dateFormat.format(date1);
System.out.println("排序前的时间为:"+date1Str);
//测试冒泡排序
bubbleSort(arr);
Date date2 = new Date();
String date2Str = dateFormat.format(date2);
System.out.println("排序后的时间为:"+date2Str);
}
public static void bubbleSort(int[] arr){
boolean flag = false; //标识变量,表示是否进行过交换
int temp = 0; //临时变量
for (int i=0; i< arr.length -1; i++) {
for (int j = 0; j < arr.length - 1 -i; j++) {
//如果前面的数比后面的数大,则交换
if (arr[j] > arr[j + 1]) {
flag = true; //表示交换过
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
if (!flag){ //在一趟排序中,一次交换都没有发生过
break;
}else {
flag = false; //重置flag,进行下次判断
}
}
}
经过我们的多次执行,发现冒泡排序在处理八万条数据的时间大概为十秒左右由此可见冒泡排序的性能并不高!
我在 Angular 项目中使用了来自 Github 的模块项目,它可以让我调整 DOM 元素的大小,这些元素绘制在 div 之上,充当绘图板。 为了塑造我的第一个元素(它们是简单的矩形),顺便说一句
如何在类之间传递事件? 我知道这听起来很荒谬(确实如此),但在过去的一段时间里我一直被这个问题难倒了。搜索没有出现类似的问题,所以我想我会提出这个问题。 这里是涉及的对象: WinForm -> Sp
我在 class 中订阅了一个 Event。比如 MainStation mainStation = StationFactory.GetMainStation(); mainStation.Fre
当用户多次悬停(mouseenter)时如何防止冒泡或“失控”。当用户悬停时,我使用slideDown和slideUp作为mouseleave,并将延迟设置为250。只有当延迟设置为1毫秒时,我才能解
背景:我目前正在编写一个greasemonkey 脚本,用于嵌入/修改特定页面的html。该页面设置有 3 个嵌套 div。在这 3 个 div 中,我只能将事件监听器添加到最外面的 div(这是由于
想想 HTML5 服务器发送的事件(我在服务器端使用 php)。为了获取服务器发送的数据,我有以下代码: if(typeof(EventSource) !== "undefined") { v
我想禁用 SPA 路由器正文部分中所有具有“nolink”类的链接。为了实现这一点,我使用了事件委托(delegate),它不能很好地处理嵌套元素。 (下面是简化的代码)。 HTML:
实验证据使我相信键(向上、向下、按下)事件只会触发(在气泡阶段)处于焦点的元素。 这种行为可能是直观的、明显的和/或可取的,但还没有在任何地方看到这种记录,所以我希望社区能够证实我的“理论”。 否则,
如果我有以下布局: public class A : INotifyPropertyChanged { public event PropertyChangedEventHandler Pro
我有几个带有随机数的 div,我后来使用一些简单的冒泡排序代码按升序排列,我想逐渐排列并为它们添加样式,而不是对它们进行样式设置并立即安排。 这感觉很简单,但我无法找到 sleep for 循环 或正
我已经用 Java 实现了所有四种排序算法。只是为了它,我决定查看每种算法中的交换次数和比较次数。对于大小为 20 的随机数组,这是我的结果 冒泡排序:87 次交换,87 次比较 插入排序:87 次交
所以根据MDN (这是有道理的)AnimationEvent 有 bubble 参数,但是如何将它设置为 true?考虑到该事件是从 CSS 动画触发的。 最佳答案 好吧,原来CSS是做冒泡事件的,例
我在 WPF WindowsFormsHost 中有 Winforms 控件。Winforms 控件是被动的,不能处理任何鼠标事件。鼠标事件应该像往常一样从 WPF 可视化树中最内部的 WPF 控件引
我有一个 iframe,它具有警报功能和 console.log 功能。 我能够看到 console.log 的输出,但是警报功能没有冒泡(永远不会以可见的方式触发)。 我尝试在 chromium 上
我有以下 html 设置: blaat blaat2 它的样式使您不能悬停 div1 而不悬停其他 2 个 div 之一。现在我在 div1 上有一个 mouseout。 问题是当我从 conte
最近学习了python基础,写一下3大排序练练手: 复制代码 代码如下: ''' Created on 2013-8-23 @author: codegeek
我正在处理一个内容可编辑的 div,我需要在将字符添加到 div 之前和之后捕获击键。 我对捕获与冒泡的理解是,事件首先在 dom 树的最高层捕获,然后向下传递,而对于冒泡,它从最低层开始,然后在树上
Demo Here 我想要实现的目标: 鼠标悬停时 - 将显示共享图标。 单击共享图标时,将显示新 Div 问题 当鼠标移出共享图标时“新 Div 不应关闭,必须显示”。 当大图像的 MouseOut
我知道我的问题是在 DOM 内冒泡,因为我的分页中有多个页面,当我多次单击编辑类链接时,它会冒泡并连续加载相同的文件,我想知道更好的解决这个问题的方法。 $('.edit').live('click'
我需要使用事件委托(delegate)捕获内部带有图像的 anchor 节点。 document.addEventListener( 'click', function(event) {
我是一名优秀的程序员,十分优秀!