四种简单的排序算法

部分排序算法总结

冒泡排序

原理:

  • 相连两个数据两两比较,后者小于前者,交换位置,执行第一趟比较后,最后一个位置的元素一定是最大的元素;
  • 第二趟重复以上过程,直到比较到倒数第二个位置结束,倒数第二个位置一定是次最大的
  • 重复上述过程,直到最后一趟比较完成,整个数据完成排序

源码:

void burbSort(int number[], int length){
    int i, j, temp;
    i = length; 
    while(i > 0){
        for(j = 0; j < i; j++){
            if(number[j] > number[j + 1]){
                temp = number[j];
                number[j] = number[j+1];
                number[j+1] = temp;
            }
        }
        i = j - 1;
        printArray(number, 0, length);
    }
}

总结:

排序过程为相邻数据比较,不存在跳跃数据比较,比较稳定,时间复杂度为O(n^2);
当数据末端已经有序或者部分有序,基本冒泡仍然会对齐排序,可以进行改进,减少排序次数:

没排序一次,就记录这次最后交换数据的位置,该位置后面的数据表示已经排好了顺序;下次排序终点就在这个位置结束
  同时,可以使用双向冒泡排序,从前往后,排升序,在从后往前,排降序

插入排序

原理:

假设把一个元素插入到一个已经排好顺序的数据列表,从第一个元素开始比较,如果比插入元素小,在比较第二个,以此类推...,如果其中一个比插入的元素大,那该元素及其以后的数据后移一位,插入元素插入到这个位置;插入排序就是按照这个原理,默认把第二个元素当做插入元素插入到前一个元素的数据列表,在把第三个元素插入到前两个元素的数据列表,以此类推完成排序

源码:

void insertSort(int number[], int length){
    int i,j;
    int temp;
    printArray(number, 0, length);
    for(i = 0; i < length - 1; i++){
        j = i + 1;
        temp = number[j];
        while(j != 0 && temp < number[j - 1]){
            number[j] = number[j - 1];
            j--;
        }
        if(j != i +1){
            number[j] = temp;
        }
        printArray(number, 0, length);
    }
}

总结:

插入排序的效率时间和元素个数以及数据排列顺序的程度有关,最佳情况就是已经排好顺序的情况,最差的情况是倒序的数据排序情况,时间复杂度为O(n^2)

快速排序

原理:

  • 选择数据列表中任意一个元素作为分割点数据(后称关键数据),默认是列表第一个数据
  • 对比整个列表数据,比关键数据大的数据移动到关键数据后面,比关键数据小的移动到关键数据前面
  • 这样就分成了两个数据表,并且关键数据的位置一定是确定好了
  • 把分割好的两个表重复上述过程进行分割字表,直到字表里面的个数为1时结束比较

源码:

int splitArray(int number[], int start, int end){
    int value = number[start];
    printf("------------------------------------------");
    while(start < end){
        while(value < number[end] && start < end){
            end--;
        }
        if(start >= end)
            break;
        number[start] = number[end];
        printf(" %d ", number[start]);
        start++;
        while(value > number[start] && start < end){
            start++;
        }
        if(start >= end)
            break;
        number[end] = number[start];
        printf(" %d ", number[end]);
        end--;
    }
    number[end] = value;
    printf("------------------------------------------\n");
    printArray(number, 0, 17);
    return end;
}


void quickSort(int number[], int start, int end){
    int mIndex;
//  printArray(number, start, end + 1);
    if(start < end){
        mIndex = splitArray(number, start, end);
        quickSort(number, start, mIndex - 1);
        quickSort(number, mIndex + 1, end);
    }
}

总结:

快速排序相对来说是一种比较快的排序,因为它是属于跳跃式排序,比某个值大的数据放到一边,小的放到另一边,交换数据的位置变大了,总的数据交换次数就少了;最差的情况就是相邻数据的交换,在最差的情况下时间复杂度是O(n^2),平均复杂度是O(nlogn)

堆排序

原理:

了解排序原理前需要先弄明白两个定义:

完全二叉树:

如果一个二叉树深度为h,则除h层外的其它层,叶子节点必须全部都有,并且第h层的所有节点是先左后右;

最大堆和最小堆

最大堆 -- 所有节点必须大于它的子节点,堆顶为整个数据列表的最大值
    最小堆 -- 所有节点必须小于它的子节点,堆顶为整个数据列表的最小值

二叉树的特性:

树的深度height = length / 2 - 1
    当前节点的位置为index,则它左右子节点分别为2index + 1和 2index + 2

  • 把数据列表构造成一个完全二叉树,假设以最大堆的方式排列
  • 从index = length / 2 - 1的位置开始比较,比较该index节点和其左右子节点,如果子节点比它大,交换位置;如果小,在把子节点中大的一个节点比较其它的子节点
  • index--,重复上面第二个步骤,最终index=0的时候,将在堆顶得到一个最大值
  • 将堆顶的最大值和最后一个叶子节点交换位置
  • 在从倒数第二个叶子节点开始,重复上面第二个步骤进行最大堆比较,再把堆顶元素和倒数第二个叶子节点交换位置
  • 依次类推,重复比较,直至比较完成

源码:

void heapSort(int number[], int startIndex, int endIndex){
    int parentNode = startIndex;
    int childNode = 2 * parentNode + 1;
    int parentNodeValue = number[startIndex];
    for(; childNode <= endIndex; parentNode = childNode, childNode = 2 * childNode + 1){
        if(childNode < endIndex && number[childNode] < number[childNode+1]){
            childNode++;
        }

        if(parentNodeValue < number[childNode]){
            number[parentNode] = number[childNode];
            number[childNode] = parentNodeValue;
        }else{
            break;
        }
    }
}

void maxHeapSort(int number[], int length){
    int i;
    int j;
    int temp;
    for(i = length / 2 - 1; i >= 0; i--){
        heapSort(number, i, length - 1);
    }
    j = length - 1;
    for( i = 0; i < length - 1 ; i++){
        temp = number[0];
        number[0] = number[j];
        number[j] = temp;
        j--;
        heapSort(number, 0, j); 
    }

}

总结:

对于大数据的处理: 如果对100亿条数据选择Topk数据,选择快速排序好还是堆排序好? 答案是只能用堆排序。
  堆排序只需要维护一个k大小的空间,即在内存开辟k大小的空间。而快速排序需要开辟能存储100亿条数据的空间

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

推荐阅读更多精彩内容