选择排序

原理

# 循环列表,每次循环找到列表中的最小数,放到一个位置上;
# 再次循环找到剩下列表中的最小数,放在之前找到的最小数下一个位置。

代码实现

初步实现思路

# 循环列表,找到列表中的最小数,将这个最小数从原列表中取出后放入一个空的新列表中;
# 不过这种实现思路会导致同时存在两个列表,空间复杂度较高

初步实现代码

# -*- coding: utf-8 -*-
# created by X. Liu on 2020/3/8

def select_sort_simple(li):
    new_li = []
    for _ in range(len(li)):        # 循环中不实用循环次数的值,故使用占位符 _
        min_val = min(li)           # min()函数是一个O(n)的循环操作
        new_li.append(min_val)
        li.remove(min_val)          # remove()函数也是一个O(n)的循环操作
    return new_li                   # 整个算法的时间复杂度是O(n^2),空间复杂度O(n)

升级版思路

# 上述代码实现是通过一个新列表实现位的,但是会导致占用额外的内存空间
# 参考冒泡排序的原地交换思路,实现原地交换的选择排序
# 首先默认min_index等于无序区第一个位置,如果后面位置上的数比默认位置上的数小,即重置最小数的位置,
# 这样每趟循环后,min_index都是无序区最小数的位置。
# 将无序区第一个位置的数和min_index上的数交换,实现原地交换

升级版代码

def select_sort(li):
    for i in range(len(li) - 1):    # i表示循环趟数
        min_index = i               # 默认无序区的第一个位置上的元素最小,最为比较的参考对象
        for j in range(i+1, len(li)):    # j比较的起始位置,可以从i+1开始,减少一次和自己比较的循环
            if li[j] < li[min_index]:
                min_index = j               # 记录最小数的位置
        # 一趟循环后,找到无序区最小数的位置,交换无序区第一个位置的数和无序区最小的数
        li[i], li[min_index] = li[min_index], li[i]

动画演示

补充思考

def select_sort(li):
    for i in range(len(li) - 1):   
        min_index = i              
        for j in range(i+1, len(li)):   
            if li[j] < li[min_index]:
                min_index = j             
       
        li[i], li[min_index] = li[min_index], li[i]
        

        
# 上述实现思路和代码已经很简洁明了啦。但是在选择比较的过程中,我们是基于位置实现的:
# 也就是说,通过比较数据大小,记录最小数的所在的位置。
# 每趟循环后拿最小数所在的位置,交换两个

# 个人认为这样很好但是不是非常好理解。最简单的理解应该是比较大小后,直接交换两个数

def select_sort_v2(li):
    for i in range(len(li) - 1):
        # min_val = li[i]
        for j in range(i + 1, len(li)):
            if li[j] < li[i]:                   # 默认w无序区第一个数是最小的
                li[j], li[i] = li[i], li[j]
   
# 值得注意的是这样最然在思路和代码上看起来更容易理解,但是它也有一个不足:
# 不足在于它每趟循环内,在比较的过程中多次交换数据。在性能上不如select_sort()的一次交换
posted @ 2020-03-08 12:05  the3times  阅读(205)  评论(0)    收藏  举报