常用排序 算法
常用排序算法:
检测算法执行效率:
# 检测算法执行效率 def caltime(func): def inner(*args,**kwargs): start = time.time() func(*args,**kwargs) end=time.time() print("%s时间是: %s"% (func.__name__,end-start)) return inner #
冒泡
#冒泡排序 # """ # 一个列表,从中拿一个元素k,和其他元素进行比较, # 如果k大,那么就继续和其他元素比较, # 如果k小,就交换位置(交叉赋值,从而k变成较大的元素)后,继续和其他元素比较,最k会变成最大的那个数,而且还在最右边(从小到大排序)。 # 确认一个数后,进行第二次比较(比较次数减1,因为k是最大的,所以没必要比),以此类推。 # 最终得到一个有序列表 # ps: 加入第一次比较 k就是最小的,没有和谁交换位置,那么说明这个列表本身就是有序的,后面的比较也就没有必要。 # # """ @caltime def BubbleSort(li): for i in range(len(li)): status = False #加入一个标记状态,一旦有交换位置就(改变)状态,(没变)就直接结束循环 for j in range(len(li)-i-1): #一开始-1是因为要拿出第一个数来作为比较值,减i 是因为一次循环比较都会确认一个最大的数。 if li[j]<li[j+1]: li[j],li[j+1] = li[j+1],li[j] status = True if not status: return
选择:
#选择排序 # """ # 1.从列表中拿出第1个数,并标记一下,然后在拿着这个数去和其他的数比较大小,如果第一个数大(小),就让他们交换一下位置, # 2. 继续拿着交换来的小数去和剩下的数比较,直到第一个数最小(最大) ,之后拿出第二个数重复第一个数的历程,以此类推 # """ @caltime def selectSort(li): for i in range(len(li)): biao = i for j in range(i+1,len(li)): if li[j] < li[biao]: li[j],li[biao] = li[biao],li[j]
插入排序:
#插入排序: 每次取一个列表元素与列表中已经排序好的列表段进行比较,然后插入从而得到新的排序好的列表段,最终获得排序好的列表。 # """ # 默认拿列表第一个元素作为有序列表[k,],(一个值就是有序的),所以从第二个值开始和 k 比较大小, # 如:大 插入k前面, # 小 就把 k往前面推一位(空出来的位置刚好留给插入的对比对象) # 然后,在和 k 后面的 值比较大小... # 以此类推,直到 k 后面没有值,就表示比较的对象最小,放在最后(列表第一个位置)。 # """ # 场景类似于把手中的乱牌排好序 @caltime def insertSort(li): for i in range(1,len(li)): #从第二个值开始 tmp = li[i] #第二个值 j = i-1 #这样得到 有序列表[k,] k的索引 #由上分析得知,一直比较的话用while循环 while j >= 0 and li[j] > tmp: #j >= 0 表示 k 后面没有值,同时j不可能小于0 li[j+1] = li[j] #k往前面推一个位置 j = j - 1 #k 后面的 值的索引 li[j+1] = tmp # 插入k前面
快排:
#拿出一个元素,使其归位后,大的在其右边,小的在左边;得到一个相对有序的列表,然后以其为中间数分割线列表, # 重复上一步归位,以此类推,最终得到一个 有序列表 ### O(n) #快排 def partition(li, left, right): tmp = li[left] while left < right: while left < right and li[right] >= tmp: #和右边数比 right = right - 1 li[left] = li[right] while left < right and li[left] <= tmp: #和左边数比 left = left + 1 li[right] = li[left] li[left] = tmp # 归位:通过左右两边确认里li[left] 的下标 return left ## 时间复杂度: O(nlogn) def _quickSort(li, left, right): if left < right: mid = partition(li, left, right) ### O(n) 拿到归位后的数,对左右两边循环归位 _quickSort(li, left, mid - 1) ### O(logn) _quickSort(li, mid + 1, right) @caltime def quickSort(li, left, right): _quickSort(li, left, right)
归并:
### 时间复杂度: O(nlogn) def merge(li, low, mid, right): i = low j = mid + 1 ltmp = [] while i <= mid and j <= right: if li[i] < li[j]: ltmp.append(li[i]) i = i + 1 else: ltmp.append(li[j]) j = j + 1 while i <= mid: ltmp.append(li[i]) i = i + 1 while j <= right: ltmp.append(li[j]) j = j + 1 li[low:right+1] = ltmp def mergeSort(li, low, high): if low < high: mid = (low + high) // 2
mergeSort(li, low, mid) mergeSort(li, mid + 1, high)
merge(li, low, mid, high) #这个一定的放最后