排序算法总结

def quick_sort(lis,s,e,r):
    """
    优点:快速简洁,不需要额外内存
    缺点:最差为n^2,不稳定,递归层数很深
    trick:打乱,tail sort
    """
    if s>=e:
        return
    if r<=0 or e-s < 5:
        for i in range(s,e+1):
            for j in range(i-1,s-1,-1):
                if lis[j] > lis[j+1]:
                    lis[j],lis[j+1]=lis[j+1],lis[j]
                else:
                    break
        return
    i = s
    j = e
    key = lis[i]
    while i < j:
        while lis[j] >= key and i < j:
            j -= 1
        lis[i] = lis[j]
        while lis[i] <= key and i < j:
            i += 1
        lis[j] = lis[i]
    lis[i] = key
    quick_sort(lis,s,i-1,r-1)
    quick_sort(lis,i+1,e,r-1)

def merge_sort(lis):
    """
    优点:快速,稳定
    缺点:需要额外储存空间
    trick:可以处理内存装不下的情况的排序,改用索引操作,减少移动次数
    """
    l = len(lis)
    if l <= 1:
        return lis
    lis1 = merge_sort(lis[:int(l/2)])
    lis2 = merge_sort(lis[int(l/2):])
    lis = []
    while lis1 and lis2:
        if lis1[0] > lis2[0]:
            lis.append(lis2.pop(0))
        else:
            lis.append(lis1.pop(0))
    return lis+lis1+lis2

def bubble_sort(lis):
    """
    优点:稳定,只需要比较相邻的元素
    缺点:慢
    trick:升级成鸡尾酒排序
    """
    l = len(lis)
    for i in range(l):
        flag = 0
        for j in range(1,l-i):
            if lis[j-1] > lis[j]:
                flag = 1
                lis[j-1],lis[j] = lis[j],lis[j-1]
        if flag == 0:
            return

def cocktail_sort(lis):
    l = len(lis)
    for i in range(int(l/2)+1):
        flag = 0
        for j in range(i+1,l-i):
            if lis[j-1] > lis[j]:
                flag = 1
                lis[j-1],lis[j] = lis[j],lis[j-1]
        if flag == 0:
            return
        for j in range(l-i-1,i,-1):
            if lis[j-1] > lis[j]:
                flag = 1
                lis[j-1],lis[j] = lis[j],lis[j-1]
        if flag == 0:
            return

def insert_sort(lis):
    """
    优点:稳定,小规模数据时较快,基本有序时较快
    缺点:大规模数据时慢
    trick:作为快排等的tail排序,序列较长时改进为希尔排序
    """
    l = len(lis)
    for i in range(1,l):
        value = lis[i]
        for j in range(i-1,-1,-1):
            if lis[j] > lis[j+1]:
                lis[j+1],lis[j]=lis[j],lis[j+1]
            else:
                break
def select_sort(lis):
    """
    优点:稳定,比插入排序位置移动少
    缺点:慢
    """
    l = len(lis)
    for i in range(l):
        key = i
        for j in range(i,l):
            if lis[j] < lis[key]:
                key = j
        lis[i],lis[key]=lis[key],lis[i]

def adjust_heap(lis,i,l):
    if i > int(l/2):
        return
    key = i
    if 2*i < l and lis[2*i] > lis[key]:
        key = 2*i
    if 2*i+1 < l and lis[2*i+1] > lis[key]:
        key = 2*i+1
    if key == i:
        return
    else:
        lis[i],lis[key]=lis[key],lis[i]
        adjust_heap(lis,key,l)

def init_heap(lis,l):
    for i in range(int(l/2),-1,-1):
        adjust_heap(lis,i,l)

def heap_sort(lis):
    """
    优点:快速,不需要额外内存,最差的情况可是O(nlgn)
    缺点:不稳定,局部性不强,跳着使用内存,有很多无效的比较
    """
    l = len(lis)
    init_heap(lis,l)
    for i in range(l-1,-1,-1):
        lis[0],lis[i] = lis[i],lis[0]
        adjust_heap(lis,0,i)

