算法
算法简介
算法是一组完成任务的指令。当数据量比较大的时候,算法的优劣对程序的性能好坏极为重要
衡量算法性能 - 大 O 表示法
-
算法的速度指的并非时间,而是操作数的增速
-
谈论算法的速度时,我们说的是随着输入的增加,其运行时间将以什么样的速度增加
-
算法的运行时间用大 O 表示法表示
-
大 O 表示法指出了最糟情况下的运行时间
-
O(logn) 比 O(n) 快,当需要搜索的元素越多时,前者比后者快得越多
数组与链表
数组:元素在内存中都是相连的
链表:元素可存储在内存中任何地方,并不一定是相连的
数组擅长读取,链表擅长插入与删除(数组支持随机访问,而链表只能顺序访问)
| 数组 | 链表 | |
|---|---|---|
| 读取 | O(1) | O(n) |
| 插入 | O(n) | O(1) |
| 删除 | O(n) | O(1) |
递归
定义:函数自己调用自己
基线条件和递归条件
递归条件:函数调用自己
基线条件:函数不再调用自己,从而避免形成无限循环
栈
元素 后进先出(LIFO) 的一种数据结构
调用栈
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("maggie"),内存分配情况:
接下来,打印 hello, maggie! 再调用 greet2("maggie")
打印 hello are you, maggie? 然后从函数返回。栈顶内存块被弹出。
调用另一个函数时,当前函数暂停并处于未完成状态。接下来,打印 getting ready to say bye...,调用函数 bye()
打印 ok bye! 从函数返回
用于存储多个变量的栈就是调用栈
递归调用栈
递归函数使用调用栈,例如:
def fact(x):
if x == 1:
return 1
else:
return x * fact(x-1)
几种重要算法
二分查找
只适用于有序元素列表
目的: 查找某个数是否存在于数组中
算法: 前提条件:a 为数组,first 和 last 分别指向数组的头尾,mid 指向数组的中间项,value 为要查找的数
如果 first > last, 返回 None(没有找到元素),否则循环执行以下程序: mid = (first + last) // 2
- 如果 a[mid] > value ,查找区间变为[first, mid-1]
- 如果 a[mid] < value ,查找区间变为[mid+1, last]
- 如果 a[mid] = value ,返回 mid
代码:
def BinarySearch(a, value):
first = 0
last = len(a) - 1
while first <= last:
mid = (first + last) // 2
guess = a[mid]
if guess < value:
first = mid + 1
elif guess > value:
last = mid - 1
else:
return mid
return None
二分查找的时间复杂度:O(logn)
选择排序
每次都找出数组中最小的元素,并添加到新数组中
代码(找出最小值):
def findSmallest(arr):
smallest = arr[0]
smallest_index = 0
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)):
smallest = findSmallest(arr)
newArr.append(arr.pop(smallest))
return newArr
选择排序时间复杂度: