一、查找算法:
根据指定的值,在待查找数据集合中确认是否存在某一数据的值与该指定值相同。
A. 顺序查找:
从待查找数据的第一个元素开始,逐个将每个元素与要查找的数据值进行对比:如果比较到两者值相同,则查找成功;如果一直到最后都未找到,则查找失败。
特点: 不要求数据本身有序
劣势: 当数据集合较大时,查找效率低
代码示例:
# 待查找数据集合 value
# 查找的值 key
def linear(value, key):
# 从头到尾遍历待查找数据
for i in range(len(value)):
if value[i] == key:
# 成功,返回下标值
return i
else:
# 失败,返回-1
return -1
values = [9, 1,11, 3, 2, 6, 12, 5, 4, 7, 8, 10, 13]
# 查找 7
result = linear(values, 7)
if result == -1:
print('查找失败')
else:
print('查找成功,对于下标:',result)
B. 二分查找:
找出*有序数据*中的中间元素,由中间元素值将原数据分为两个子表,然后根据指定查找值与 中间元素的大小关系进行比对:若相对,则查找成功;若查找值小于中间元素,则在左侧子表中继续查找;若查找值大于中间元素,则在右侧子表中继续查找。如此递归查找下去,直到查找成功或查找完整个数据集合为止。(折半查找)
优势: 每次查找之后,搜索范围减半
特点: 要求数据本身有序
代码示例:
**# 递归实现**
# 待查找数据集合 - value
# 要查找的数值 - key
# 限定查找范围的左侧元素下标值 - left
# 限定查找范围的右侧元素下标值 - right
def binary(value, key, left, right):
if left > right:
# 查找结束 - 未找到
return -1
# 获取中间元素的下标值
middle = (left + right) // 2
# 对比中间元素值与key值
if value[middle] == key:
# 成功找到返回下标
return middle
elif value[middle] > key:
# 继续在左侧查找
return binary(value, key, left, middle-1)
else:
# 继续在右侧查找
return binary(value, key, middle+1, right)
values = [3, 5, 7, 12, 25, 36, 45, 56, 67, 77, 97, 101]
# 查找数据 25
result = binary(values, 25, 0, len(values)-1)
if result == -1:
print('查找失败')
else:
print('查找成功,对应下标:', result)
**# 循环实现**
# 待查找数据集合 - value
# 要查找的数值 - key
def binary(values, key):
# 获取查找范围对应的左侧/右侧的下标
left = 0
right = len(values)-1
# 在查找范围内循环查找
while left <= right:
# 获取中间元素下标
middle = (left + right) // 2
# 中间元素值与key值对比
if values[middle] == key:
# 成功找到返回下标
return middle
elif values[middle] > key:
# 继续在左侧查找
right = middle -1
else:
# 继续在右侧查找
left = middle + 1
# 查找完成 - 未找到
return -1
values = [3, 5, 7, 12, 25, 36, 45, 56, 67, 77, 97, 101]
# 查找数据 25
result = binary(values, 25)
if result == -1:
print('查找失败')
else:
print('查找成功,对应下标:', result)
二、排序算法:(从小到大)
A. 冒泡排序:
重复走访要排序的数据集合,依次比较每两个相邻的元素:如果其次序错误则 交换两数据;重复进行走访对比直到没有相邻数据需要交换为止。
特点: 对数据本身有序性敏感
代码示例:
def bubble(value):
# 外层循环: 对应走访数据的过程
for i in range(len(value) - 1):
# 内层循环: 对应每次走访数据时相邻数据对比次数
for j in range(len(value) - 1 - i):
# 对比相邻数据的值,从小到大排序
if value[j] > value[j + 1]:
# 次序错误则交换
value[j], value[j + 1] = value[j + 1], value[j]
# 测试走访数据的次数
print('loop count:', i + 1)
values = [100, 2, 9, 19, 23, 27, 34, 39, 45, 52, 67, 73, 86, 98]
print('before:', values)
bubble(values)
print('after:', values)
B. 插入排序:
将数据插入到已经有序的数据中,从而得到新的有序数据。默认首元素自然有序,取出下一个元素,对已经排序的数据从后向前扫描:
若有序数据大于取出数据,则该有序数据后移;
若有序数据小于等于取出数据,则在该有序数据后插入取出数据
如果所有的有序数据均大于取出数据,则在有序数据头部插入取出数据。
取出下一个未排序数据,重复上步骤,直到处理完所有数据为止
特点:不交换只移动,优于冒泡
代码示例:
def insert(value):
# 外层循环: 对应无序数据遍历次数
for i in range(1, len(value)):
# 取出数据
temp = value[i]
# 取出数据要插入的位置下标值
index = i
# 内层循环: 对应从后向前遍历有序数据
for j in range(i - 1, -1, -1):
# 对比取出数据与有序数据
if value[j] > temp:
# 当有序数据大于取出数据时
# 有序数据后移一位
value[j + 1] = value[j]
# 更新取出数据的插入位置
index = j # -> 0
else:
# 当有序数据小于等于取出数据时
# 在有序数据后面一位插入取出数据
index = j + 1
break
# 在指定位置插入数据
value[index] = temp
values = [23, 45, 2, 67, 34, 9, 86, 39, 52, 73, 19, 98, 27]
print('before:', values)
insert(values)
print('after:', values)
C. 快速排序:
首先任意选取一个数据(通常我们选用第一个数)作为关键数据,然后将所有比它小的数据放在其前面,将所有比它大的数据放到其后面,这个过程称为一趟快速排序。通过一趟排序将数据分为两个部分,然后递归对该两个部分重复进行快速排序,已达到所有数据有序。
特点: 如果每次都能均匀分组则排序速度是最快的
代码示例:
def quick(value):
# 当仅有一个数据时无需排序
if len(value) < 2:
return value
# 设置关键数据
key = value[0]
# 找出所有比key小的数据
smaller = [x for x in value if x < key]
# 找出所有与key相等的数据
equal = [x for x in value if x == key]
# 找出所有比key大的数据
bigger = [x for x in value if x > key]
# 从小到大排序
return quick(smaller) + equal + quick(bigger)
values = [23, 45, 2, 67, 34, 9, 86, 39, 52, 73, 19, 98, 27]
print('before:', values)
values = quick(values)
print('after:', values)