def shell_insert_sort(lis, dx, n):
    for pos in range(dx,n):
        index = pos
        while pos-dx >=0 and lis[pos] < lis[pos-dx]:
            lis[pos-dx],lis[pos] = lis[pos],lis[pos-dx]
            pos = pos-dx

def shell_sort(lis):
    """
    出乎意料的快
    """
    n = len(lis)
    delta = [1,2]
    while delta[-1]+delta[-2]<n:
        delta.append(delta[-1]+delta[-2])
    for dx in delta[::-1]:
        shell_insert_sort(lis, dx, n)

def counting_sort(lis,s,e):
    """
    优点:快
    缺点:假设很强,输入范围不能太广
    trick:升级成radix 排序和桶排序
    """
    n = (e-s+1)
    lis_aux = n*[0]
    lis2 = len(lis)*[0]
    for i in lis:
        lis_aux[i-s] += 1
    for i in range(1,n):
        lis_aux[i] += lis_aux[i-1]
    for i in lis[::-1]:
        lis2[lis_aux[i-s]-1] = i
        lis_aux[i-s] -= 1
    return lis2

def radix_sort():
    pass

def bucket_sort():
    pass

突破 O(nlgn) O ( n l g n ) 的高级排序算法简述

Munro和Raman给出一个稳定的排序算法,它在最坏情况下需要执行 O(n(1+ϵ)) O ( n ( 1 + ϵ ) ) 次比较,其中 0<ϵ1 0 < ϵ ≤ 1 是任意的固定常数。
尽管任一O(nlgn)时间算法所需比较次数更少,但Munro和Raman的算法仅需要将数据移动O(n)次,而且它是原址排序。

许多研究人员都对如何在 O(nlgn) O ( n l g n ) 时间内对n个b位整数进行排序做过研究,并已获得了一些有益的成果。
其中每一项成果都对计算模型做了略有不同的假设,对算法的限制也稍有差异。
所有这些成果都假设计算机内存被划分成可寻址的b位字。
Fredman和Willard引入融合树(fushion tree)这一数据结构,它可以在 O(nlgn/lglgn) O ( n l g n / l g l g n ) 时间内对 n n 个整数进行排序。
Andersson将这一界改善为O(nsqrt(lgn))
这些算法要用到乘法和几个预先计算好的常量。
Andersson、Hagerup、Nilson和Raman给出了一种不用乘法可以在 O(nlglgn) O ( n l g l g n ) 时间内对n个整数进行排序的算法。
但是,该算法所需要的存储空间以 n n 来表示的话,可能是无界的。
利用乘法散列技术,我们可以将所需的存储空间降至O(n),最坏情况运行时间的界 O(nlglgn) O ( n l g l g n ) 成为期望运行时间的界。
通过一般化Andersson提出的指数搜索树,Thorup给出一个 O(n(lglgn)2) O ( n ( l g l g n ) 2 ) 时间的排序算法,该算法不使用乘法和随机化,并且只需要线性存储空间。
Han把这些技术与一些新的想法结合起来,将排序算法的界改善至 O(nlglgnlglglgn) O ( n l g l g n l g l g l g n ) 时间。
尽管上述算法有着重要的理论突破,但都太复杂。
就目前的情况来看,它们不太可能在实践中与现有的排序算法竞争。

import random
import time
lis = []
lis2 = []
n = 100000
for i in range(n):
    num = random.randint(0,10)
    lis.append(num)
    lis2.append(num)
# print(lis)
# print(lis2)
now = time.time()
lis.sort()#0.0249969959259s 100000
print(time.time()-now)
now = time.time()
# quick_sort(lis2,0,len(lis2)-1,10) #递归层数太深,限制深度+tail sort 35.4185571671s 100000
# lis2 = merge_sort(lis2) #2.67715215683s 100000
# bubble_sort(lis2) #853.174901962s 100000
# cocktail_sort(lis2) #691.719685078s 100000
# insert_sort(lis2) #644.47479105ss 100000
# select_sort(lis2) #385.849671125s 100000
# heap_sort(lis2) #1.4s 100000
# shell_sort(lis2) #0.39s 100000
lis2 = counting_sort(lis2,0,10) #0.0284290313721s 100000
print(time.time()-now)
print(lis == lis2)
# print(lis)
# print(lis2)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值