首页 > 编程语言 > 详细

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

时间:2019-05-03 13:56:31      阅读:125      评论:0      收藏:0      [点我收藏+]

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

时间复杂度

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

技术分享图片

技术分享图片

技术分享图片

时间复杂度-小结:

技术分享图片

快速地判断算法复杂度:

简单情况:

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

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

稳定性:

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

 

1、冒泡排序(Bubble Sort)

算法描述

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

动图

技术分享图片

代码实现

def bubble_sort(li):
    # 第一层循环,总共需要循环几趟
    # 默认最后一躺的那个数字已经是最大or最小值,所以最后一趟不用走了(能省则省)
    for i in range(len(li) - 1):

        exchange = False  # 此标志位用来检测该躺有没有发生前后值的替换,如果没有的话,说明列表已经有序,后面无需循环

     # 第二层循环,就是循环比较无序区中的数字
for j in range(len(li) - i - 1): # -i(i 躺数):每一趟就会产生一个有序区的数字在最后面,我们循环只负责找无序区的数字 # -1 n个数,相邻替换的次数比len少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)

##[9, 8, 7, 6, 5, 4, 3, 2, 1]

小结:

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

2、选择排序(Selection Sort)

算法描述

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

动图演示

技术分享图片

代码演示

def select_sort(li):

    # 第一次循环,循环几趟
    for i in range(len(li) - 1):
        # -1:每一次循环都要选择第一个数出来和后面的数进行比较 所以要-1, 比如[4, 1, 2, 3]
        min_sol = i

        # 第二层循环,无序区中每个数都与第一个数字进行比较
        for j in range(i+1, len(li)):
            # 每次比较都是无序区中的数字,所以是 除了抽出来的数字 到最后一个数字
            if li[j] > li[min_sol]:
                min_sol = j

        li[i], li[min_sol] = li[min_sol], li[i]

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

小结:

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

3、插入排序(Insertion Sort)

算法描述

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

实现思路:

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

动图演示

技术分享图片

技术分享图片

 

代码实现

def insert_sort(li):

    for i in range(1, len(li)):
        j = i - 1   # j 为手里最大的牌

        while j >= 0 and li[j] > li[i]:     # 只要手里最大的牌比摸回来的牌大就一致往右移动
            # j >= 0 ,说明所有数都比摸到的牌要大,直接退出循环
            li[j+1] = li[j]     # 右移
            j -= 1

        li[j+1] = li[i]     # 确定要插入的时候,是必须插到j的前一个位置

 小结:

  • 时间复杂度:n方
  • 原地排序
  • 没有跳着(跳着无序区的数字)插入,所以具有稳定性。

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

原文:https://www.cnblogs.com/Xuuuuuu/p/10804830.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!