这两天把几个基础排序算法捋了捋,做个记录。
堆排序是不稳定的,其他取决于判断条件有无 =
冒泡
def maopao(nums): #冒泡,时间O(n^2),空间O(1)
def help(start, end):
for i in range(end, start,-1):
if lst[i] < lst[i - 1]:
#print(lst[i - 1], lst[i])
# 交换位置 ( 严格小于才交换位置,稳定的)
lst[i - 1], lst[i] = lst[i], lst[i - 1]
#print(lst[i - 1], lst[i])
for i in range(len(nums) - 1):
help(i, len(nums) - 1)
return nums
选择
def select(nums): #选择排序,时间O(n^2),空间O(1)
for i in range(len(nums)-1):
min_ = i
for j in range(i+1,len(nums)):
if nums[j]<nums[min_]: #稳定的
min_=j
nums[i], nums[min_] = nums[min_],nums[i]
return nums
插入
def insert(nums): #插入排序,时间O(N**2),空间(1)原地修改
#最差的情况,第k轮需要比较k-1次,1+2+..+n-1 时间O(N**2)
size =len(nums)
for i in range(1,size):
j = i#后面无序数组的start
while j>0:
if nums[j]<nums[j-1]: #前面为有序数组,稳定的
nums[j],nums[j-1]= nums[j-1],nums[j]
else:
break
j-=1
return nums
折半插入排序
二分查找法,边界最容易错,最好把 tmp == nums[mid] 单独拿出来吧,不容易乱,
low<=high 和 low= mid+1,high = mid-1 必须匹配的,
如果 high=mid 或者 low = mid 就会陷入死循环
#插入排序+二分查找法,在有序序列中寻找插入位置时,使用二分查找
def binaryInsert(nums):
size = len(nums)
for i in range(1,size):
tmp = nums[i]
low = 0
high = i-1
while low<=high:
mid = low + (high-low)//2 #左中位数
if tmp == nums[mid]:
low = mid+1
break
if tmp>nums[mid]:
low= mid+1
else:
high = mid-1
for j in range(i,low,-1):
nums[j] = nums[j-1]
nums[low] = tmp #最终确定的位置在low
return nums
希尔排序
#希尔排序: 做间隔插入排序, 间隔递减, 最后间隔为1, 不稳定的!
def shellSort(nums):
size= len(nums)
gap = size//2
while gap:
for i in range(size-1,gap-1,-1):
tmp = nums[i]
j = i
while j-gap>=0 and nums[j-gap]>nums[j]:
nums[j] = nums[j-gap]
j-=gap
nums[j] = tmp
gap= gap//2
return nums
堆排序
def heapSort(nums):
def shiftDown(root,end):
child = 2*root+1
while child<=end:
if child+1<=end and nums[child+1]> nums[child]:
child+=1
if nums[child]> nums[root]:
nums[root],nums[child] = nums[child],nums[root]
else:
break
root = child
child = 2 * root+1
size = len(nums)
start = size//2-1
# 构建
for i in range(start,-1,-1):
shiftDown(i, size-1)
#递增 排序
for i in range(size-1,0,-1):
nums[i],nums[0] = nums[0],nums[i]
shiftDown(0,i-1)
return nums
归并
def merge(left_arr,right_arr):
result = []
l,r = 0,0
while l<len(left_arr) and r<len(right_arr):
if left_arr[l]<=right_arr[r]: #这里加上=是稳定的,不加是不稳定的
result.append(left_arr[l])
l+=1
else:
result.append(right_arr[r])
r+=1
if l==len(left_arr): result+=right_arr[r:]
else: result+= left_arr[l:]
return result
def mergeSort(nums): #空间O(N),未必稳定,时间O(nlogn),递推写法
step = 1
size = len(nums)
while step*2 <=size:
for i in range(0,size,2*step):
if i+2*step < size:
nums[i:i+2*step] = merge(nums[i:i+step],nums[i+step:i+2*step])
if i+step<size:
nums[i:]= merge(nums[i:i+step],nums[i+step:])
step *= 2
if step <size:
return merge(nums[:step],nums[step:])
else:
return nums
#递归,递推
def mergeSort2(nums): #空间O(N),未必稳定,时间O(nlogn), 递归写法
if len(nums)<2: #递归边界
return nums
mid = len(nums)//2 #右中位数
left = mergeSort2(nums[:mid])
right = mergeSort2(nums[mid:])
return merge(left,right)
快排
def quickSort(nums): #时间O(nlogn)空间? 不太清楚,递归栈应该会用
#只能自顶向下,分治递归:递归式,停止条件
def partition(left, right):
mid = left + (right - left) // 2
nums[mid], nums[right] = nums[right], nums[mid]
store_index = left
for i in range(left, right):
if nums[i] < nums[right]: #没有=,是稳定的
nums[i], nums[store_index] = nums[store_index], nums[i]
store_index += 1
nums[store_index], nums[right] = nums[right], nums[store_index]
return store_index
if len(nums)<2:
return nums
pivot = partition(0,len(nums)-1)
nums[:pivot]= quickSort(nums[:pivot])
nums[pivot+1:]= quickSort(nums[pivot+1:])
return nums
如有错误,还请指正~
ps: 今天晚上看了切片,可是可劲用切片了…