查找算法:根据指定的值,在待查找数据集合中确认是否存在某一数据的值与该指定值相同。
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)
print( (0 + 11) // 2 )
print( (0 + 5) // 2 )
特点: 不要求数据本身有序
劣势: 当数据集合较大时,查找效率低
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, 9, 10, 12, 25, 34, 45, 56, 67, 76, 84, 99]
# 查找数据 25
result = binary(values, 25, 0, len(values)-1)
if result == -1:
print('查找失败')
else:
print('查找成功,对应下标:', result)
优势: 每次查找之后,搜索范围减半
特点: 要求数据本身有序
排序算法:(从小到大)
A. 冒泡排序:重复走访要排序的数据集合,依次比较每两个相邻的元素:如果其次序错误则交换两数据;重复进行走访对比直到没有相邻数据需要交换为止。
特点: 对数据本身有序性敏感
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
# 冒泡排序
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 = [23, 45, 2, 67, 34, 9, 86, 39, 52, 73, 19, 98, 27]
values = [100, 2, 9, 19, 23, 27, 34, 39, 45, 52, 67, 73, 86, 98]
print('before:', values)
bubble(values)
print('after:', values)
更优的冒泡排序
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
# 冒泡排序
def bubble(value):
# 外层循环: 对应走访数据的过程
for i in range(len(value) - 1):
# 设置数据交换标志
flag = False
# 内层循环: 对应每次走访数据时相邻数据对比次数
for j in range(len(value) - 1 - i):
# 对比相邻数据的值,从小到大排序
if value[j] > value[j + 1]:
# 次序错误则交换
value[j], value[j + 1] = value[j + 1], value[j]
# 更新标志的值
flag = True
# 判断是否发生相邻数据交换
if flag is False:
# 若未发生数据交换,则证明后续数据均有序
# 无需继续下次走访,退出循环
break
# 测试走访数据的次数
print('loop count:', i + 1)
# values = [23, 45, 2, 67, 34, 9, 86, 39, 52, 73, 19, 98, 27]
values = [100, 2, 9, 19, 23, 27, 34, 39, 45, 52, 67, 73, 86, 98]
print('before:', values)
bubble(values)
print('after:', values)
B. 插入排序:将数据插入到已经有序的数据中,从而得到新的有序数据。默认首元素自然有序,取出下一个元素,对已经排序的数据从后向前扫描:
若有序数据大于取出数据,则该有序数据后移;
若有序数据小于等于取出数据,则在该有序数据后插入取出数据
如果所有的有序数据均大于取出数据,则在有序数据头部插入取出数据。
取出下一个未排序数据,重复上步骤,直到处理完所有数据为止
特点:不交换只移动,优于冒泡
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
# 插入排序
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. 快速排序:首先任意选取一个数据(通常我们选用第一个数)作为关键数据,然后将所有比它小的数据放在其前面,将所有比它大的数据放到其后面,这个过程称为一趟快速排序。通过一趟排序将数据分为两个部分,然后递归对该两个部分重复进行快速排序,已达到所有数据有序。
特点: 如果每次都能均匀分组则排序速度是最快的
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
# 快速排序
# 递归实现
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)
想要看更多的课程请微信关注SkrEric的编程课堂