<<大话数据结构>>之浅谈冒泡排序算法

“简单不先于复杂,而是在复杂之后.” —— Alan Perlis

大话数据结构修改版.png


序言


当我们第一次数组排序的时候,通常都会介绍一种排序算法,那就是冒泡排序.冒泡排序的思路是最简单的,最容易让人理解的.可能看这篇文章的各位大神都在程序的世界遨游已久,会对此嗤之以鼻,说不就是两层For循环嘛,不是简单的很?而我却要说,NO,NO,NO,今天的文章可能让你眼前一亮,请耐心看下去.你会发现一些你认知中所不一样的东西.


冒泡概念简介以及最简单的排序实现


冒泡排序

冒泡排序是一种交换排序,它的实现原理是:两两比较相邻的记录值,如果反序则交换,直到没有反序的记录为准,如上图,这就是一次完整的冒泡排序.我们看一下代码是如何实现的.还是以OC语言为基础.在ViewController中实现代码.

#import "ViewController.h"

@interface ViewController ()

@property(nonatomic,strong)NSMutableArray *dataArray;//数据源数组

@end

@implementation ViewController

- (void)viewDidLoad {

    [super viewDidLoad];

    self.dataArray = [NSMutableArray arrayWithArray:@[@6,@5,@3,@1,@8,@7,@2,@4]];

    for (int i = 0; i< self.dataArray.count; i++) {
        
        for (int j = i +1 ; j <self.dataArray.count; j++) {
            
            if (self.dataArray[i] < self.dataArray[j]) {
                
                NSNumber *number = self.dataArray[i];
                
                self.dataArray[i] = self.dataArray[j];
                
                self.dataArray[j] = number;
                
            }
            
        }

    }

    NSLog(@"%@",self.dataArray);

}

@end

</br>

控制台输出的结果
冒泡排序完成.gif

上面的冒泡排序算法应该是我们平常最常用的冒泡排序了,但是其实从严格意义上来说,上面的冒泡排序并不能成为严格意义上的冒泡排序,因为它不满足"两两比较相邻记录"的冒泡排序的思想,相比叫它冒泡排序,不如叫它最简单的交换排序.它的思路就是让每一个元素与它后面的每一个元素比较,如果大则交换,这样第一个位置的元素在第一排序之后一定活成为最大值.如上图,这就是一次排序的整个过程.上面的排序方式只能算是最简单的排序方式了,不过这样简单的代码却有缺陷的,比如在第一次排序完成的数组为[5,3,1,8,7,6,2,4]对其他的元素却没有帮助.也就说,这个方法是非常低效的,那么接下来,我们看一下正宗的冒泡排序有没有什么改进的地方.


冒泡排序算法


我们先看一下正宗的冒泡排序代码是如何实现的

  self.dataArray = [NSMutableArray arrayWithArray:@[@6,@5,@3,@1,@8,@7,@2,@4]];
    
    for (int i = 0; i< self.dataArray.count; i++) {
        
        //注意j是从后往前循环,从后往前遍历
        for (int j = (int)self.dataArray.count-1 ; j >= i ; j--) {
            
            if (self.dataArray[i]< self.dataArray[j]) {
                
                NSNumber *number = self.dataArray[i];
                
                self.dataArray[i] = self.dataArray[j];
                
                self.dataArray[j] = number;
                
            }
            
        }
        
        
    }
    
    NSLog(@"%@ ",self.dataArray);

}

那么,我们就看第一次遍历,先从最后一个元素4开始,因为4>2,所以交换位置,然后4和7比较,不交换位置,7和8比较,交换位置,最后,8分别和1,3,5,6比较,然后全都交换位置,然后数组的第一次遍历就完成,数组为[8,6,5,3,1,7,4,2];相比于简单排序第一完成之后的数组[5,3,1,8,7,6,2,4],除了元素8往前进了一位,元素6到了数组的后半部分了.这一正宗的算法果然要比前面的要有所进步,可能数组中的元素个数少的时候,可能效率差的不会是很大,如果在上十万条数据的排序过程中,这种差异就会体现出来.但是,这样正宗的冒泡排序有没有改进的方案呢?答案是有的.首先,我们来打印一下冒泡排序和简单的执行次数.

简单排序和冒泡排序的执行次数的比较

那么,为什么会出现这种情况,我们改如何改进呢?


冒泡排序的优化


为什么冒泡排序会比最贱的排序方式执行次数多呢?比如正宗的冒泡排序第一次执行完成之后的数组为[8,6,5,3,1,7,4,2],我们当执行第二次的时候,最后执行的的是7和8 的比较,明明元素8 的位置就赢改第一位,毋庸置疑,却还要比较一次,尽管没有交换数据,但是比较还是多余的.往后的遍历中,这样的无用的比较缺不改变位置很多,我们改如何改进呢?我们的改进思想是这样的,设置一个BOOL值,在一次的遍历
过程中只要有位置的变动,我们就允许下一次遍历,否则就不再执行下一次遍历,代码实现如下.

    
    self.runNumber = 0;
    
    self.isContinue = YES;
    
    self.dataArray = [NSMutableArray arrayWithArray:@[@6,@5,@3,@1,@8,@7,@2,@4]];
    
    for (int i = 0; i< self.dataArray.count && self.isContinue; i++) {
        
        self.isContinue = NO;
        
        for (int j = (int)self.dataArray.count-1 ; j >= i ; j--) {
            
            if (self.dataArray[i]< self.dataArray[j]) {
                
                self.isContinue  = YES;
                
                NSNumber *number = self.dataArray[i];
                
                self.dataArray[i] = self.dataArray[j];
                
                self.dataArray[j] = number;
                
            }
            
            self.runNumber++;
        }
        
        
    }
    
    NSLog(@"冒泡排序优化:\n %@ \n 执行次数:%ld",self.dataArray,self.runNumber);


代码和普通的冒泡排序最大的区别就是多了一个BOOL值,来判断一下程序是否有必要执行下去,进过这样的改进,冒泡排序在性能上就有了一些提升,可以避免因有序的情况下无意义的循环判断.

那么,程序到底优化了多少呢?来,我们打印三次的执行次数,如下图,我们可以从图中可以看出优化的执行次数为30次,而冒泡排序的执行次数是36次,效率提高了16.67%,大大的优化程序性能.

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

推荐阅读更多精彩内容

  • 数据结构与算法--排序之冒泡、选择、插入、希尔 我们关注的主要对象是重新排列数组元素的算法,每个元素都有一个主键,...
    sunhaiyu阅读 1,118评论 2 12
  • 1 序 2016年6月25日夜,帝都,天下着大雨,拖着行李箱和同学在校门口照了最后一张合照,搬离寝室打车去了提前租...
    RichardJieChen阅读 5,071评论 0 12
  • 第一章 绪论 什么是数据结构? 数据结构的定义:数据结构是相互之间存在一种或多种特定关系的数据元素的集合。 第二章...
    SeanCheney阅读 5,735评论 0 19
  • K妞昨天大半夜给我发微信,说她和男朋友吵了一晚上,原因是他忘了他们的恋爱两周年纪念日。 K从当天午夜十二点之后就开...
    朵拉鱼阅读 4,553评论 29 61
  • 窗外又下起了雨,最近雨连绵不断,心情持续的低落,心里明镜的知道的是因为什么原因,可是自己却调节不好,不知道怎么办了...
    核桃牛奶的牛阅读 254评论 0 0