zoukankan      html  css  js  c++  java
  • 三种常用又简单的排序算法

    2021-11-09

    关键字:桶排序


    1、桶排序

    桶排序一般用于对一组知道上下限的整数序列中。

    因为桶排序的核心原理就是全覆盖式计数,为整个区间每一个数创建一个计数器,遍历待排序序列,为每一个出现的数计数加1,最后根据需要从头至尾或从尾至头打印区间计数。

    举个例子,假设要为一个班级的学生数学考试分数做个排序。

    已知分数范围为 0 ~ 100,是一个知道上下限的区间。现有分数:52、70、41、99、64、64。创建一个101个长度的数组score,第0号表示成绩为0分的人数,第1号为成绩为1分的人数,第101号为成绩为100分的人数。遍历待排序序列,第一个成绩为52,则将score数组第53号的值加1,第二个成绩为70,则将score数组第71号的值加1,依此类推直至结尾。当我们需要获取排序结果时,例如想要将成绩从高到低打印出来,则可以逆遍历score数组,当其计数值大于0时则打印出来即可。

    桶排序的优点就是速度快,缺点是对序列元素有要求,且其空间占用会随着序列规模的增大而增大。

    以下是一个桶排序的C语言实例:

    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
        //待排序序列
        const char scores[] = {71, 100, 7, 40, 88, 100, 91, 96, 71, 84, 60, 40, 71, 0, 1, 0};
        //序列上下限为 0 ~ 100 的整数。
        char score_bucket[101];
        
        memset(&score_bucket, 0, 101);
        
        int count = sizeof(scores) / sizeof(char);
        int i;
        for(i = 0; i < count; i++)
        {
            score_bucket[scores[i]] += 1;
        }
        
        //打印结果(递减顺序)
        int j = 0;
        for(i = 100; i >= 0; i--)
        {
            if(score_bucket[i])
            {
                for(j = 0; j < score_bucket[i]; j++)
                {
                    printf("%d,", i);
                }
            }
        }
        printf("\n");
        return 0;
    }

    2、冒泡排序

    冒泡排序对空间的要求非常小,时间复杂度为O(n(n+1))约等于O(n2)。

    其核心原理是从头到尾两两比较,将顺序不正确的两个数互换一下位置,如此一趟下来能将符合要求的最大或最小数挪到原数据的最末位,然后再重复一次操作,只不过这次因为最末一位已经是正确的顺序了,第二轮比较就只到第n-1位了。如此循环直至原数组中已排序序列数量涨至n-1个为止即表示整个排序已完成。

    以下是冒泡排序的C语言实例:

    #include <stdio.h>
    
    int main()
    {
        //待排序序列
        char scores[] = {71, 100, 7, 40, 88, 100, 91, 96, 71, 84, 60, 40, 71, 0, 1, 0};
        
        int count = sizeof(scores) / sizeof(char); //序列长度
        int i;
        int j;
        int loop = count - 1; //最后一个元素不用参与到排序中。
        char tmp;
        for(i = 0; i < loop; i++)
        {
            for(j = 0; j < loop - i; j++)
            {
                if(scores[j] > scores[j + 1])
                {
                    tmp = scores[j];
                    scores[j] = scores[j+1];
                    scores[j+1] = tmp;
                }
            }
        }
        
        //print
        for(i = 0; i < count; i++)
        {
            printf("%d,", scores[i]);
        }
        printf("\n");
        
        return 0;
    }

    3、快速排序

    桶排序速度快,但是空间消耗大。冒泡排序空间消耗小,但是速度慢。快速排序则可以一定程度上兼顾空间和时间消耗,它在数值比较上采用与冒泡排序类似的两两交换法,在空间消耗上采用函数递归调用,虽然递归调用函数也会随着序列规模上升而增长,但相对来讲空间占用还是比桶排序好很多。

    快速排序的核心是选中一个基准数,在递增排序的需求下将所有大于基准数的元素放在基准数右边,将所有小于基准数的元素放在其左边。然后对分别对左半子序列和右半子序列应用同样的算法,直至子序列只剩一个元素为止。通常为了方便,基准数选第1个或最后一个。

    快速排序的实现原理是将待排序序列第1个元素作为基准数,分别从序列两端收缩遍历取值。如果基准数选的是第1个,则首先从右端收缩,若基准数选的是最后一个,则首先从左端收缩。当从右端开始收缩时,一直收缩直到遇到一个数小于基准数为止,然后收缩左端,直到找到一个数大于基准数为止。然后直接交换这两个数,之后再重复两端的收缩过程,直至两端收缩碰撞为止。收缩碰撞后将碰撞值直接与基准数对调,之后便可对生成的两个子序列再分别应用此算法,直至子序列只有一个元素为止。

    以下是一个C语言版的实例:

    #include <stdio.h>static void quick_sort(char nums[], int start, int end)
    {
        char tmp;
        int i = start;
        int j = end;
        if(start >= end)
            return;
    
        while(1)
        {
            if(i == j)
            {
                //直接跟基数交换
                tmp = nums[start];
                nums[start] = nums[j];
                nums[j] = tmp;
                
                //迭代左边的
                if(start < j)
                {
                    quick_sort(nums, start, j - 1);
                }
                
                //迭代右边的
                if(end > i)
                {
                    quick_sort(nums, i + 1, end);
                }
                
                //排序完成
                break;
            }
            else
            {
                //j先动。
                if(nums[j] < nums[start])
                {
                    //轮到i动
                    if(nums[i] > nums[start])
                    {
                        if(i != j)
                        {
                            //可以交换
                            tmp = nums[j];
                            nums[j] = nums[i];
                            nums[i] = tmp;
                        }
                    }
                    else
                    {
                        i++;
                    }
                }
                else
                {
                    j--;
                }
            }
        }
    }
    
    int main()
    {
        //待排序序列
        char nums[] = {6, 1, 2, 7, 9, 3, 4, 5, 10, 8};
        
        int i;
        quick_sort(nums, 0, 9);
        
        for(i = 0; i < 10; i++)
        {
            printf("%d, ", nums[i]);
        }
        printf("\n");
        
        return 0;
    }

    +++
  • 相关阅读:
    linux下 C++ 读取mat文件 MATLAB extern cyphon scipy 未完待续
    mshadow笔记
    mem_fun 例子
    gedit embeded terminal 设置字体 颜色
    decltype typename
    gcc4.9.1新特性
    C++开发者都应该使用的10个C++11特性 转
    如何加快C++代码的编译速度 转 ccache
    cout关闭输出缓冲,调试用
    boost range zhuan
  • 原文地址:https://www.cnblogs.com/chorm590/p/15522034.html
Copyright © 2011-2022 走看看