为了账号安全,请及时绑定邮箱和手机立即绑定

不懂算法的程序员不是好工程师--选择排序

标签:
C# 算法

算法主要衡量标准


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

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

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

https://img1.sycdn.imooc.com/5de7c7a40001054e06890323.jpg

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

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

结果的正确性

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

原理


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

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

具体步骤如下:

  1. 在一个数据列表中找到最小的那个元素,将它和列表的第一个元素交换位置。

  2. 在第二个元素位置开始再次寻找最小的那个元素,然后和列表的第二个位置的元素交换。

  3. 在第三个元素位置开始再次寻找最小的那个元素,然后和列表的第三个位置的元素交换

  4. 如此反复,直到开始查找起始位置到达列表末尾。

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

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

复杂度

  • 时间复杂度
  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

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


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消