- 二分查找
#coding=utf-8
def binary_search(list, item):
low = 0
high = len(list) - 1
while low <= high: # While you haven't narrowed it down to one element ...
mid = (low + high) // 2 # ... check the middle element
guess = list[mid]
if guess == item:
return mid
if guess > item:
high = mid - 1
else:
low = mid + 1
return None # Item dosen't exist
my_list = [1, 3, 5, 7, 9]
print (binary_search(my_list, 3)) # 'None' means nil in Python. We use to indicate that the item wasn't found.
- 选择排序
#coding=utf-8
# Finds the smallest value in an array
def findSmallest(arr):
smallest = arr[0] # Stores the smallest value
smallest_index = 0 # Stores the index of the smallest value
for i in range(1, len(arr)):
if arr[i] < smallest:
smallest = arr[i]
smallest_index = i
return smallest_index
def selectionSort(arr):
newArr = []
for i in range(len(arr)):
# Finds the smallest element in the array and adds it to the new array
smallest = findSmallest(arr)
newArr.append(arr.pop(smallest))
return newArr
print(selectionSort([5, 3, 6, 2, 10]))
- 递归
3.1 基线条件 和 递归条件
#coding=utf-8
# 基线条件和递归条件
def countdown(i):
if i <= 0: # <---- base case 基线条件
return
else:
countdown(i-1) # <---- recursive case 递归条件
countdown(5)
3.2 调用栈
这是本节的一个重要概念:调用另一个函数时,当前函数暂停并处于未完成状态
# 调用栈
def greet2(name):
print("how are you, " + name + "?")
def bye():
print("ok bye!")
def greet(name):
print("hello, " + name + "!")
greet2(name)
print("getting ready to say bye...")
bye()
greet("adit")
3.3 递归调用栈-斐波那契
def fact(x):
if x == 1:
return 1
else:
return x * fact(x-1)
print(fact(5))
- 快速排序
快速排序闭选择排序快很多。
使用了分而治之(D&C)思想。
别忘了,你要使用D&C,因此需要将数组分解,直到满足基线条件
def quickSort(array):
if len(array) < 2:
return array # 基线条件:为空或只包含一个元素的数组是“有序”的
else:
pivot = array[0] # 递归条件
less = [i for i in array[1:] if i <= pivot ] # 由所有小于基准值的元素组成的子数组
greater = [i for i in array[1:] if i > pivot ] # 由所有大于基准值的元素组成的子数组
return quickSort(less) + [pivot] + quickSort(greater)
print(quickSort([10, 5, 2, 3]))
-
散列表
散列表由键和值组成
对于同样的输入,散列表必须返回同样的输出,这一点很重要
使用散列表来检查是否重复,速度非常快 -
广度优先搜索
#coding=utf-8
from collections import deque
# 判断一个人是不是芒果销售商
def person_is_seller(name):
return name[-1] == 'm' # 检查人的姓名是否以m结尾
graph = {}
graph["you"] = ["alice", "bob", "claire"]
graph["bob"] = ["anuj", "peggy"]
graph["alice"] = ["peggy"]
graph["claire"] = ["thom", "jonny"]
graph["anuj"] = []
graph["peggy"] = []
graph["thom"] = []
graph["jonny"] = []
def search(name):
search_queue = deque() # 创建一个队列
search_queue += graph[name] # 将你的邻居都加入到这个搜索队列中
searched = [] # 这个数组用于记录检查过的人
while search_queue: # 只要队列不为空
person = search_queue.popleft() # 就取出其中的第一个人
if not person in searched: # 仅当这个人没检查过时才检查
if person_is_seller(person): # # 检查这个人是否是芒果销售商
print(person + " is a mango seller!") # 是芒果销售商
return True
else:
search_queue += graph[person] # 不是芒果销售商。将这个人的朋友都加入搜索队列
searched.append(person) # 将这个人标记为检查过
return False # 如果到达了这里,就说明队列中没人是芒果销售商
print(search("you"))
7.狄克斯特拉算法
狄克斯特拉算法找出的是 总权重最小的路径
带权重的图称为加权图(weighted graph),不带权重的图称为非加权图(unweighted graph)
要计算非加权图中的最短路径,可使用广度优先搜索。要计算加权图中的最短路径,可使用狄克斯特拉算法
在无向图中,每条边都是一个环。狄克斯特拉算法只适用于有向无环图(directed acyclicgraph,DAG)
包含四个步骤:
(1)找出“最便宜”的节点。即可在最短时间内到达的节点。
(2)更新该节点的邻居开销。
(3)重复这个过程,直到对图中的每个节点都这样做了。
(4)计算最终路径。
#coding=utf-8
# 需要三个散列表和一个数组。
# 散列表:1)图;2)costs:存储每个节点的开销;3)parents:存储父节点
# 数组:processed 记录处理过的数组
# the graph
graph = {}
graph["start"] = {}
graph["start"]["a"] = 6
graph["start"]["b"] = 2
graph["a"] = {}
graph["a"]["fin"] = 1
graph["b"] = {}
graph["b"]["a"] = 3
graph["b"]["fin"] = 5
# the costs table
infinity = float("inf")
costs = {}
costs["a"] = 6
costs["b"] = 2
costs["fin"] = infinity
# the parents table
parents = {}
parents["a"] = "start"
parents["b"] = "start"
parents["fin"] = None
processed = []
# 两个重要的点:1)节点 lowest_cost_node;2)节点成本 lowest_cost
def find_lowest_cost_node(costs):
lowest_cost = float("inf")
lowest_cost_node = None
for node in costs: # 遍历所有节点
cost = costs[node]
if cost < lowest_cost and node not in processed: #如果当前节点开销更低且未处理过
lowest_cost = costs
lowest_cost_node = node
return lowest_cost_node
# 三个重要的点 :1)node(开销最小的节点);2)该节点的邻居 neighbours.keys();3)成本。cost+neighbours[n]。经该节点,到邻居的成本
node = find_lowest_cost_node(costs) # 在未处理节点中找出开销最小的节点
while node is not None: # 这个while循环在所有节点都被处理过后结束
cost = costs[node]
neighbors = graph[node]
for n in neighbors.keys(): # 遍历当前节点的所有邻居
new_cost = cost + neighbors[n]
if costs[n] > new_cost: # 如果当前节点前往该邻居更近
costs[n] = new_cost # 就更新该邻居的开销
parents[n] = node # 同时将该邻居的父节点设置为当前节点
processed.append(node) # 将当前节点标记为处理过
node = find_lowest_cost_node(costs) # 找出接下来要处理的节点,并循环
总结
广度优先搜索用于在非加权图中查找最短路径。
狄克斯特拉算法用于在加权图中查找最短路径。
仅当权重为正时狄克斯特拉算法才管用。
如果图中包含负权边,请使用贝尔曼福德算法。