Day5
Python基本算法之排序与查找
排序算法
排序算法是将一串数据按照特定顺序排列的算法
排序算法稳定性
稳定排序算法会让原本顺序为AB的相等值记录排序后还是保持顺序为AB,而不稳定算法则不一定。人工扩充键值可将不稳定特别地实现为稳定,但这样会有额外地空间负担。
冒泡排序
从头到尾将元素与下一个元素比较,不满足想要的大小关系则交换其位置;第一次遍历后最大(或最小)的被移到末尾,如此遍历n-1次(n为元素个数)即可正确排序
冒泡排序实现
def bubble_sort(alist):
n = len(alist)
for j in range(n-1):
count = 0
for i in range(0, n-1-j):
if alist[i] > alist[i+1]:
alist[i], alist[i+1] = alist[i+1], alist[i]
count += 1
if count == 0: //无需排序时直接返回
return
if __name__ == "__main__":
li = [54, 26, 93, 17, 14, 55, 64, 23, 20]
print(li)
bubble_sort(li)
print(li)
选择排序
待排序的元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。
选择排序实现
def select_sort(alist):
n = len(alist)
for j in range(n-1):
min_index = j
for i in range(j+1, n):
if alist[min_index] > alist[i]:
min_index = i
alist[j], alist[min_index] = alist[min_index], alist[j]\
if __name__ == "__main__":
li = [54, 26, 93, 17, 14, 55, 64, 23, 20]
print(li)
select_sort(li)
print(li)
插入排序
对整个序列遍历,思想是使第n个数前的n-1个数都按顺序排列,将第n个数插入前面已排序的序列中
插入排序实现
def insert_sort(alist):
n = len(alist)
for j in range(1, n):
i = j
while i > 0:
if alist[i] < alist[i-1]:
alist[i], alist[i-1] = alist[i-1], alist[i]
i -= 1
else:
break
if __name__ == "__main__":
li = [54, 26, 93, 17, 14, 55, 64, 23, 20]
print(li)
insert_sort(li)
print(li)
希尔排序
希尔排序是插入排序的一种,也称缩小增量排序,是非稳定排序。基本思想是设定一个初始步长,以该步长取元素,取出的元素条再拼为一个矩阵或表的形式
希尔排序实现
def shell_sort(alist):
n = len(alist)
gap = n // 2
while gap > 0:
for j in range(gap, n):
i = j
while i > 0:
if alist[i] < alist[i-gap]:
alist[i], alist[i-gap] = alist[i-gap], alist[i]
i -= gap
else:
break
gap //= 2
if __name__ == "__main__":
li = [54, 26, 93, 17, 14, 55, 64, 23, 20]
print(li)
shell_sort(li)
print(li)
快速排序
快速排序是冒泡排序的一种改进,取一个元素,将所有元素划分为比其小和比其大的两组,最后用递归达到排序目的
快速排序实现
def quick_sort(alist, first, last):
if first >= last:
return
mid_value = alist[first]
low = first
high = last
while low < high:
while low < high and alist[high] >= mid_value:
high -= 1
alist[low] = alist[high]
while low < high and alist[low] < mid_value:
low += 1
alist[high] = alist[low]
alist[low] = mid_value
quick_sort(alist, first, low-1)
quick_sort(alist, low+1, last)
if __name__ == "__main__":
li = [54, 26, 93, 17, 14, 55, 64, 23, 20]
print(li)
quick_sort(li, 0, len(li)-1)
print(li)
归并排序
采用分而治之的思想先将所有元素分为两个两个一组的先比较,再将之后得到的
归并排序实现
def merge_sort(alist):
n = len(alist)
if n <= 1:
return alist
mid = n//2
left_li = merge_sort(alist[:mid])
right_li = merge_sort(alist[mid:])
left_pointer, right_pointer = 0, 0
result = []
while left_pointer < len(left_li) and right_pointer < len(right_li):
if left_li[left_pointer] < right_li[right_pointer]:
result.append(left_li[left_pointer])
left_pointer += 1
else:
result.append(right_li[right_pointer])
right_pointer += 1
result += left_li[left_pointer:]
result += right_li[right_pointer:]
return result
if __name__ == "__main__":
li = [54, 26, 93, 17, 14, 55, 64, 23, 20]
print(li)
sorted = merge_sort(li)
print(sorted)
常见排序算法效率比较
搜索算法
二分法查找
二分法每次都折半查找数据,缺点在于要求表为有序的,且插入删除困难
二分法实现
def binary_search(alist, item): //递归
n = len(alist)
if n > 0:
mid = n//2
if alist[mid] == item:
return True
elif item < alist[mid]:
return binary_search(alist[:mid], item)
else:
return binary_search(alist[mid+1:], item)
return False
def binary_search_2(alist, item): //非递归
n = len(alist)
first = 0
last = n-1
while first <= last:
mid = (first+last)//2
if alist[mid] == item:
return True
elif item < alist[mid]:
last = mid - 1
else:
first = mid + 1
return False
if __name__ == "__main__":
li = [10, 23, 24, 65, 89, 95, 120] //必须一开始就有序
print(li)
print(binary_search(li, 24))
print(binary_search_2(li, 65))