• 3种简单排序:冒泡、选择、插入排序的概念及实现代码


      做题时遇到排序的问题,解题思路还是比较清晰,涉及到数据的排序,打算直接用插入排序直接快速水过去,没想到来到排序部分这里,内外的循环边界不清晰,导致直接越界出错,浪费时间,调试了多遍。因为这部分比较重要掌握不好直接影响后面其他快排算法的学习,所以写这篇当作复习巩固。

    影响排序的效率因素

    简单来说主要有:排序的稳定性,时间性能,辅助空间,算法的复杂度

    • 排序的稳定性

    比如排序(2,3,1(第一个),1(第二个),5,6)

    不稳定的排序,可能会排出(1(第二个),1(第一个),2,3,5,6);

    不稳定的情况下程序需要做更多的比较和移动,相当稳定的排序效率低

    • 时间性能

    是排序算法的重要衡量标志,在排序时主要进行比较和移动,高效率的排序应该尽可能少的元素比较和尽可能少的移动

    • 辅助空间

    即执行算法所需要的辅助存储空间,以及待排序所占用的空间

    • 算法复杂性

    这里指的是算法本身的复杂度,如果算法本身庞大且复杂显然会影响其排序的性能

    本文排序用到的公共结构与函数

    采用简单、易于理解的顺序表(数组)来演示

    typedef strut{
        int data[MAXSIZE+1]; //使用data[0]作为哨兵,提高程序可读性
        int length;                  //记录顺序表长度 
    }list;

    排序时最常用到的操作就是交换,将他写成函数swap

    void swap(list *s,int i,int j){
        int temp = s->data[i];
        s->data[i]=s->data[j]
        s->data[j]=temp;
    }

    冒泡排序

    排序原理:每两个相邻元素之间进行,反序则交换,一直交换到没有反序的元素为止。“冒泡”的含义是从后面开始进行两两比较,交换后符合的元素就往上冒。

    实现代码:

    void BublleSort(list *s){
        for(int i = 1; i < s->length-1;i++)
            for(int j = s->length-1;j >= i;j--)
                if(s->data[j] > s->data[j+1])
                    swap(s,j,j+1);
    }

    冒泡排序for循环的作用(结果):

    第一层i循环结束时data[i]是i之后的元素中中最小的元素

    第二层是为了两两比较交换,作用是将小的往上冒

    改进思路:

    我们每进行了一次第一层for循环后,data[i]已经是最小了,以及i之后的元素相比上一次for循环是相对有序的,而我们目前的程序没有利用这样以后相对有序的结果,再次进行两两比较,降低了效率。

    比如:

    当遇到21345的情况时,避免i以及循环了,且交换1,2后为:12345,
    i循环到了3发现没有交换,但是i又还继续循环了4,5。

    代码改进

    int flag = 1;
    void BublleSortPlus(list *s){
        for(int i = 1; i < s->length && flag; i++)
        {//当循环了某个i之后没有发生交换,表明i之后的元素以排序
            flag = 0;
            for(int j = s->length - 1;j >= i;j--){
                if(s->data[j] > s->data[j+1])
                {
                    swap(s,j,j+1);
                    flag = 1;
                }
            }
        }
    }

    选择排序

    排序原理:第i个元素,与他 i 之后的n-i个元素进行比较,如果发现小的元素,记录下标,直到之后所有的元素比较完,就将data[i]和data[min]进行交换

    实现代码:

    void SelectSort(list *s){
        for(int i = 1; i < s->length;i++){
            int min = i;
            for(int j = i + 1; j <= s->length;j++)
                if(s->data[min] > s->data[j]) 
                    min = j;
            if(min != i)    swap(s,i,min);
        }
    } 

    插入排序

    插入排序相对于前面两种平均时间复杂度是比较低的,只有O(n^2/4),不过最差复杂度都是O(n^2)

    排序原理:类似我们打扑克牌,拿到牌后进行整牌。拿到第 i 个元素与他前面的i-1个元素进行比较,比较时将元素往后挪,直到遇到比data[i]小的元素,就插入。因为i时从2开始所以确保了i之前的元素时有序的。

    void InsertSort(list *s){
        int i,j;
        for(i = 2;i <= s->length;i++){
        //i遍历为第二个到第n个。 
            if(s->data[i]<s->data[i-1]){
                s->data[0] = s->data[i];
                int j;
                for(j = i-1;s->data[j] > s->data[0];j--){
                    s->data[j+1] = s->data[j];
                }
                s->data[++j] = s->data[0];
            }
        }
    } 
  • 相关阅读:
    关于delphi xe8安装完之后的关键步骤
    delphi xe8开发安卓程序:访问服务器上的配置文件
    delphi grideh使用
    delphi 获取可执行文件的当前路径
    Delphi XE10下用FireDAC与SQLite连接要注意的问题
    Google Map Api 自定义maker样式和InfoWindow样式(叠加层)
    地理定位(navigator.geolocation)
    document.documentElement和document.body的区别
    【JavaScript】Function类型
    Ubuntu 14.04 安装 php5.6
  • 原文地址:https://www.cnblogs.com/liqiujiong/p/8871009.html
Copyright © 2020-2023  润新知