三种NB的排序

主要内容:

  • 1.快速排序
  • 2.堆牌
  • 3.归并排序

1. 快速排序

  • 取一个元素p(第一个元素),使元素p归位;
  • 列表被p分成两部分,左边都比p小,右边都比p大;
  • 递归完成排序

1.1 快排代码书写

import random
from cal_time import cal_time

def _quick_sort(lst,left,right):
    if left < right:
        mid = partition(lst,left,right)
        _quick_sort(lst,left,mid-1)
        _quick_sort(lst,mid+1,right)

def partition(lst,left,right):
    tmp = lst[left]

    while left < right:
        while left < right and lst[right] >= tmp:
            right -=1
        #当这个while循环退出时,将右边比tmp大的数放到左边
        lst[left] = lst[right]
        #此时进入下边的while循环,从左边选出比tmp大的数去田右边刚留出的空
        while left < right and lst[left] <= tmp:
            left +=1
        #循环退出时候,将比tmp大的数放到右边
        lst[right] = lst[left]
    #循环退出
    lst[left] = tmp
    return left


@cal_time
def quick_sort(li):
    _quick_sort(li, 0, len(li)-1)

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

quick_sort(li)

#quick_sort running time: 0.021941661834716797 secs.

1.2 快排的时间复杂度    O(nlogn)

  • 递归深度并不是很大 , 因为他是分层的,每次大概少一半 

1.3 快排的问题

  • 最坏情况: 当所有的数是倒序 ,此时不是logn层,每次递归只让元素少一个,时间复杂度编程 O(n^2)     (可以通过修改partition函数进行解决)
    def partition(li, left, right):
        i = random.randint(left, right)
        li[i], li[left] = li[left], li[i]
        tmp = li[left]
        while left < right:
            while left < right and li[right] >= tmp:
                right -= 1
            li[left] = li[right]
            while left < right and li[left] <= tmp:
                left += 1
            li[right] = li[left]
        li[left] = tmp
        return left
  • 递归

1.4 另一种partition的写法

#将最后一个元素归为
def partition2(li, left, right):
    # 区域1:[left, i] 区域2:[i+1, j-1]
    i = left - 1 # 初识区域1和区域2都空  left = i此时就时有值的所以只能-1
    for j in range(left, right):
        if li[j] < li[right]: # 归到区域1
            i += 1
            li[j], li[i] = li[i], li[j]
    li[right], li[i+1] = li[i+1], li[right]
    return i+1

 

posted @ 2019-03-27 16:54  一路向北_听风  阅读(212)  评论(0)    收藏  举报