时间空间复杂度
1直接选择排序
def select_sort(lst):
if lst == []: return []
for i in range(len(lst)-1): #i不断增加序号
smallest = i
for j in range(i, len(lst)):
if lst[j] < lst[smallest]:#选择最小的,放到和第一个交换
smallest = j
lst[i], lst[smallest] = lst[smallest], lst[i]
return lst
2堆排序
升序:小根堆
1从最后一个非叶子结点开始(第一个非叶子结点 arr.length/2-1),判断其和叶子节点大小,最大的放到根节点,小的放到叶子节点--还要考虑此叶子节点为根的子树是否仍满足条件
2步骤二 将堆顶元素与末尾元素进行交换,使末尾元素最大。然后继续调整堆,再将堆顶元素与末尾元素交换,得到第二大元素。如此反复进行交换、重建、交换。
#重构大根堆+交换
def adjustHeap(lst, begin, end):
if lst == []: return []
temp=begin
i, j = begin, begin * 2 + 1 #根节点要最大,左节点开始向下找
while j < end:
if j + 1 < end and lst[j + 1] > lst[j]:
j += 1 #j等于左节点开始下面更大的叶子节点
elif temp > lst[j]: break #比下面最大的都大,结束循环
else:
lst[i] = lst[j] #交换,i拿到更大的
lst[j] = temp
i, j = j, 2 * j + 1 #改变后继续建
def heap_sort(lst):
if lst == []: return []
for i in range((len(lst)// 2) - 1, -1, -1):#从最后一个非叶子结点开始len/2-1
adjustHeap(lst, i, len(lst))
for i in range(end - 1, 0, -1):#结构混乱重新调整
lst[i],lst[0] = lst[0],lst[i]
adjustHeap(lst, 0, i)
return lst
#或者递归
def adjust_heap(lists, i, size):
# 调整堆
lchild = 2 * i + 1
rchild = 2 * i + 2
maxi = i
if lchild < size and lists[maxi] < lists[lchild]:
maxi = lchild
if rchild < size and lists[maxi] < lists[rchild]:
maxi = rchild
if maxi != i:
# 如果做了堆调整,maxi的值等于左/右节点的,对调操作
lists[maxi], lists[i] = lists[i], lists[maxi]
adjust_heap(lists, maxi, size)
3插入排序
无序变成一个有序,每次拿出一个数字插入到新的有序中
第i趟排序时,有序数组中的数字就有i个,就需要进行i次比较,因此循环i次
def Insert_sort(lst):#升序
if lst == []: return []
for i in range(1, len(lst)):
temp = lst[i] #要插入的数
j = i #插入位置,向左找序列位置并移动
while j > 0 and temp < lst[j - 1]: #要插入的数更小
lst[j] = lst[j - 1] #不停向右移动
j -= 1
lst[j] = temp #插入
return lst
4冒泡排序
n轮每次把最大的移到最后,
最好情况:加入标记swaptrue,如果循环没有进行交换,可以理解为数组已经排好序,一轮后就可以退出排序;
def bubble_sort(lst):
if lst == []: return []
swaptrue=False
for i in range(len(lst)):
for j in range(1, len(lst) - i):
if lst[j - 1] > lst[j]:
lst[j - 1], lst[j] = lst[j], lst[j - 1]
swaptrue=True
if didSwap == false:return
return lst
5快速排序(分治
把基准数大的都放在基准数的右边,把比基准数小的放在基准数的左边
图解:快速排序---(面试碰到过好几次)_nrsc的博客-CSDN博客
时间复杂度:快速排序 及其时间复杂度和空间复杂度_寒夕若梦的博客-CSDN博客
时间复杂度公式为:T[n] = 2T[n/2] +n;T[n/2]为平分后的子数组的时间复杂度,f[n] 为平分这个数组时所花的时间遍历一遍;
最优的情况就是每一次取到的元素都刚好平分整个数组:T[n] = n + nlogn
最差的情况就是每一次取到的元素就是数组中最小/最大的,这种情况其实就是冒泡排序了(每一次都排好一个元素的顺序)
快速排序,分治法策略來把一個序列分為较小和较大的2个子序列,然后递归地排序两个子序列。
def quick_sort(lst):
if not lst: return []
pivot = lst[0]
left = quick_sort([x for x in lst[1: ] if x < pivot])
right = quick_sort([x for x in lst[1: ] if x >= pivot])
return left + [pivot] + right
##2
def quick_sort(li, start, end):
# start=end ,证明要处理的数据只有一个> ,证明右边没有数据
if start >= end:
return
# 定义两个游标,分别指向0和末尾位置
left = start
right = end
mid = li[left] # 把0位置的数据,认为是中间值
while left < right:
while left < right and li[right] >= mid:
right -= 1
li[left] = li[right]
while left < right and li[left] < mid:
left += 1
li[right] = li[left]
li[left] = mid # while结束后,把mid放到中间位置,left=right
quick_sort(li, start, left-1)# 递归处理左边的数据
quick_sort(li, left+1, end) # 递归处理右边的数据
6归并排序
将两个顺序序列合并成一个顺序序列的方法:2个合并--4个合并--。。。各自有序再合并有序
def merge_sort(lst):
if len(lst) <= 1: return lst
mid = len(lst) // 2
left = merge_sort(lst[: mid])
right = merge_sort(lst[mid:])
return merge(left, right)
def merge(left, right):
l, r, res = 0, 0, [] #申请空间,大小为两个已经排序序列之和,该空间用来存放合并后的序列
while l < len(left) and r < len(right):
if left[l] <= right[r]:
res.append(left[l])
l += 1
else:
res.append(right[r])
r += 1
res += left[l:]
res += right[r:]
return res
7基数排序
基数排序-----python(简单易懂)_瑶子ove的博客-CSDN博客
首先根据个位数的数值,在走访数值时将它们分配至编号0到9的桶子中,将数值重新串接,再根据十位数。持续进行以上的动作直至最高位数为止。
def RadixSort(a):
i = 0 #初始为个位排序
n = 1 #最小的位数置为1(包含0)
max_num = max(a) #得到带排序数组中最大数
while max_num > 10**n: #得到最大数是几位数
n += 1
while i < n:
bucket = {} #用字典构建桶
for x in range(10):
bucket.setdefault(x, []) #将每个桶置空
for x in a: #对每一位进行排序
radix =int((x / (10**i)) % 10) #得到每位的基数
bucket[radix].append(x) #将对应的数组元素加入到相应位基数的桶中
j = 0
for k in range(10):
if len(bucket[k]) != 0: #若桶不为空
for y in bucket[k]: #将该桶中每个元素
a[j] = y #放回到数组中
j += 1
i += 1