排序算法
python自带排序
a = [7,3,4,1,6]
b = sorted(a)
print(b)
a.sort(reverse=True)
print(a)
[1, 3, 4, 6, 7]
[7, 6, 4, 3, 1]
d = {"2":5,"1":1,"2":3,"5":15,"4":10}
sorted(d.items(),key=lambda x:x[0])
[('1', 1), ('2', 3), ('4', 10), ('5', 15)]
冒泡排序
从头遍历所有样本,进行两两比较,如果是从小到大排序,每次比较大的样本在前都要进行交换,最终将最大值放到最后;每次遍历将当前最大值放到最后,对剩下未排序样本进行重复的遍历比较操作,最终得到排序好的序列。
def bubbling_sort(a):
for i in range(len(a)-1,0,-1):
for j in range(1,i+1):
# 交换两个相邻的样本
if a[j] < a[j-1]:
a[j-1],a[j] = a[j],a[j-1]
if __name__ == "__main__":
a = [7,3,4,1,6]
bubbling_sort(a)
print(a)
[1, 3, 4, 6, 7]
选择排序
如果是从小到大排序,每次选出最小的样本放到序列的最前面,然后在剩下的样本中选第二小的样本,放到前面,不断重复这个过程。
def select_sort(a):
for i in range(len(a)-1):
min_value = float("inf")
index = -1
for j in range(i,len(a)):
if a[j]< min_value:
index = j
min_value = a[j]
a[i],a[index] = a[index],a[i]
if __name__ == "__main__":
a = [7,3,4,1,6]
select_sort(a)
print(a)
[1, 3, 4, 6, 7]
插入排序
从头开始遍历,对于遍历的每个元素i,其前i-1个元素为有序,将其第i个元素插入到前i-1个元素中正确的位置。
def insert_sort(a):
n = len(a)
for i in range(1,n):
for j in range(i,0,-1):
if a[j]<a[j-1]:
a[j-1],a[j] = a[j],a[j-1]
if __name__ == "__main__":
a = [7,3,4,1,6]
insert_sort(a)
print(a)
[1, 3, 4, 6, 7]
希尔排序
在插入排序的基础上做的一个升级。通过增量大小对序列分组,对每组分别进行插入排序,然后不断缩小增量。
def shell_sort(a):
n = len(a)
gap = n // 2
while gap >= 1:
for i in range(gap,n):
j = i
while j-gap>=0:
if a[j]<a[j-gap]:
a[j-gap],a[j] = a[j],a[j-gap]
j = j-gap
else:
break # 之前的已经排好序,不要再往前比较
gap = gap // 2
if __name__ == "__main__":
a = [7,3,4,1,6]
shell_sort(a)
print(a)
[1, 3, 4, 6, 7]
快速排序
每次将一个基数放置到正确的位置,用两个指针left和right,分别从左边和右边进行遍历,将右边比基数小的值和左边比基数大的值进行交换,重复该过程,直到两个指针相遇,left指针位置即为基数应所处的位置。
def find_base(a,left,right):
base = a[left]
while left < right:
while left < right and a[right] > base:
right -= 1
if left < right:
a[left] = a[right]
while left < right and a[left] < base:
left += 1
if left < right:
a[right] = a[left]
a[left] = base
return left
def quick_sort(a,left,right):
if left<right:
base = find_base(a,left,right)
quick_sort(a,left,base-1)
quick_sort(a,base+1,right)
if __name__ == "__main__":
a = [7,3,4,1,6]
quick_sort(a,0,len(a)-1)
print(a)
[1, 3, 4, 6, 7]
归并排序
不断的将两个有序序列进行合并的过程。
def mergesort(a):
if len(a) == 1:
return a
mid = len(a)//2
return merge(mergesort(a[:mid]),mergesort(a[mid:]))
def merge(left,right):
result = []
while len(left) and len(right):
if left[0] <= right[0]:
result.append(left.pop(0))
else:
result.append(right.pop(0))
while len(left):
result.append(left.pop(0))
while len(right):
result.append(right.pop(0))
return result
if __name__ == "__main__":
a = [7,3,4,1,6]
b = mergesort(a)
print(b)
[1, 3, 4, 6, 7]
堆排序
首先建立最大堆或者最小堆,然后将堆的最小值或者最大值放置数组最后,重新调整剩下的元素为最大堆或者最小堆,重复上述过程。
def heapfiy(a,i):
left = 2*i
right = 2*i+1
largest = i
if left < n and a[largest] < a[left]:
largest = left
if right < n and a[largest] < a[right]:
largest = right
if largest != i:
a[i],a[largest] = a[largest],a[i]
heapfiy(a,largest)
def build_maxheap(a):
for i in range(n//2,-1,-1):
heapfiy(a,i)
def heapsort(a):
global n
n = len(a)
# 建立最大堆,为了升序排序
build_maxheap(a)
for i in range(n-1,0,-1):
a[0],a[i] = a[i],a[0]
n = n - 1
heapfiy(a,0)
if __name__ == "__main__":
a = [7,3,4,1,6]
heapsort(a)
print(a)
[1, 3, 4, 6, 7]
应用
第k小(大)的元素
- 第k小的元素即索引为k-1位置的元素,n为序列长度
- 第k大的元素即索引为n-k位置的元素,n为序列长度
# 时间复杂度:O(n)
def find_base(a,left,right):
base = a[left]
while left < right:
while left < right and a[right] > base:
right -= 1
if left < right:
a[left] = a[right]
while left < right and a[left] < base:
left += 1
if left < right:
a[right] = a[left]
a[left] = base
return left
def quicksort(a,left,right,k):
if left < right:
base = find_base(a,left,right)
if k == base:
return a[base]
elif k<base:
return quicksort(a,left,base-1,k)
else:
return quicksort(a,base+1,right,k)
def findKthElement(a,k):
n = len(a)
k = k-1
return quicksort(a,0,n-1,k)
if __name__ == "__main__":
a = [7,3,4,1,6]
print(findKthElement(a,2))
3