Python:经典排序算法实现

最近回去复习一下排序算法,就想起用Python实现看看。(注:部分代码参考wiki)

执行效率:

BubbleSort: 5.64282536674
MergeSort: 0.0852148677502
HeapSort: 1.56255770524
ShellSort: 0.0197063255004
InsertionSort: 0.00171472623788
SelectionSort: 3.58283402721
CocktailSort: 0.000626048759962

请忽略,这个不具备参考价值。其实,Python里sort函数已经做到最优了,不需如此大费周章,

只是为了自己熟悉这些内容,代码如下:

# -*- coding:utf-8 -*-
'''
Created on 2014-11-26

@author: L
'''
import timeit

alist = sorted(xrange(1,10000),key=lambda x:len(str(x)), reverse=True)
n = len(alist)

def Swap(valueA,valueB):
    (valueA,valueB) = (valueB,valueA)
    return
'''快速排序
1、选择轴值: 需求中心点的值,或者任意值
2、分组:重新排列数组,将比轴值大的放在数组左边,比轴值少的放在数组右边,
3、按2的方法,递归排序两边数组
'''
def Partition(alist,left,right):
    pivot = alist[(left + right)/2]
    (i,j) = (left,right)
    while i <= j:
        while alist[i] < pivot:
            i += 1
        while alist[j] > pivot:
            j -= 1
        
        if i <= j:
            (alist[i],alist[j]) = (alist[j],alist[i])
            i += 1
            j -= 1
    return i

def QuickSort(alist,left,right):
    index = Partition(alist,left,right)
    if index-1 > left:
        QuickSort(alist,left,index-1)
    if index < right:
        QuickSort(alist,index,right)

'''冒泡算法
1、 比较相邻两个元素的值,如果前面元素大于后面元素,则交换两个元素;
2、按1的逻辑,对0到N-i(i为遍历次数)个元素进行遍历
'''
def BubbleSort(alist,length):
    assert len(alist) >= length
    for i in xrange(0,length):
        for j in xrange(1,length-i):
            if alist[j-1] > alist[j]:
                (alist[j-1],alist[j]) = (alist[j],alist[j-1])
    return

'''冒泡算法2 又称  鸡尾酒排序
1、从左到右对数组进行升序的冒泡排序
2、从右到左对数组进行降序的冒泡排序
3、依次类推,不断缩小排序范围,直到最后一个元素
'''
def CocktailSort(alist):
    left = 0
    right = len(alist) -1
    index = left
    while(left < right):
        for i in xrange(left,right):
            if alist[i] > alist[i+1]:
                (alist[i+1],alist[i]) = (alist[i],alist[i+1])
                index = i + 1

        right = index
        for i in xrange(right,left,-1):
            if alist[i-1] > alist[i]:
                (alist[i-1],alist[i]) = (alist[i],alist[i-1])
                index = i
        left = index
            
    return

'''选择排序
每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完
'''
def SelectionSort(alist):
    end = len(alist)
    for i in xrange(0,end-1):
        mimal = i
        for j in xrange(i+1,end):
            if alist[j] < alist[mimal]:
                mimal = j
        if mimal != i:
            (alist[i],alist[mimal]) = (alist[mimal],alist[i]) 
            
    return        

'''插入排序
将数组分成两部分:有序数组 和 无序数组。初始化,有序数组为第一个元素,无序数组为剩下的,每次从无序数组取第一个元素插入有序数组中,知道无序数组为空
类似于选择排序
'''
def InsertionSort(alist):
    end = len(alist)
    for i in xrange(1,end):
        newValue = alist[i]
        j = i
        while j > 0 and alist[j-1] > newValue:
            alist[j] = alist[j-1]
            j -= 1
            
        alist[j] = newValue
'''二分法搜索  binary search
'''
def BinarySearch(alist,value,left,right):
    if left > right:
        return -1
    
    middle = (left + right) /2
    if alist[middle] == value:
        return middle
    if alist[middle] > value:
        return BinarySearch(left,middle-1)
    if alist[middle] < value:
        return BinarySearch(middle+1,right)
    
'''希尔排序 步长序列
'''    
def GetSedgewickSteps(n):
    steps = []
    step = 1
    k = 0
    for k in xrange(0,n):
        step = 9 * (4**k - 2**k) + 1
        if step >= n:
            break
        steps.append(step)
        step = 2**(k + 2)*(2**(k + 2) -3) + 1
        if step >= n:
            break
        steps.append(step)
    
    return sorted(steps,reverse=True)

