Python Algorithms-basic knowledge of chapter2, algorithmschapter2
I. Progressive recording
Three important marks
Attention, Ω, attention, and attention are used to represent the progressive upper bound, while the Ω method is used to represent the progressive lower bound. The attention method also provides the upper and lower bounds of functions.
Several common instances of progressive running time
Three Important Cases
Best case, worst case, average case
The worst case is usually the most useful case, which can guarantee the optimal algorithm efficiency.
Empirical algorithm Evaluation
Tip1: If possible, don't worry about it.
Tip2: Timing using the timeit Module
import timeittimeit.timeit("x = 2+2") #0.003288868749876883timeit.timeit("x = sum(range(10))") #0.003288868749897271
Tip3: Use profiler to identify bottlenecks
Use cProfiler to obtain the running content and print the timing results of each function in the program. If the python version does not contain cProfiler, use profiler instead.
import cProfilecProfile.run("helloworld()")
Tip4: Draw the result
You can use matplotlib to draw the results, refer to the http://www.cnblogs.com/huangqiancun/p/8379502.html
Tip5: Be careful when making judgments based on timing comparison results
Tip6: Be careful when judging the progressive time through relevant experiments
Ii. Graphs and trees
1. Implementation
Adjacent table
Adjacent set
a, b, c, d, e, f, g, h = range(8)N = [ {b, c, d, e, f}, # a {c, e}, # b {d}, # c {e}, # d {f}, # e {c, g, h}, # f {f, h}, # g {f, g} # h]
b in N[a] # Truelen(N[f]) # 3
Adjacent list
a, b, c, d, e, f, g, h = range(8)N = [ [b,c,d,e,f], #a [c,e], #b [d], #c [e], #d [f], #e [c,g,h], #f [f,h], #g [f,g] #h ]
Weighted neighbor dictionary
a, b, c, d, e, f, g, h = range(8)N = [ {b:2, c:1, d:3, e:9, f:4}, # a {c:4, e:3}, # b {d:8}, # c {e:7}, # d {f:5}, # e {c:2, g:2, h:2}, # f {f:1, h:6}, # g {f:9, g:8} # h]
b in N[a] # Truelen(N[f]) # 3N[a][b] # 2
Dictionary representation of the adjacent Sets
N = { 'a': set('bcdef'), 'b': set('ce'), 'c': set('d'), 'd': set('e'), 'e': set('f'), 'f': set('cgh'), 'g': set('fh'), 'h': set('fg')}
Adjacent matrix
a, b, c, d, e, f, g, h = range(8)N = [[0,1,1,1,1,1,0,0], # a [0,0,1,0,1,0,0,0], # b [0,0,0,1,0,0,0,0], # c [0,0,0,0,1,0,0,0], # d [0,0,0,0,0,1,0,0], # e [0,0,1,0,0,0,1,1], # f [0,0,0,0,0,1,0,1], # g [0,0,0,0,0,1,1,0]] # hN[a][b] # Neighborhood membership -> 1sum(N[f]) # Degree -> 3
Assign a weighted matrix of infinite power values to nonexistent Edges
a, b, c, d, e, f, g, h = range(8)_ = float('inf')W = [[0,2,1,3,9,4,_,_], # a [_,0,4,_,3,_,_,_], # b [_,_,0,8,_,_,_,_], # c [_,_,_,0,7,_,_,_], # d [_,_,_,_,0,5,_,_], # e [_,_,2,_,_,0,2,2], # f [_,_,_,_,_,1,0,6], # g [_,_,_,_,_,9,8,0]] # hW[a][b] < inf # Truesum(1 for w in W[a] if w < inf) - 1 # 5
Note: Remember to subtract 1 from the sum of the degrees, because we do not want to include the diagonal lines.
Dedicated array in Numpy Library
N = [[0]*10 for i in range(10)]
import numpy as npN = np.zeros([10,10])
For more information, see http://www.cnblogs.com/huangqiancun/p/8379241.html
2-tree implementation
T = [["a", "b"], ["c"], ["d", ["e","f"]]]T[0][1] # 'b'T[2][1][0] # 'e'
Binary Tree
class Tree: def __init__(self, left, right): self.left = left self.right = rightt = Tree(Tree("a", "b"), Tree("c", "d"))t.right.left # 'c'
Multi-path search tree (left child, right brother)
class Tree: def __init__(self, kids, next=None): self.kids = self.val = kids self.next = nextreturn Treet = Tree(Tree("a", Tree("b", Tree("c", Tree("d")))))t.kids.next.next.val # 'c'
Bunch Mode
Bunch class
class Bunch(dict): def __init__(self, *args, **kwds): super(Bunch, self).__init__(*args, **kwds) self.__dict__ = self
x = Bunch(name = "Jayne Cobb", position = "Public Relations")x.name #'Jayne Cobb'
T = Buncht = T(left = T(left = "a",right = "b"), right = T(left = "c"))t.left # {'right': 'b', 'left': 'a'}t.left.right #' b'"left" in t.right # True
Iii. Black Box
1 recessive square-level operation
from random import randrangeL = [randrange(10000) for i in range(1000)]42 in L # FalseS = set(L)42 in S #False
It seems meaningless to use set, but the Member query is linear in list, and it is constant in set.
lists = [[1,2], [3,4,5], [6]]sum(lists, []) #[1, 2, 3, 4, 5, 6]res = []for lst in lists: res.extend(lst)# [1, 2, 3, 4, 5, 6]
The sum function is a square-level running time, and the second is a better choice. When the list length is very short, there is no big gap between them, but once it exceeds a certain length, the sum version will be completely defeated.
2. troubles in floating point operations
sum(0.1 for i in range(10)) == 1.0 #False
def almost_equal(x, y, places=7): return round(abs(x-y), places) == 0almost_equal(sum(0.1 for i in range(10)), 1.0) # True
from decimal import *sum(Decimal("0.1") for i in range(10)) == Decimal("1.0") #True