一,归并算法
思想:先将原序列经过多次对半,分解为单个元素,每次对半分均分为左边序列与右边序列。然后再将一个个单个元素,合并起来。也采用两两合并的方式,合并过程中由左指针与右指针控制,判断两个指针代表值的大小,并将小的放在result列表中,然后移动,直到左列表或右列表有一个到头,然后将另一个列表剩余数据插入result列表中。最优与最坏时间复杂度均为nlogn,因为该算法不像快速排序,不管在最好最坏的情况,都可以分为logn次.但是快速排序的优点是不需要产生新的列表,且平均情况接近于nlogn
需要用到递归的思想,代码如下:
def Merge_sort(alist):
n=len(alist)
if n<=1: #应在n//2前面
return alist
last=n//2
left_li=Merge_sort(alist[:last]) #调用自己,有分解出左列表和右列表
right_li=Merge_sort(alist[last:])#同上,将右序列再分
left_point=0
right_point=0
result=[]
while left_point<len(left_li) and right_point<len(right_li):#执行到这里说明左右序列均已分好,不能是alist,底层alist有两个元素
if left_li[left_point]<=right_li[right_point]:
result.append(left_li[left_point])
left_point+=1
else:
result.append(right_li[right_point])
right_point+=1
result+=left_li[left_point:]#不能用append
result+=right_li[right_point:]
return result
if __name__=='__main__':
li=[213,432,435,543,765,123,434,768,345]
print(li)
eli=Merge_sort(li)
print(eli)
结果如下:
[213, 432, 435, 543, 765, 123, 434, 768, 345]
[123, 213, 345, 432, 434, 435, 543, 765, 768]
二,二分查找
思想:在有序序列(经过排序)的顺序表(需要用到下标)中查找某个数据,通过起始下标与终止下标平均找到中间值,判断查找值与中间值大小,然后在左或右列表中继续操作,直到总列表中只有一个元素为止。最坏时间复杂度为logn
'''有递归的二分查找'''
def Binary_search(alist,item):
n=len(alist)
if n>0:
mid=n//2
if alist[mid]==item:
return True
elif alist[mid]<item:#顺序弄反
return Binary_search(alist[mid+1:],item)
else:
return Binary_search(alist[:mid],item)
return False
'''无递归的二分查找'''
def Binary_search2(alist,item):
n=len(alist)
first=0
last=n-1
while first<=last:
mid=(first+last)//2
if alist[mid]==item:#注意这里如何实现缩短列表范围
return True
elif alist[mid]<item:
first=mid+1
else:
last=mid-1
return False
if __name__ == "__main__":
li = [17, 20, 26, 31, 44, 54, 55, 77, 93]
print(Binary_search(li, 55))
print(Binary_search(li, 100))
print(Binary_search2(li, 55))
print(Binary_search2(li, 100))
结果如下:
True
False
True
False