一些排序算法的代码实现——Python

        记录一下学习过程,大部分代码和教材(Python数据结构)上一致,做了一小部分修改,例如用索引代替列表切片操作,算是完成课后习题吧。

首先是三个经典的排序算法,冒泡,插入,选择。它们思路简单但时间复杂度较高n^{2}

冒泡

对冒泡排序进行了小小的修改,在序列已经有序之后可以提前退出

def Bubblesort(alist):#冒泡(改)
     exchanges = True#这里是改进的地方
     right = len(alist)-1
     left = 0
     while right>left and exchanges:
          exchanges = False
          for i in range(left,right):
               if alist[i]>alist[i+1]:
                    exchanges=True
                    alist[i],alist[i+1]=alist[i+1],alist[i]
          right = right-1
          for j in range(right,left,-1):
               if alist[j]<alist[j-1]:
                    alist[j],alist[j-1]=alist[j-1],alist[j]

插入和选择

插入排序是维护一个有序的序列,选择一个数,插入有序的序列中

选择排序则是生成一个有序的序列,始终选择最大的那个数,这样由它们生成的序列就是有序的

 

def selectionSort(alist):#选择
     for fillslot in range(len(alist)-1, 0, -1):
          positionOfMax = 0
          for location in range(1, fillslot+1):
               if alist[location] > alist[positionOfMax]:
                    positionOfMax = location
          alist[fillslot],alist[positionOfMax]=alist[positionOfMax],alist[fillslot]


def insertionSort(alist):#插入
     for index in range(1, len(alist)):
          currentvalue = alist[index]
          position = index
          while position > 0 and alist[position-1] > currentvalue:
               alist[position] = alist[position-1]
               position = position-1
          alist[position] = currentvalue

希尔排序

        是更高级的插入排序,把数据分组,对每个小组进行插入排序,之后不断减少组数,增加每组所包含的数的数量,如第一开始两个数一组,分成n/2个组,第二遍四个数一组,分成n/4组,直到最后所有数都为一组,序列就是有序的了。

def shellSort(alist):#希尔
     sublistcount = len(alist) // 2
     while sublistcount > 0:
          for startposition in range(sublistcount):
               gapInsertionSort(alist, startposition, sublistcount)
          sublistcount = sublistcount // 2

def gapInsertionSort(alist, start, gap):
     for i in range(start+gap, len(alist), gap):
          currentvalue = alist[i]
          position = i
          while position >= gap and alist[position-gap] > currentvalue:
               alist[position] = alist[position-gap]
               position = position-gap
          alist[position] = currentvalue

归并排序

一个序列先不断二分拆成一个一个的数,再合并为有序的序列,排序是在合并时进行的。

加入了索引,来避免列表切片操作

def mergeSort(alist):#归并(改)
     j=0
     for i in mergeSortHelp(alist,0,len(alist)-1)[:]:
          alist[j]=i
          j+=1
     
def mergeSortHelp(alist,start,end):
     if end-start>=1:
          mid=(start+end)//2
          lefthalf=mergeSortHelp(alist,start,mid)
          righthalf=mergeSortHelp(alist,mid+1,end)
          rest=[]
          i,j=0,0
          while i < len(lefthalf) and j < len(righthalf):
               if lefthalf[i] < righthalf[j]:
                    rest.append(lefthalf[i])
                    i = i + 1
               else :
                    rest.append(righthalf[j])
                    j = j + 1
          while i < len(lefthalf):
                    rest.append(lefthalf[i])
                    i = i + 1
          while j < len(righthalf):
                    rest.append(righthalf[j])
                    j = j + 1
          return rest
     else :
          return [alist[start]]

快速排序

        选择一个数作为基准,比它大的放右边,比它小的放左边,再分别对左边和右边进行同样的操作,直到左右只剩一个元素,有一种递归的感觉。 

修改后的,再选基准元素时,在三个里面选中间的,尽量避免了选择过大或者过小的元素。

def quickSort(alist, first, last):#快速排序
     if first < last:
          pivotvalue = alist[first]
          leftmark = first + 1
          rightmark = last
          done = False
          while not done:
               while leftmark <= rightmark and alist[leftmark] <= pivotvalue:
                    leftmark = leftmark + 1
               while alist[rightmark] >= pivotvalue and rightmark >= leftmark:
                    rightmark = rightmark - 1
               if rightmark < leftmark:
                    done = True
               else:
                    temp = alist[leftmark]
                    alist[leftmark] = alist[rightmark]
                    alist[rightmark] = temp
          temp = alist[first]
          alist[first] = alist[rightmark]
          alist[rightmark] = temp
          quickSort(alist, first, rightmark-1)
          quickSort(alist, rightmark+1, last)


def quickSort3(alist,first,last):#快速排序改
     if first < last:
          pivotvalue = middle(alist[first],alist[last],alist[(first+last)//2])
          leftmark = first
          rightmark = last
          while rightmark>leftmark:
               while alist[leftmark] <= pivotvalue:
                    leftmark = leftmark + 1
               while alist[rightmark] >= pivotvalue:
                    rightmark = rightmark - 1
               if rightmark > leftmark:
                    temp = alist[leftmark]
                    alist[leftmark] = alist[rightmark]
                    alist[rightmark] = temp
          quickSort(alist, first, rightmark)
          quickSort(alist, rightmark, last)
     
def middle(a,b,c):
     li=[a,b,c]
     li.sort()
     return li[1]

对比一下这几种算法的运行时间

import random
alist=[i for i in range(500)]
random.shuffle(alist)
import timeit
t1=timeit.Timer('Bubblesort(alist[:])','from __main__ import alist,Bubblesort' )
t2=timeit.Timer('selectionSort(alist[:])','from __main__ import alist,selectionSort' )
t3=timeit.Timer('insertionSort(alist[:])','from __main__ import alist,insertionSort' )
t4=timeit.Timer('shellSort(alist[:])','from __main__ import alist,shellSort' )
t5=timeit.Timer('mergeSort(alist[:])','from __main__ import alist,mergeSort' )
t6=timeit.Timer('quickSort(alist[:],0,len(alist[:])-1)','from __main__ import alist,quickSort' )
t7=timeit.Timer('quickSort3(alist[:],0,len(alist[:])-1)','from __main__ import alist,quickSort3')
t8=timeit.Timer('alist[:].sort()','from __main__ import alist')
print(t1.timeit(number=100))
print(t2.timeit(number=100))
print(t3.timeit(number=100))
print(t4.timeit(number=100))
print(t5.timeit(number=100))
print(t6.timeit(number=100))
print(t7.timeit(number=100))
print(t8.timeit(number=100))

'''
运行结果
冒泡1.5784653999999998
选择0.6926877
插入0.9691874
希尔0.1233234000000003
归并0.12611349999999977
快速0.0806591000000001
快速改0.08754919999999977
列表类提供的sort方法0.003951200000000377
'''

        可以看出冒泡、选择、排序这三个运行时间还是较长的,希尔、归并、快速时间复杂度平均都是nlogn,运行时间比较短,改进选择基准值的快速排序算法,作用不大,但是这六个相对于列表类提供的sort(),都慢了太多太多。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值