【Java】算法积累2-冒泡排序算法及优化

算法刚刚入门,每次记录下自己所学的知识总结以及理解,希望能够帮助大家,如有内容有错误或可改进的地方,欢迎一起探讨,一起进步,在此也要感谢WYSCODER学长给我的学习建议

目录

一、基本概念

二、动画演示

 三、具体操作

思路

初始代码

优化思路

代码优化


一、基本概念

冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法

它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行,直到没有相邻元素需要交换,也就是说该元素列已经排序完成。

这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”。(查自百度百科)

二、动画演示

 三、具体操作

  思路

/*
        思路:
            遍历无序数组,
            嵌套循环,外层循环从头到尾遍历这个无序数组,轮数就为数组长度-1,内层循环也是从头到尾遍历这个无序数组,
            将第一个与第二个进行比较,如果>则进行交换,以此类推,那么内层遍历了一轮之后,这个无序数组的最后一位一定是最大值
            那么下一次的内层循环是不是就不用再遍历全部的数组了,每次内层循环全部遍历一次都会确定一个数的位置,
            所以内层循环的次数是逐步递减的,外层循环是每次递增的
            例如:
                1 3 7 3 8 4 5
                经过第一次的内层排序,最后一位是8,那么下一次内层循环索引值仅需要遍历到5就可以了
            因此,内层循环次数就为:无序数组长度-1-每次的外层循环的索引值
     */

 初始代码

package 排序问题;

import java.io.*;

public class 冒泡排序 {
    static StreamTokenizer input = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    static PrintWriter output = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));

    public static void sort(int[] arr) {
        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]) {
                    arr[j] = arr[j] ^ arr[j + 1];//step1
                    arr[j + 1] = arr[j] ^ arr[j + 1];//step2
                    arr[j] = arr[j] ^ arr[j + 1];//step3
                    /*
                        想一想为什么交换值要用异或,而不开一个变量来保存交换?
                        我们知道,异或操作符功能是:两个数对应而二进制数的各个位进行比较,相同为0,不相同1
                        一个数如果异或自己,那么结果就为零,再异或另一个数那么结果就为另一个数
                        并且运用异或,能减短运行时间,提高效率,因为是直接对计算机底层进行操作
                        因此:
                            再交换两个数时,推荐用异或运算符
                     */
                }
            }
        }
        /*
            for (Integer value : arr) {
                output.print(value + " ");
                output.flush();
            }
            这是foreach循环,他不需要索引值,Integer是你的数组元素的数据类型,value是你给你的元素所命名的名称,arr就是你要遍历的数组或是集合的名称
            如果对输出样式有要求的话就不推荐这个,其他情况下推荐使用,他不会出现数组越界,其他循环有时手误或掌握不牢可能会数组越界
         */

        /*
            有些题可能对空格会有要求,比如输出一堆数,每个数之间有空格,但最后一个数后没有空格
            想一想该怎么满足
            那么我们只需要第一个数只输出,剩下的数每次输出空格+下一个数就能轻易解决了
         */
        for (int i = 0; i < arr.length; i++) {
            if (i==0){
                output.print(arr[i]);
                output.flush();
            }else {
                output.print(" "+arr[i]);
                output.flush();
            }
        }
    }

    public static void main(String[] args) {
        int[] example = {8, 5, 1, 4, 7, 5, 7, 3};
        sort(example);
    }
}

 优化思路

/*
        优化思路:
            如果我们队一组无序数组进行排序
            2 1 3 4 5 6 7
            我们发现只有前两个是无序的,剩下的数字都是有序的,如果还用上一个方式进行操作,
            那么即使后面是有序的,但还是要进行判断,很浪费时间
            因此我们要对外层循环进行改动
            每次在内层循环的外面创建一个布尔变量=true,表示这轮数组是否为有序,如果无序,布尔变量就为false
            如果一轮下来结果为true那么后面的就已经排序好了,我们就不需要轮数再排了,因此直接break循环
            内层循环的次数也可以改动,有必要每次都执行arr.length()-1-i吗?
                以 2 1 3 4 5 6为例
                外层循环次数我们已经控制了,内层循环呢
                我们可以发现 3 4 5 6已经是有序的了,但内层循环次数还是每次逐渐递减,实际循环到1就可以了
                因此我们需要刷新内层循环次数,这样只需要每次遍历无序数组就可以了,
               先设置一个变量来保存最后一次交换的位置,那么他之后的就已经是有序的
               再设置一个变量来保存内层循环的刷新次数,最开始为arr.length()-1
               每次内层循环之后让他等于保存最后一次交换位置的变量
     */

 代码优化

package 排序问题;

import java.io.*;

public class 冒泡排序优化 {
    static StreamTokenizer input = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    static PrintWriter output = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));

    public static void sortImprove(int[] arr) {
        int lastBored = 0;
        int everySort = arr.length - 1;
        for (int i = 0; i < arr.length - 1; i++) {
            boolean f = true;
            for (int j = 0; j < everySort; j++) {
                if (arr[j] > arr[j + 1]) {
                    arr[j] = arr[j] ^ arr[j + 1];
                    arr[j + 1] = arr[j] ^ arr[j + 1];
                    arr[j] = arr[j] ^ arr[j + 1];
                    f = false;
                    lastBored = j;
                }
            }
            everySort = lastBored;
            if (f) break;
        }
        for (Integer value : arr) {
            output.print(value + " ");
            output.flush();
        }
    }

    public static void main(String[] args) {
        int[] example = {6, 4, 2, 3, 4, 5};
        sortImprove(example);
    }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值