吴军老师讲的那些排序算法

冒泡排序、归并排序、快速排序,一个个名词耳熟能详,听吴军老师娓娓道来,仍有不少额外的收获,记录分享如下。

对于冒泡排序,原理很简单,就是每次找到无序数据中的最大值,直到排序完成,步骤如下:

1.比较相邻的元素。如果第一个比第二个大,就交换他们两个;

2.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数;

3.针对所有的元素重复以上的步骤,除了最后一个;

4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

算法复杂度为O(n2),用C语言实现如下:

void bubble_sort(int a[], int n)

{

    int i, j, temp;

    for (j = 0; j < n - 1; j++)

        for (i = 0; i < n - 1 - j; i++)

        {

            if(a[i] > a[i + 1])

            {

                temp = a[i];

                a[i] = a[i + 1];

                a[i + 1] = temp;

            }

        }

}

归并排序的原理是将无序数据分堆,找出每一堆的序列,然后合并得到一个完整的有序序列,步骤如下:

1.申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;

2.设定两个指针,最初位置分别为两个已经排序序列的起始位置;

3.比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;

4.重复步骤3直到某一指针超出序列尾;

5.将另一序列剩下的所有元素直接复制到合并序列尾。

算法复杂度为nlog(n),C语言实现如下:

void Merge(int sourceArr[],int tempArr[], int startIndex, int midIndex, int endIndex)

{

    int i = startIndex, j=midIndex+1, k = startIndex;

    while(i!=midIndex+1 && j!=endIndex+1)

    {

        if(sourceArr[i] > sourceArr[j])

            tempArr[k++] = sourceArr[j++];

        else

            tempArr[k++] = sourceArr[i++];

    }

    while(i != midIndex+1)

        tempArr[k++] = sourceArr[i++];

    while(j != endIndex+1)

        tempArr[k++] = sourceArr[j++];

    for(i=startIndex; i<=endIndex; i++)

        sourceArr[i] = tempArr[i];

}

 //内部使用递归

void MergeSort(int sourceArr[], int tempArr[], int startIndex, int endIndex)

{

    int midIndex;

    if(startIndex < endIndex)

    {

        midIndex = (startIndex + endIndex) / 2;

        MergeSort(sourceArr, tempArr, startIndex, midIndex);

        MergeSort(sourceArr, tempArr, midIndex+1, endIndex);

        Merge(sourceArr, tempArr, startIndex, midIndex, endIndex);

    }

}

 快速排序的原理是通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。步骤如下:

1.设置两个变量i、j,排序开始的时候:i=0,j=N-1;

2.以第一个数组元素作为关键数据,赋值给key,即key=A[0];

3.从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将A[j]和A[i]互换;

4.从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]互换;

5.重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。

这个算法的复杂度一般也是nlog(n),C语言实现如下:

void sort(int *a, int left, int right)

{

     int i = left;

    int j = right;

    int key = a[left];

    if(left >= right)/*如果左边索引大于或者等于右边的索引就代表已经整理完成一个组了*/

    {

        return ;

    }

    while(i < j)                               /*控制在当组内寻找一遍*/

    {

        while(i < j && key <= a[j])

        /*而寻找结束的条件就是,1,找到一个小于或者大于key的数(大于或小于取决于你想升

        序还是降序)2,没有符合条件1的,并且i与j的大小没有反转*/ 

        {

            j--;/*向前寻找*/

        }

        a[i] = a[j];

        /*找到一个这样的数后就把它赋给前面的被拿走的i的值(如果第一次循环且key是

        a[left],那么就是给key)*/

        while(i < j && key >= a[i])

        /*这是i在当组内向前寻找,同上,不过注意与key的大小关系停止循环和上面相反,

        因为排序思想是把数往两边扔,所以左右两边的数大小与key的关系相反*/

        {

            i++;

        }

        a[j] = a[i];

    }


    a[i] = key;/*当在当组内找完一遍以后就把中间数key回归*/

    sort(a, left, i - 1);/*最后用同样的方式对分出来的左边的小组进行同上的做法*/

    sort(a, i + 1, right);/*用同样的方式对分出来的右边的小组进行同上的做法*/

                       /*当然最后可能会出现很多分左右,直到每一组的i = j 为止*/

}

作为一个码农,排序的事情经常做,却对其本质知之甚少。

排序算法的效率提高,在于它少做了很多并不需要做的比较。效率=产出/所做的事情。人的产出是很难提高的,但是所做的事情是可以减少的。强调工程师水平差一级,贡献可能就差出10倍。在农耕文明时代,没有力气的人最不济也能产生壮劳力1/3的生产力。在工业时代,靠手工一件件生产商品,可能效率能有机器的1%。但是到了智能时代,本事差一点,效果可能差几百万倍,几亿倍,专业和不专业就差得更远了。

罗胖跨年演讲说,人生即算法。人的总时间和注意力都相差不多,关键在于如何取舍,并且在核心方面最好最后的1%。

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

推荐阅读更多精彩内容

  • 概述:排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    每天刷两次牙阅读 3,726评论 0 15
  • 概述 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    蚁前阅读 5,155评论 0 52
  • 总结一下常见的排序算法。 排序分内排序和外排序。内排序:指在排序期间数据对象全部存放在内存的排序。外排序:指在排序...
    jiangliang阅读 1,318评论 0 1
  • 2017年11月10日 晴 星期五 亲子日记第47篇 昨天晚上,女儿看了我近期写的亲子日记,提出抗议,说是写儿子的...
    敏文妈咪阅读 316评论 0 2
  • 文/孤鸟差鱼 有些角落 每每一触 就生疼
    孤鸟差鱼阅读 134评论 2 3