常见排序算法(1)--冒泡排序

前言:相信很多小伙伴在学习排序算法的时候,都遇到过一个问题,就是好像理解了某算法的思想,但是手写的时候,总是不能写对,主要在边界问题上,不知道写j还是j-1,写<length还是<=length。
目标:希望经常此专题的共同学习,每个小伙伴都能轻松的理解排序算法并且完全写对。
先看最简单的入门排序算法:冒泡排序吧。
为了后面可以方便的测试,先把简单的辅助函数写好。

#import <Foundation/Foundation.h>
// 打印数组的函数
void printArr(int *arr, int length)
{
    for (int i = 0; i < length; i++)
    {
        printf("%d,",arr[i]);
    }
    printf("\n");
}
// 交互数组的元素
void swap(int *arr,int i,int j)
{
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}
1. 很像冒泡排序但是不是真正的冒泡排序
void BubbleSort0(int *arr,int length)
{
    for (int i = 0; i < length-1; i++)
    {
        for (int j = i+1; j < length; j++)
        {
            if (arr[i] > arr[j]) // 采用升序排序
            {
                swap(arr, i, j);
            }
        }
    }
}

光看代码可能不好理解,所以先看个简单的数组。int arr[] = { 3, 4, 2, 1};c语言的数组第一个元素下标为0,最后一个元素下标为length-1。第一次循环的时候,i从0开始,j从i+1开始,j的左边界很好理解,右边界为啥是<length呢?我们把arr[0]取出来放在那里,然后分别与arr[1]、arr[2]...到最后的arr[length-1]比较,如果遇到比arr[0]小的元素,就把它跟arr[0]交换。这样当i=0走完后,arr[0]就会成为最小的元素。然后i依次递增下去,排序就完成了,现在看看i的右边界为啥写<length-1而不写<length,其实外循环写<length也不会有错误,只是没有必要,因为当arr[length-2]排序完成后,剩余的最后一个元素arr[length-1]肯定就是最大的了。相信看完这段略显啰嗦的解释,大家应该都能一字不差的写出此"非正宗冒泡排序"了。

2. 正宗的冒泡排序
void BubbleSort(int *arr,int length)
{
    for (int i = 0; i < length-1; i++)
    {
        for (int j = length - 2; j >= i; j--)
        {
            if (arr[j] > arr[j+1])
            {
                swap(arr, j, j+1);
            }
        }
    }
}

为啥说这个是正宗的而前面却是似是而非的冒泡排序呢?因为冒泡排序的定义是两两相邻比较。我们还是拿最简单的例子来看,int arr[] = { 3, 4, 2, 1};当i=0时,j=2,其实就是拿数组的最后一个元素与倒数第二个元素比较,把小的交换到前面。然后j依次递减,到最后比较的就是arr[i]与arr[i+1],所以j的左边界是i,右边界是length-2。i=0的内循环走完后,其实arr[0]就是最小的元素,i依次递增,arr[i]就是依次的最小值。i的右边界的问题上一段有解释,不重复了。很多网上的冒泡排序的内循环的j是从0开始的,这个其实也是对的,大家任选一种就好了(不过j从后往前,造成的效果是小的元素依次上浮,个人感觉比较符合冒泡排序的意思。)。
tip:2其实效率跟1一样。方法1外循环执行完一次,仅仅做到了把arr[i]变为最小值,但是方法2在外循环执行完一次的过程中,除了把最小值带到arr[i]之外,还做了把数组中较小的元素慢慢交换到数组前半部的事情,所以数组会慢慢变的有序。2和1的比较次数和交换次数是一样的,不同的是2的数组在慢慢变的有序,这就是可以继续优化为3的基础。

3. 冒泡排序优化版
void BubbleSort2(int *arr,int length)
{
    int status = 1; // 初始值为1
    for (int i = 0; i < length-1 && status; i++)
    {
        status = 0; // 假设数组已经有序
        for (int j = length - 2; j >= i; j--)
        {
            if (arr[j] > arr[j+1])
            {
                swap(arr, j, j+1);
                status = 1; // 有交换,重置为1,数组可能还不是完全有序,需要再做校验
            }
        }
    }
}

这个相对上面的冒泡排序有了一些优化,引入了一个标志位。还是拿一个最简单的数组int arr[] = { 2, 1, 3, 4};先把标志位设置为1,然后在内外循环之间将标志位设置为0,假设数组已经有序。内循环从后到前依次比较2个相邻元素,如果if一直为假,即可证明arr[0]<=arr[1]<=...<=arr[length-1]。标志位没有被重置为1。下一次循环,外循环条件也不满足,结束循环。如果发生了交互,就把标志位重置为1,数组可能还不是完全有序,需要下一次循环再做校验。

冒泡排序到这里就结束了,可能会略显啰嗦,啰嗦的原因是大家觉得冒泡排序太简单,后面到略微复杂一些的希尔快速等排序的时候,也会保持这个风格,确保所有看过文章的人都能看懂,并且把排序代码正确的写出来。

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

推荐阅读更多精彩内容

  • Sort Algorithm(ASC) [TOC] //怎么生成目录,纠结ing 插入排序 每一趟排序都将待排元素...
    一条小袍袍YoY阅读 428评论 0 1
  • 排序算法说明 (1)排序的定义:对一序列对象根据某个关键字进行排序; 输入:n个数:a1,a2,a3,…,an 输...
    code武阅读 648评论 0 0
  • 参考:十大经典排序算法 0、排序算法说明 0.1排序的定义 对一序列对象根据某个关键字进行排序。 0.2 术语说明...
    谁在烽烟彼岸阅读 1,004评论 0 12
  • 1、冒泡排序 最简单的一种排序算法。假设长度为n的数组arr,要按照从小到大排序。则冒泡排序的具体过程可以描述为:...
    Joe_2e0c阅读 499评论 0 0
  • 昨天晚上和丁月月聊天的时候,有句话不太恰当,冒犯了她,我立马也意识倒了,给她道歉,对不起,她夜立马回复到“伪君子”...
    套马的汉子爱学习阅读 268评论 0 0