三种较low排序

主要内容

  • 1.冒泡排序
  • 2.选择排序
  • 3.插入排序

1. 冒泡排序

时间复杂度 : O(n2)

原理:

  • 比较相邻的元素,如果后一个比前一个大就进行交换
  • 对每一对相邻元素做同样的工作,完成以后,最后的元素会是最大的数,这里可以理解为走了一趟;
  • 针对所有的元素重复以上的步骤,除了最后一个

冒泡排序代码

import random
from cal_time import cal_time

@cal_time
def bubble_sort(lst):
    for i in range(len(lst)-1):  # i 表示要进行冒泡比较的趟数
        # 第i趟的无序区位置 [0,n-1-i]
        for j in range(len(lst) -i -1):
            if lst[j] > lst[j+1]:
                #下一个数比当前的大就进行交换
                lst[j],lst[j+1] = lst[j+1],lst[j]

# 测试:
lst = list(range(10000))
random.shuffle(lst)
bubble_sort(lst)
#bubble_sort running time: 7.759883880615234 secs

 

代码做一次优化:

@cal_time
def bubble_sort(lst):
    for i in range(len(lst)-1):  # i 表示要进行冒泡比较的趟数
        # 第i趟的无序区位置 [0,n-1-i]
        exchange = False
        for j in range(len(lst) -i -1):
            if lst[j] > lst[j+1]:
                #下一个数比当前的大就进行交换
                lst[j],lst[j+1] = lst[j+1],lst[j]
                exchange = True
        if not exchange:
            return

对于时间复杂度的具体讨论:

  • 最好情况 :此时的列表已将排好序,此时无序进行交换 时间复杂度为 O(n)
  • 平均情况 :此时的列表为正常的无序状态, 时间复杂度为O(n^2)
  • 最坏情况 :此时列表是倒序,每次都需要进行交换 时间复杂度为O(n^2)

2. 选择排序

  • 一趟遍历记录最小的数,放到第一个位置
  • 再一趟遍历记录剩余列表中最小的数,继续放置

 

关键: 

  • 无序区
  • 最小数的位置
def find_min(lst):
    min_num = lst[0]
    for i in range(1,len(lst)):
        if lst[i] < min_num:
            min_num = lst[i]
    return min_num

#获取最小数的位置
def find_min_pos(lst):
    min_pos = 0
    for j in range(1,len(lst)):
        if lst[j] < lst[min_pos]:
            min_pos = j
    return min_pos

代码 时间复杂度 O(n^2)

import  random
from cal_time import cal_time

@cal_time
def select_sort(lst):
    for i in range(len(lst) -1):
        #第 i趟无序区 [i,len(lst)-1]
        #找无序区最小数的位置,和无序区第一个数进行交换
        min_pos = i
        for j in range(i+1,len(lst)):
            if lst[j] < lst[min_pos]:
                min_pos = j
        lst [min_pos],lst[i] = lst[i],lst[min_pos]


li = list(range(10000))
random.shuffle(li)
select_sort(li)

#select_sort running time: 3.5867788791656494 secs.

3. 插入排序

  • 将列表分为有序区和无序区两个部分,最初有序区只有一个元素
  • 每次从无序区选择一个元素,插入到有序区的位置,知道无序区变空 
import random
from cal_time import cal_time

@cal_time
def insert_sort(lst):
    for i in range(1,len(lst)):  # 从无序区摸排,表示第i趟,i表示摸到的牌
        tmp = lst[i]             # tmp表示摸到的牌的值
        #摸到的牌前一张,即有序区最后一张牌的下标为j
        j = i - 1
        while j >=0 and lst[j] > tmp: #只要往后挪就循环,2个条件都满足
            #如果j =-1 就停止挪,如果lst[j]小了就停止挪
            lst[j+1] = lst[j]
            j -=1
        #j位置在循环结束的时
        # 候要么是-1 要么是一个比tmp小的值的下标
        lst[j+1] = tmp
li = list(range(10000))
random.shuffle(li)
insert_sort(li)

 

posted @ 2019-03-25 20:30  一路向北_听风  阅读(155)  评论(0)    收藏  举报