冒泡排序、选择排序、插入排序

在开始这三种算法的学习之前,我们要先来补给几个知识:

时间复杂度

时间复杂度:用来评估算法运行效率的一个式子

时间复杂度-小结:

快速地判断算法复杂度:

简单情况:

  • 确定问题规模n
  • 循环减半过程 -- logn
  • k层关于n的循环 n的k次方

复杂情况:根据算法执行过程判断

稳定性:

  相同值的情况下,排序完两个值的相对位置不会发生变化。

 

1、冒泡排序(Bubble Sort)

算法描述

比较相邻的两个元素,如果第一个比第二个大,就交换他们两个的位置。(每一趟都会冒出一个有序区的数。)

动图

 

代码实现

def bubble_sort(li):

    # 第一层循环几趟
    # len - 1,因为冒泡排序最后一趟的数字已经是最大的了,无需要再走一趟。
    for i in range(len(li) - 1):

        # 第二层循环,
        # - i:在无序区中比较两个数的大小,每一趟结束之后会产生一个有序数字
        # - 1:最后一个数字无须遍历,因为在第j次(倒数第二个数字)已经与j+1(倒数第一个数字)次进行了比较
        exchange = False
        for j in range(len(li) - i - 1):
            if li[j+1] < li[j]:      # 升序
                li[j+1], li[j] = li[j], li[j+1]
                exchange = True

        # 如果标志位没有变化,则说明这一趟中数字位置没有发生变化(即已经有序了),后面的趟没必要比较了
        if not exchange:
            return


li = [1, 2, 5, 3, 4, 6, 9, 8, 7]
bubble_sort(li)
print(li)

小结:

  • 选择排序时间复杂度:O的二次方
  • 原地排序
  • 比较时都是相邻的数进行比较(埃个比较),具有稳定性

2、选择排序(Selection Sort)

算法描述

每一趟选择一个数放在第一位,然后后面每个数都与这个数进行比较,如果比第一位数小的话就替换掉第一个数,然后后面的数再和新的最小值比较,一趟完成过后有序区产生一个有序数字,然后每一趟都循环无序区中的数字。

动图演示

代码演示

def select_sort(nums):

    # 因为遍历了n-1次之后 最后一个值肯定是最大的了,无序再遍历
    for i in range(len(nums) - 1):

        min_pos = i     # 当前遍历目标位置
        # i后面所有的数都和 目标位置的数值进行比较
        for j in range(i + 1, len(nums)):
            if nums[j] < nums[min_pos]:
                min_pos = j
        nums[min_pos], nums[i] = nums[i], nums[min_pos]
    return nums

  

小结:

  • 时间复杂度也是n方
  • 原地排序
  • 排序时发现一个数比第一个数小,直接隔离很多数换去第一个位置(跳着换),不具有稳定性。比如:[2,3,2,1,4], 1和第一个2换了,两个2的相对位置发生了变化
  • 和冒泡排序的区别,稳定性和不稳定性,冒泡排序的无序区在每一趟后面,选择排序的无序区在每一趟前面。

3、插入排序(Insertion Sort)

算法描述

它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置插入。

实现思路:

  1. 从第一个元素开始,该元素可以认为已经被排序;
  2. 取出下一个元素,在已经排序的元素序列从后向前扫描
  3. 如果该元素大于新元素,则该元素移动到下一位置。

动图演示

 

 

代码实现

def insert_sort(nums):

    for i in range(1, len(nums)):
        temp = nums[i]  # 要插入的值
        j = i - 1  # j为有序区中最大的值
        while j >= 0 and nums[j] > temp:    # 有序区中 所有比temp大的值全部往右移动
            nums[j + 1] = nums[j]
            j -= 1
        nums[j + 1] = temp
    return nums

 小结:

  • 时间复杂度:n方
  • 原地排序
  • 没有跳着(跳着无序区的数字)插入,所以具有稳定性。
posted @ 2019-05-03 12:51  下山打老虎i  阅读(535)  评论(0编辑  收藏  举报