常见算法1-冒泡及优化

冒泡算法:

(对一些部分有序的数组,效率高)
时间复杂度:n^2;
一般入门时是这样写的:

        int [] datas= new int[]{6,5,4,3,2,1};
        for (int i=0;i<datas.length;i++){
            for (int j=0;j<datas.length-1;j++){
                if (datas[j]>datas[j+1]){
                    int minV=datas[j];
                    datas[j]=datas[j+1];
                    datas[j+1]=minV;
                }
            }
        }
       for (int data : datas) {
              System.out.print(data+" ");
       }

得道结果是12346;没问题;
但是加上打印每一步骤的结果值,发现还有些执行相同的
多次,导致浪费计算次数。于是想到了优化;


image.png
冒泡算法的优化:
优化1

1.首先是第二个for循环的总次数:
由打印的日志分析知道,每执行一次内层的循环一次,就可以将大的值给冒泡交换到最后面了。最大数,第一遍就给放到最后面了,因此可以不用再交换后面排好序的位置了。
由打印结果规律,归纳推导,发现外层遍历的下标刚好是内层循环排好序的个数。于是内层的遍历可以在后面便利的总数减去外层遍历下标。
2.内层循环遍历时,有一个最小比对值,需要频繁的申明,使用,再释放。因此可以放到最外面,两个循环的初始下标计量也可以放入外边统一声明。
于是得到如下:

        int [] datas= new int[]{6,5,4,3,2,1};
        int change,m=0,n;
        for (;m<datas.length;m++){
            n=0;
            for (;n<datas.length-1;n++){
                if (datas[n]>datas[n+1]){
                    change=datas[n];
                    datas[n]=datas[n+1];
                    datas[n+1]=change;
                }
                System.out.format("第 %d 遍的第%d 次交换:", m+1,n+1);
                for(int count:datas) {
                    System.out.print(count+" ");
                }
                System.out.println();
            }
            System.out.format("第 %d 遍最终结果:", m+1);
            for (int data : datas) {
                System.out.print(data+" ");
            }
            System.out.println();
        }

结果是:


image.png

发现最后的结果明显内循环每次都减少了次数。

优化2

但是如果数据是321456呐?
结果还是会走那么多次数,而且再有些步骤中就已经排好序了,可是外层循环还要继续排序。


image.png

于是,为了这个想去优化问题,我们可以设置一个标志位,用来表示当前第m趟是否有交换,如果有则要进行m+1 趟,如果没有,则说明当前数组已经完成排序。实现代码如下

        int [] datas= new int[]{3,2,1,4,5,6};
        int change,m=0,n;
        boolean flag;
        for (;m<datas.length;m++){
            n=0;
            flag=true;
            for (;n<datas.length-1-m;n++){
                if (datas[n]>datas[n+1]){
                    change=datas[n];
                    datas[n]=datas[n+1];
                    datas[n+1]=change;
                    //如果还有没排好序的,将标志位设置为false;
                    flag=false;
                }
                System.out.format("第 %d 遍的第%d 次交换:", m+1,n+1);
                for(int count:datas) {
                    System.out.print(count+" ");
                }
                System.out.println();
            }
            System.out.format("第 %d 遍最终结果:", m+1);
            for (int data : datas) {
                System.out.print(data+" ");
            }
            System.out.println();
            //如果没有要交换位置的,就证明排好序了,直接退出整个循环
            if (flag){
                return;
            }
        }

打印结果:


image.png

发现好多了,少外层的两次循环。

优化3

但是还有一个问题,就是上图中,明明第二次遍历,第一次的交换就已经完成了,但是后面还要继续交换,造成了一定的时间浪费。
对于这种问题,我们可以想到一个解决方案,利用一个标志位,记录一下当前第m趟所交换的最后一个位置的下标,在进行第m+1 趟的时候,只需要内循环到这个下标的位置就可以了,因为后面位置上的元素在上一趟中没有换位,这一次也不可能会换位置了。基于这个规律,我们可以进一步优化我们的代码:

        int [] datas= new int[]{3,2,1,4,5,6};
        int change,m=0,n,changelen=datas.length-1,tempIndex=0;
        boolean flag;
        for (;m<datas.length;m++){
            n=0;
            flag=true;
            for (;n<changelen;n++){
                if (datas[n]>datas[n+1]){
                    change=datas[n];
                    datas[n]=datas[n+1];
                    datas[n+1]=change;
                    //如果还有没排好序的,将标志位设置为false;
                    flag=false;
                    tempIndex=n;
                }
                System.out.format("第 %d 遍的第%d 次交换:", m+1,n+1);
                for(int count:datas) {
                    System.out.print(count+" ");
                }
                System.out.println();
            }
            changelen=tempIndex;
            System.out.format("第 %d 遍最终结果:", m+1);
            for (int data : datas) {
                System.out.print(data+" ");
            }
            System.out.println();
            //如果没有要交换位置的,就证明排好序了,直接退出整个循环
            if (flag){
                return;
            }
        }

打印结果:


优化三

从打印输出来看,明显减少了很多不必要的计算。比原来的更加优良,减少了时间复杂度。

选择排序:

(适用于无序不重复的数列)
时间复杂度:n^2;
原理:
第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。选择排序是不稳定的排序方法。
代码:

    public void selectSort(){
        int change,m=0,n;
        int [] datas= new int[]{8,1,48,92,12,77,66,6};
        for (;m<datas.length;m++){
            change=datas[m];
            for (n=m+1;n<datas.length;n++){
                if (datas[n]<change){
                    change=datas[n];
                    datas[n]=datas[m];
                    datas[m]=change;
                }
            }
        }
        for (int data : datas) {
            System.out.print(data+" ");
        }
    }

打印结果:
1 6 8 12 48 66 77 92 ;

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343