'''希尔排序,是基于【插入排序对几乎排好序的序列,效率可达线性】的特点就行改进的
1、按照一定的步长将原数组分成若干个子数组,分别进行直接插入排序;
2、根据一定的增量,是步长逐步减少,反复进行1的操作,当步长接近1的时候,原数组几乎排好序
3、步长为1,进行普通的插入排序
例如: 【1,8,2,4,3,0,5,7,11,9,17,36】,步长=5 分成3组,对每列排序
1  8  2  4  3   0  5  2  4  3
0  5  7  11 9   1  8  7  11 9
17 36           17 36
依次将步长减少
最好步长序列是由Sedgewick提出的 (1, 5, 19, 41, 109,...),该序列的项来自 9 \times 4**i - 9 \times 2**i + 1 和 2**{i+2} \times (2**{i+2} - 3) + 1 这两个算式
'''
def ShellSort(alist):
    n = len(alist)
    steps = GetSedgewickSteps(n)
    for s in steps:
        for i in xrange(s,n):
            j = i -s
            tmp = alist[i]
            while(j >= 0 and alist[j] > tmp):
                alist[j+s] = alist[j]
                j -= s
            alist[j+s] = tmp     
'''堆排序
1、最大堆调整,将堆的末端子节点调整,使得子节点永远小于父节点
2、创建最大堆,将堆所有数据进行排序
3、移除位于第一个数据的根节点,并做最大堆调整的递归运算
堆:子结点的键值或索引总是小于(或者大于)它的父节点
父节点i的左子节点:2*i+1
父节点i的右子节点:2*i+2
子节点i的父节点:floor((i-1)/2)
'''
def HeapSort(alist):
    def HeadAdjust(start,end):
        root = start
        while True:
            child = 2 * root + 1
            if child > end:
                break
            while child + 1 <= end and alist[child] < alist[child+1]:
                child += 1
            if alist[root] < alist[child]:
                alist[root],alist[child] = alist[child],alist[root]
                root = child
            else:
                break
    
    for start in xrange((len(alist) -2 )/2,-1,-1):
        HeadAdjust(start,len(alist) -1)
    
    for end in xrange(len(alist) -1,0,-1):
        alist[end],alist[0] = alist[0],alist[end]
        HeadAdjust(0,end-1)
    
    return alist

'''归并排序
指的是将两个已经排序的序列合并成一个序列的操作。归并排序算法依赖归并操作
'''
def MergeSort(alist):
    if (len(alist) <= 1):
        return alist
    
    def Merge(left,right):
        merged = []
        while left and right:
            merged.append(left.pop(0) if left[0] < right[0] else right.pop(0))
        while left:
            merged.append(left.pop(0))
        while right:
            merged.append(right.pop(0))
        return merged
    
    middle = int(len(alist) / 2)
    left = MergeSort(alist[:middle])
    right = MergeSort(alist[middle:])
    
    return Merge(left,right)

            
if __name__ == '__main__':
    tmp = alist
    print 'BubbleSort: ' + str(timeit.Timer('BubbleSort(tmp,n)','from __main__ import BubbleSort,tmp,n').timeit(1))
    tmp = alist
    print 'MergeSort: ' + str(timeit.Timer('MergeSort(tmp)','from __main__ import MergeSort,tmp').timeit(1))
    tmp = alist
    print 'HeapSort: ' + str(timeit.Timer('HeapSort(tmp)','from __main__ import HeapSort,tmp').timeit(1))
    tmp = alist
    print 'ShellSort: ' + str(timeit.Timer('ShellSort(tmp)','from __main__ import ShellSort,tmp').timeit(1))
    tmp = alist
    print 'InsertionSort: ' + str(timeit.Timer('InsertionSort(tmp)','from __main__ import InsertionSort,tmp').timeit(1))
    tmp = alist
    print 'SelectionSort: ' + str(timeit.Timer('SelectionSort(tmp)','from __main__ import SelectionSort,tmp').timeit(1))
    tmp = alist
    print 'CocktailSort: ' + str(timeit.Timer('CocktailSort(tmp)','from __main__ import CocktailSort,tmp').timeit(1))
    print 'end'


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值