排序搜索算法
简单算法的主要操作:
-
比较两个数据项.
-
交换两个数据项, 或者复制其中一项.
注意:每种算法具体实现的细节有所不同
冒泡排序
思路:
-
第一次找出最大的数据放在最后, 我们需要两个两个数据项进行比较, 那么这个应该是一个循环操作.
-
第二次将次最大的数据找到放在倒数第二个位置, 也是两个比较, 只是不要和最后一个比较(少了一次), 但是前面的两个两个比较也是一个循环操作.
-
第三次...第四次..
实现:
def bubble_sort(list):
for j in range(len(list) - 1):
for i in range(len(list) - 1 - j):
# print(list[i],i)
if list[i] > list[i + 1]: # 从小到大
list[i], list[i + 1] = list[i + 1], list[i]
return list
list1=[5,1,2,4,3,8,9]
re=bubble_sort(list1)
print(re)
插入排序
思路分析:
-
插入排序应该从下标值1开始(因为0位置默认可以被认为是有序的)
-
从1位置开始取出元素, 并且判断该元素的大小和0位置进行比较, 如果1位置元素小于0位置元素, 那么交换, 否则不交换.
-
上面步骤执行完成后, 0 - 1位置已经排序好.
-
取出2位置的元素, 和1位置进行比较:
-
如果2位置元素大于1位置元素, 说明2位置不需要任何动作. 0 - 1 - 2已经排序好.
-
如果2位置元素小于1位置元素, 那么将1移动到2的位置, 并且2继续和0进行比较.
-
如果2位置元素大于0位置的元素, 那么将2位置放置在1的位置, 排序完成. 0 - 1 - 2搞定.
-
如果2位置元素小于1位置的元素, 那么将0位置的元素移动到1位置, 并且将2位置的元素放在0位置, 0 - 1 - 2搞定.
-
-
按照上面的步骤, 依次找到最后一个元素, 整个数组排序完成.
实现:
def insert(list):
j=0
for i in range(1,len(list)-1):
j=i
temp=list[j]
while j>0 and list[j-1]>temp: # 在前面排好序的数据里面,谁比temp大,谁就往后移动
list[j]=list[j-1]
j-=1
list[j]=temp
return list
list2=[5,3,4,2,6,1,9]
re=insert(list2)
print(re)
归并排序
基本思想与过程:先递归的分解数列,再合并数列(分治思想的典型应用)
(1)将一个数组拆成A、B两个小组,两个小组继续拆,直到每个小组只有一个元素为止。
(2)按照拆分过程逐步合并小组,由于各小组初始只有一个元素,可以看做小组内部是有序的,合并小组可以被看做是合并两个有序数组的过程。
(3)对左右两个小数列重复第二步,直至各区间只有1个数。
实现:
def merge(left,right): #left小数据 right大数据
i=j=0
list = []
while (i<len(left) and j<len(right)):
if left[i]<right[j]:
list.append(left[i])
i+=1
else:
list.append(right[j])
j+=1
list=list+left[i:]
list=list+right[j:]
return list
def merge_sort(list):
if len(list)>1:
index=len(list)//2
# middle=list[index]
left=list[:index]
right=list[index:]
return merge(merge_sort(left),merge_sort(right))
else:
return list
list1=[2,3,5,6,1,2,5,9]
re=(merge_sort(list1))
print(re)
选择排序
思路:
-
选定第一个索引位置,然后和后面元素依次比较
-
如果后面的队员, 小于第一个索引位置的队员, 则交换位置
-
经过一轮的比较后, 可以确定第一个位置是最小的
-
然后使用同样的方法把剩下的元素逐个比较即可
-
可以看出选择排序,第一轮会选出最小值,第二轮会选出第二小的值,直到最后
实现:
def select_sort(list):
# 第一次拿第一个数据和其他7个数据挨个比较,比他小的直接交换下标
for i in range(len(list)):
index = i
for j in range(i+1, len(list)):
if list[index] < list[j]:
index = j
list[index], list[i] = list[i], list[index] # 第一次循环完成后交换数据,得出一个最小的
return list
list1=[5,1,4,3,2,6,8,9]
re=select_sort(list1)
print(re)
快速排序
快速排序的思想:
-
快速排序最重要的思想是分而治之.
-
比如我们有这样一堆数字需要排序: [13,81,92,43,65,31,57,26,75,0]
-
第一步: 从其中选出了65. (其实可以是选出任意的数字, 我们以65举个栗子)
-
第二步: 我们通过算法: 将所有小于65的数字放在65的左边, 将所有大于65的数字放在65的右边.
-
第三步: 递归的处理左边的数据.(比如你选择31来处理左侧), 递归的处理右边的数据.(比如选择75来处理右侧, 当然选择81可能更合适)
-
最终: 排序完成
-
实现:
def quick_sort(list):
if len(list)<=1:
return list
index=len(list)//2
el=list[index]
left=[x for x in list if x<el]
middle=[x for x in list if x==el]
right=[x for x in list if x>el]
return quick_sort(left)+middle+quick_sort(right)
list1=[5,1,8,7,2,3]
re=quick_sort(list1)
print(re)
顺序搜索
从数据结构的第一个元素开始逐个检查,直到找到目标值或遍历完整个数据集。适用于数组和链表等基本数据结构
def binary_search(arr, target):
for i in range(len(arr)):
if arr[i] == target:
return i
return -1 # 没有找到目标值时返回 -1
sorted_array = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
search_target = 11
result_index = binary_search(sorted_array, search_target)
if result_index != -1:
print(f"找到目标值 {search_target},其索引为 {result_index}")
else:
print(f"未能在数组中找到目标值 {search_target}")
二分搜索
针对有序数组进行搜索,通过不断将搜索范围减半来提高查找效率。每次都将搜索区间划分为两部分,并基于中间元素与目标值的比较决定是在左半边还是右半边继续搜索。
思路:
初始化:给定一个已排序的列表或数组 arr 和一个要查找的目标值 target。
义查找区间:设置两个指针,分别代表待查找区间的起始(left)和结束(right)位置。
循环条件:当左边界不大于右边界时,继续循环。
计算中间位置:取区间的中间位置 mid,一般计算方式为 (left + right) // 2。
比较中间元素:检查 arr[mid] 是否等于目标值 target。 若相等,则找到了目标值,返回 mid 作为目标值的索引。 若 arr[mid] 小于 target,说明目标值可能在 mid 右侧,因此更新左边界为 mid + 1。 若 arr[mid] 大于 target,说明目标值可能在 mid 左侧,因此更新右边界为 mid - 1。
循环结束:如果跳出循环,意味着没有找到目标值,返回 -1 或者一个特殊值表示未找到。
def binary_search(arr,targeet):
arr.sort(key=lambda x:x)
print(arr)
left=0
right=len(arr)
while left<right:
index = (left + right) // 2 #6 10
if arr[index]==targeet:
return True
elif arr[index]<targeet:
left=index+1#7
else:
right=index-1
return False
list=[22,12,3,123,12,3,234,32,5,34,50,4,6]
re=binary_search(list,50)
re=binary_search([100],100)
print(re)
大O表示法
大O表示法(Big O notation)是一种用于描述算法性能与输入规模之间的关系的标准数学符号,它提供了算法在最坏情况下的时间复杂度和空间复杂度的上界估计。
例:假设列表有n个元素,简单查找需要查找每个元素,因此需要执行n次操作。使用大O表示法记做:O(n),如果用二分法查找,则需要执行 log 2n 次操作。使用大O表示法记做:O(log 2n)
常见的排序算法及其对应的复杂度: