zoukankan      html  css  js  c++  java
  • 程序猿修仙之路--算法之选择排序

    “大菜”:时刻提醒自己,技术之路修远兮,予以自勉。

    算法主要衡量标准

    • 时间复杂度(运行时间)

    在算法时间复杂度维度,我们主要对比较和交换的次数做对比,其他不交换元素的算法,主要会以访问数组的次数的维度做对比。

    其实有很多同学对于算法的时间复杂度有点模糊,分不清什么所谓的 O(n),O(nlogn),O(logn)...等,也许下图对一些人有一些更直观的认识。

    image

    • 空间复杂度(额外的内存使用)

    排序算法的额外内存开销和运行时间同等重要。 就算一个算法时间复杂度比较优秀,空间复杂度非常差,使用的额外内存非常大,菜菜认为它也算不上一个优秀的算法。

    • 结果的正确性

    这个指标是菜菜自己加上的,我始终认为一个优秀的算法最终得到的结果必须是正确的。就算一个算法拥有非常优秀的时间和空间复杂度,但是结果不正确,又有什么意义呢?

    原理

    在起始位置右侧(或左侧)找出最小的那个元素,然后和起始位置的元素交换

    选择排序是一个不稳定的排序算法

    具体步骤如下:

    1. 在一个数据列表中找到最小的那个元素,将它和列表的第一个元素交换位置。
    2. 在第二个元素位置开始再次寻找最小的那个元素,然后和列表的第二个位置的元素交换。
    3. 在第三个元素位置开始再次寻找最小的那个元素,然后和列表的第三个位置的元素交换
    4. 如此反复,直到开始查找起始位置到达列表末尾。

    如果查找过程中最小的元素就是起止位置的元素,那么它就和它自己交换。

    ++因为这种算法总是在不断的选择剩余元素中最小者,因此得名选择排序++

    image

    复杂度

    • 时间复杂度
    1. 比较次数

    对于长度为N的列表,选择排序需要大约n² /2次比较.即:O(n²)平方级别。

    1. 交换次数

    对于长度为N的列表,选择排序需要大约N次交换.即:O(N) 线性级别。

    性能和特点

    总体来说,选择排序是一种比较简单的排序算法,很容易理解也很好用代码实现,当然他的特点也很明显:

    运行时间和数据初始状态无关

    为什么这么说呢?算法进行中为了查找最小的元素而遍历列表并不能为下次遍历带来任何信息,这个特性在大部分情况下是缺点。如果一个数据列表初始状态是有序的或者部分有序的,选择排序仍然需要全部扫描一次和交换。因此和一个完全无序的列表排序所花的时间相差不大。

    数据移动次数是最少的

    每次交换只会改变两个列表元素,因此长度为N的列表只会发生N次交换,交换次数和列表的长度是线性关系,其他算法都不具备这个特性。

    适用场景

    由于选择排序的对比次数在平方级别,但是移动次数在线性级别,所以当N比较小的时候比较适用。

    其他

    • 为什么选择排序不稳定呢?

    首先我们要明白算法稳定是什么意思呢?

    在待排序的数据中,存在多个相同的数据,经过排序之后,他们的相对顺序依旧保持不变,实际上就是说array[i]=array[j],i<j.就是array[i]在array[j]之前,那么经过排序之后array[i]依旧在array[j]之前,那么这个排序算法稳定,否则,这个排序算法不稳定。

    根据以上定义很容易可以得出这样的结论:

    我们举出一个实例,序列5 8 5 2 9, 这个在执行选择排序的时候,第一遍,肯定会将array[0]=5,交换到2所在的位置,也就是 2 8 5 5 9,那么很显然,之后的排序我们就会发现,array[2]中的5会出现在原先的array[0]之前,所以选择排序不是一个稳定的排序

    实现案例

    (c#)
            static void Main(string[] args)
            {
                List<int> data = new List<int>() ;
                for (int i = 0; i < 10; i++)
                {
                    
                    data.Add(new Random(Guid.NewGuid().GetHashCode()).Next(1, 100));
                }
                //打印原始数组值
                Console.WriteLine($"原始数据: {string.Join(",", data)}");
                int n = data.Count;
                for (int i = 0; i < n; i++)
                {
                    int minIndex = i;
                    //查找最小的元素的索引
                    for (int j = i+1; j < n; j++)
                    {
                        if (data[j] < data[minIndex])
                        {
                            minIndex = j;
                        }
                    }
                    //交换最小的元素和当前位置的元素,当然这里可以加入一个最小元素是否是当前位置元素的判断来较少交换次数
                    int tempItem = data[i];
                    data[i] = data[minIndex];
                    data[minIndex] = tempItem;
    
                }
                //打印排序后的数组
                Console.WriteLine($"排序数据: {string.Join(",", data)}");
                Console.Read();
            }
    

    运行结果:

    原始数据:97,85,61,22,62,12,67,22,68,42

    排序数据:12,22,22,42,61,62,67,68,85,97

    Go

    家里没环境,还得翻墙,以后再补上吧,望见谅。


    独乐不如众乐

    老妈刚要收拾收拾卫生...老公就笑着说道:“妈,您大老远过来,哪能让你打扫家务...”然后老公就让我带我妈出去逛逛街,家务他全包了...就这样,我被老妈拉了出去,我生气的对老妈说道:“明明我都看到地毯底下的钱了,为什么不让我拿出来!”老妈淡定的说道:“要嘛,你现在回去把那钱拿出来翻脸!要嘛,现在就跟我逛街去!以后家务也不用做了!你选吧...

    转载请标明出处 ^ ~ ^ 。部分图片来源于网络,如有侵权请及时联系。让我们一起进步吧

    一个不止于IT圈内容的微信公众号,欢迎关注,交流更多的IT知识。

  • 相关阅读:
    Linux之iptables 防火墙学习
    CentOS下安装JDK7
    分布式日志系统Scribe安装
    Python解析XML
    Python目录操作
    iphone开发-绘图集合 HA
    Mac技巧之显示/隐藏苹果MacOSX系统下隐藏文件的终端命令 HA
    xcode技巧宏定义 HA
    Registering Custom URL Schemes and Handling URL Requests HA
    block about basic HA
  • 原文地址:https://www.cnblogs.com/zhanlang/p/9901764.html
Copyright © 2011-2022 走看看