├── week6 ├── .ipynb_checkpoints │ ├── BFS&DFS-checkpoint.ipynb │ ├── practice-checkpoint.ipynb │ └── algorithm-checkpoint.ipynb ├── BFS&DFS.ipynb ├── practice.ipynb └── algorithm.ipynb ├── week3 ├── __pycache__ │ └── queue.cpython-37.pyc ├── deque.py ├── queue_.py ├── queue_practice.py ├── practice1.py └── List.py ├── week4 ├── converString.py ├── moveTower.py ├── tree.py ├── x.py ├── sierprinski.py └── practice.py ├── .vscode ├── settings.json └── launch.json ├── week5 ├── dbMakeChange.py ├── coin_change.py └── practice.py ├── week2 ├── practice1.py ├── practice2.py ├── stack.py ├── practice3.py └── practice4.py ├── readme.md └── week1 └── exercise.py /week6/.ipynb_checkpoints/BFS&DFS-checkpoint.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [], 3 | "metadata": {}, 4 | "nbformat": 4, 5 | "nbformat_minor": 2 6 | } 7 | -------------------------------------------------------------------------------- /week3/__pycache__/queue.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxiaolong321/Python-Datastructure-and-algorithm/HEAD/week3/__pycache__/queue.cpython-37.pyc -------------------------------------------------------------------------------- /week4/converString.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -* 2 | 3 | 4 | def toStr(n, base): # 递归实现进制转换 5 | convertString = "0123456789ABCDEF" 6 | if n < base: 7 | return convertString[n] 8 | else: 9 | return toStr(n//base, base)+convertString[n % base] 10 | 11 | for i in range(1,50): 12 | print(toStr(i, 12)) 13 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "python.pythonPath": "D:\\Miniconda3\\envs\\datastructure\\python.exe", 3 | "sqltools.connections": [ 4 | { 5 | "database": "qunar", 6 | "dialect": "MySQL", 7 | "name": "mysql", 8 | "password": "380324", 9 | "port": 3306, 10 | "server": "localhost", 11 | "username": "root" 12 | } 13 | ] 14 | } -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // 使用 IntelliSense 了解相关属性。 3 | // 悬停以查看现有属性的描述。 4 | // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Python: 当前文件", 9 | "type": "python", 10 | "request": "launch", 11 | "program": "${file}", 12 | "console": "integratedTerminal" 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /week4/moveTower.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -* 2 | 3 | def moveTower(height, fromPole, withPole, toPole): 4 | if height >= 1: 5 | moveTower(height - 1, fromPole, toPole, withPole) 6 | moveDisk(height, fromPole, toPole) 7 | moveTower(height - 1, withPole, fromPole, toPole) 8 | 9 | def moveDisk(disk, fromPole, toPole): 10 | print(f"Moving disk[{disk}] from {fromPole} to {toPole}") 11 | 12 | moveTower(3, "#1", "#2", "#3") 13 | -------------------------------------------------------------------------------- /week4/tree.py: -------------------------------------------------------------------------------- 1 | #-*- coding:utf-8 -* 2 | import turtle 3 | 4 | def tree(t, n): 5 | if n > 5: 6 | t.forward(n) 7 | t.left(20) 8 | tree(t, n-5) 9 | t.right(40) 10 | tree(t, n-5) 11 | t.left(20) 12 | t.backward(n) 13 | 14 | if __name__ == "__main__": 15 | t = turtle.Turtle() 16 | t.penup() 17 | t.right(90) 18 | t.fd(100) 19 | t.right(180) 20 | t.pendown() 21 | tree(t, 50) 22 | turtle.done() 23 | -------------------------------------------------------------------------------- /week5/dbMakeChange.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -* 2 | """ 3 | -个经典案例是兑换最少个数的硬币问题 4 | 假设你为一家自动售货机厂家编程序,自动售货 5 | 机要每次找给顾客最少数量硬币; 6 | 假设某次顾客投进$1纸币,买了37的东西,要 7 | 找63,那么最少数量就是: 2个quarter(25) 8 | 1个dime(c10)和3个penny(e1) ,一共6个 9 | """ 10 | 11 | 12 | def dpMakeChange(coinValueList, change, minCoins): # 动态规划法解决问题 13 | for cents in range(1, change + 1): 14 | coinCount = cents 15 | for j in [c for c in coinValueList if c <= cents]: 16 | if minCoins[cents - j] + 1 < coinCount: 17 | coinCount = minCoins[cents - j] + 1 18 | minCoins[cents] = coinCount 19 | return minCoins[change] 20 | 21 | 22 | print(dpMakeChange([1, 5, 10, 21, 25], 63, [0]*64)) 23 | -------------------------------------------------------------------------------- /week2/practice1.py: -------------------------------------------------------------------------------- 1 | from stack import Stack1 2 | 3 | 4 | def parChecker(symbolString): 5 | s = Stack1() 6 | balanced = True 7 | index = 0 8 | # 如果括号匹配,左右括号数目相等,压入的括号都会弹出来,不会出现残留问题或者balance为False的问题 9 | while index < len(symbolString) and balanced: 10 | symbol = symbolString[index] 11 | if symbol == "(": 12 | s.push(symbol) 13 | else: 14 | if s.isEmpty(): 15 | balanced = False 16 | else: 17 | s.pop() 18 | 19 | index += 1 20 | 21 | if balanced and s.isEmpty(): # 防止两种情况,左括号多余有括号或者有括号多余左括号 22 | return True 23 | else: 24 | return False 25 | 26 | 27 | if __name__ == "__main__": 28 | print(parChecker("([()[]{]}<>)")) 29 | print(parChecker("(((((()))))")) 30 | -------------------------------------------------------------------------------- /week2/practice2.py: -------------------------------------------------------------------------------- 1 | from stack import Stack1 2 | 3 | """ 4 | 十进制与二进制的转换 5 | """ 6 | 7 | 8 | def divideBy2(decNumber): 9 | remstack = Stack1() 10 | 11 | while decNumber > 0: 12 | rem = decNumber % 2 # 整数取余 13 | remstack.push(rem) 14 | decNumber = decNumber//2 15 | 16 | binString = "" 17 | while not remstack.isEmpty(): 18 | binString += str(remstack.pop()) 19 | 20 | return binString 21 | 22 | 23 | def BaseConverter(decNumber, base): 24 | remstack = Stack1() 25 | 26 | while decNumber > 0: 27 | rem = decNumber % base # 整数取余 28 | remstack.push(rem) 29 | decNumber = decNumber//base 30 | 31 | binString = "" 32 | while not remstack.isEmpty(): 33 | binString += str(remstack.pop()) 34 | 35 | return binString 36 | 37 | 38 | if __name__ == "__main__": 39 | print(divideBy2(42)) 40 | print(BaseConverter(42, 8)) 41 | -------------------------------------------------------------------------------- /week3/deque.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -* 2 | 3 | # 双端队列实现 4 | class Deque: 5 | def __init__(self): 6 | self.items = [] 7 | 8 | def addFront(self, item): # 队首入队 9 | self.items.insert(0, item) 10 | 11 | def addRear(self, item): # 队尾入队 12 | self.items.append(item) 13 | 14 | def removeFrond(self): # 移除队首数据 15 | return self.items.pop(0) 16 | 17 | def removeRear(self): # 移除队尾数据 18 | return self.items.pop() 19 | 20 | def isEmpty(self): 21 | return self.items == [] 22 | 23 | def size(self): 24 | return len(self.items) 25 | 26 | 27 | # 回文词判断 28 | def palchecker(aString): 29 | chardeque = Deque() 30 | 31 | for ch in aString: 32 | chardeque.addFront(ch) 33 | 34 | stillEqual = True 35 | while chardeque.size() > 1 and stillEqual: 36 | first = chardeque.removeFrond() 37 | last = chardeque.removeRear() 38 | if first != last: 39 | stillEqual = False 40 | 41 | return stillEqual 42 | 43 | if __name__ == "__main__": 44 | print(palchecker("lsdkjfskf")) 45 | print(palchecker("radar")) 46 | -------------------------------------------------------------------------------- /week3/queue_.py: -------------------------------------------------------------------------------- 1 | # -*- coding : utf-8 -* 2 | 3 | 4 | class Queue1: # 队列实现方法1,尾部添加元素 5 | def __init__(self): 6 | self.items = [] 7 | 8 | def enqueue(self, item): 9 | self.items.append(item) 10 | 11 | def dequeue(self): 12 | return self.items.pop(0) 13 | 14 | def isEmpty(self): 15 | return self.items == [] 16 | 17 | def size(self): 18 | return len(self.items) 19 | 20 | 21 | class Queue2: # 队列实现方法2,头部添加元素 22 | def __init__(self): 23 | self.items = [] 24 | 25 | def enqueue(self, item): 26 | self.items.insert(0, item) 27 | 28 | def dequeue(self): 29 | return self.items.pop() 30 | 31 | def isEmpty(self): 32 | return self.items == [] 33 | 34 | def size(self): 35 | return len(self.items) 36 | 37 | 38 | def hotPotato(namelist, num): # 热土豆问题 39 | simqueque = Queue2() 40 | for name in namelist: 41 | simqueque.enqueue(name) 42 | 43 | while simqueque.size() > 1: 44 | for i in range(num): 45 | simqueque.enqueue(simqueque.dequeue()) # 将不符合条件的土豆重新加入到队列 46 | simqueque.dequeue() 47 | 48 | return simqueque.dequeue() 49 | 50 | 51 | if __name__ == "__main__": 52 | print(hotPotato(["Bill", "IDavid", "Susan", "Jane", "Kent", "Brad", "Dnaial"], 7)) 53 | -------------------------------------------------------------------------------- /week4/x.py: -------------------------------------------------------------------------------- 1 | import turtle 2 | 3 | def drawTriangle(points,color,myTurtle): 4 | myTurtle.fillcolor(color) 5 | myTurtle.up() 6 | myTurtle.goto(points[0][0],points[0][1]) 7 | myTurtle.down() 8 | myTurtle.begin_fill() 9 | myTurtle.goto(points[1][0],points[1][1]) 10 | myTurtle.goto(points[2][0],points[2][1]) 11 | myTurtle.goto(points[0][0],points[0][1]) 12 | myTurtle.end_fill() 13 | 14 | def getMid(p1,p2): 15 | return ( (p1[0]+p2[0]) / 2, (p1[1] + p2[1]) / 2) 16 | 17 | def sierpinski(points,degree,myTurtle): 18 | colormap = ['blue','red','green','white','yellow', 19 | 'violet','orange'] 20 | drawTriangle(points,colormap[degree],myTurtle) 21 | if degree > 0: 22 | sierpinski([points[0], 23 | getMid(points[0], points[1]), 24 | getMid(points[0], points[2])], 25 | degree-1, myTurtle) 26 | sierpinski([points[1], 27 | getMid(points[0], points[1]), 28 | getMid(points[1], points[2])], 29 | degree-1, myTurtle) 30 | sierpinski([points[2], 31 | getMid(points[2], points[1]), 32 | getMid(points[0], points[2])], 33 | degree-1, myTurtle) 34 | 35 | def main(): 36 | myTurtle = turtle.Turtle() 37 | myWin = turtle.Screen() 38 | myPoints = [[-100,-50],[0,100],[100,-50]] 39 | sierpinski(myPoints,3,myTurtle) 40 | myWin.exitonclick() 41 | 42 | main() -------------------------------------------------------------------------------- /week5/coin_change.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -* 2 | import time 3 | """ 4 | -个经典案例是兑换最少个数的硬币问题 5 | 假设你为一家自动售货机厂家编程序,自动售货 6 | 机要每次找给顾客最少数量硬币; 7 | 假设某次顾客投进$1纸币,买了37的东西,要 8 | 找63,那么最少数量就是: 2个quarter(25) 9 | 1个dime(c10)和3个penny(e1) ,一共6个 10 | """ 11 | 12 | # change为兑换金额,coinValueList为兑换金额 13 | def greedyChange(coinValueList, change): # 贪心策略解决硬币问题 14 | minCoins = change 15 | if change in coinValueList: 16 | return 1 17 | else: 18 | for i in [c for c in coinValueList if c < change]: 19 | numCoins = 1 + greedyChange(coinValueList, change-i) 20 | if numCoins < minCoins: 21 | minCoins = numCoins 22 | return minCoins 23 | 24 | # print(time.process_time()) 25 | # print(greedyChange([1, 5, 10, 25], 63)) 26 | # print(time.process_time()) 27 | 28 | 29 | def NewGreedyChange(coinValueList, change, knownResults): # 贪心策略解决硬币问题,消除重复计算 30 | minCoins = change 31 | if change in coinValueList: # 最小规模,直接返回 32 | knownResults[change] = 1 33 | return 1 34 | elif knownResults[change] > 0: 35 | return knownResults[change] # 查表成功,直接用最优解,而不需要再次递归 36 | else: 37 | for i in [c for c in coinValueList if c <= change]: 38 | # 调用自身,减少规模,每次减去一种硬币面值挑选最小数量 39 | numCoins = 1 + NewGreedyChange(coinValueList, change-i, knownResults) 40 | if numCoins < minCoins: 41 | minCoins = numCoins 42 | knownResults[change] = minCoins 43 | return minCoins 44 | 45 | # print(NewGreedyChange([1,5,10,25],63,[0]*64)) 46 | print(list(range(5))) -------------------------------------------------------------------------------- /week4/sierprinski.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -* 2 | 3 | import turtle 4 | 5 | 6 | def drawTriangle(t, points, color): # 绘制三角形 7 | t.fillcolor(color) 8 | t.penup() 9 | t.goto(points['top']) 10 | t.pendown() 11 | t.begin_fill() 12 | t.goto(points['left']) 13 | t.goto(points['right']) 14 | t.goto(points['top']) 15 | t.end_fill() 16 | 17 | 18 | def getMid(p1, p2): # 获取边长中点 19 | return ((p1[0]+p2[0])/2, (p1[1]+p2[1])/2) 20 | 21 | 22 | def sierpinski(t, degree, points): # 绘制谢尔宾斯基三角 23 | colormap = ['blue', 'red', 'green', 'white', 'yellow', 'orange'] # 颜色地图 24 | drawTriangle(t, points, colormap[degree]) 25 | if degree > 0: # 绘制递归函数,degree 设置深度 26 | sierpinski(t, degree-1, 27 | { 28 | 'left': points['left'], 29 | 'top': getMid(points['left'], points['top']), 30 | 'right': getMid(points['left'], points['right']) 31 | }) 32 | sierpinski(t, degree-1, 33 | { 34 | 'left': getMid(points['left'], points['top']), 35 | 'top': points['top'], 36 | 'right': getMid(points['top'], points['right']) 37 | }) 38 | sierpinski(t, degree-1, 39 | { 40 | 'left': getMid(points['left'], points['right']), 41 | 'top': getMid(points['top'], points['right']), 42 | 'right': points['right'] 43 | }) 44 | 45 | 46 | if __name__ == "__main__": 47 | t = turtle.Turtle() 48 | points = {'left': (-200, -100), 49 | 'top': (0, 200), 50 | 'right': (200, -100)} 51 | sierpinski(t, 5, points) 52 | turtle.done() 53 | -------------------------------------------------------------------------------- /week2/stack.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -* 2 | import time 3 | 4 | 5 | class Stack1: # Python实现ADT stack,栈尾实现 6 | 7 | def __init__(self): 8 | self.items = [] 9 | 10 | def isEmpty(self): 11 | return self.items == [] 12 | 13 | def push(self, item): 14 | self.items.append(item) 15 | 16 | def pop(self): 17 | return self.items.pop() 18 | 19 | def peek(self): 20 | return self.items[len(self.items)-1] 21 | 22 | def size(self): 23 | return len(self.items) 24 | 25 | 26 | # 实现方法2,栈顶实现 27 | class Stack2: 28 | def __init__(self): 29 | self.items = [] 30 | 31 | def isEmpty(self): 32 | return self.items == [] 33 | 34 | def push(self, item): 35 | self.items.insert(0, item) 36 | 37 | def pop(self): 38 | return self.items.pop(0) 39 | 40 | def peek(self): 41 | return self.items[0] 42 | 43 | def size(self): 44 | return len(self.items) 45 | 46 | 47 | if __name__ == "__main__": 48 | count_time1 = 0 49 | count_time2 = 0 50 | for i in range(10000): 51 | start_time = time.perf_counter() 52 | s = Stack1() 53 | s. push('dog') 54 | s.push(True) 55 | s.push(8.4) 56 | s.pop() 57 | finish_time = time.perf_counter() 58 | count_time1 += finish_time - start_time 59 | 60 | start_time = time.perf_counter() 61 | s = Stack2() 62 | s. push('dog') 63 | s.push(True) 64 | s.push(8.4) 65 | s.pop() 66 | finish_time = time.perf_counter() 67 | count_time2 += finish_time - start_time 68 | 69 | print("方法一运行时间 %s" % count_time1) 70 | print("方法二运行时间 %s" % count_time2) 71 | 72 | """ 73 | 程序运行时间 74 | 方法一运行时间 0.01718990000000087 75 | 方法二运行时间 0.020802599999999394 76 | """ -------------------------------------------------------------------------------- /week3/queue_practice.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -* 2 | """ 3 | 模拟算法: 打印任务 4 | 一个具体的实例配置如下: 5 | 一个实验室,在任意的一个小时内,大约有10名学生在场, 6 | 这一小时中,每人会发起2次左右的打印,每次1~20页。 7 | 打印机的性能是:以草稿模式打印的话,每分钟10页, 8 | 以正常模式打印的话,打印质量好,但速度下降 9 | 为每分钟5页。 10 | """ 11 | import random 12 | from queue import Queue 13 | 14 | 15 | class Printer(): 16 | def __init__(self, ppm): 17 | self.pagerate = ppm # 打印速度 18 | self.currentTask = None 19 | self.timeRemaining = 0 20 | 21 | def tick(self): 22 | if self.currentTask != None: 23 | self.timeRemaining -= 1 24 | if self.timeRemaining <= 0: 25 | self.currentTask = None 26 | 27 | def busy(self): 28 | if self.currentTask != None: 29 | return True 30 | else: 31 | return False 32 | 33 | def startNext(self, newtask): 34 | self.currentTask = newtask 35 | self.timeRemaining = newtask.getPages()*60/self.pagerate 36 | 37 | 38 | class Task: 39 | def __init__(self, time): 40 | self.timestamp = time 41 | self.pages = random.randrange(1, 21) 42 | 43 | def getStamp(self): 44 | return self.timestamp 45 | 46 | def getPages(self): 47 | return self.pages 48 | 49 | def waitTime(self, currenttime): 50 | return currenttime - self.timestamp 51 | 52 | 53 | def newPrintTask(): 54 | num = random.randrange(1, 181) # 1/180的概率完成任務 55 | if num == 180: 56 | return True 57 | else: 58 | return False 59 | 60 | 61 | def simulation(numSeconds, pagesPerMinute): 62 | labprinter = Printer(pagesPerMinute) 63 | printQueue = Queue() 64 | waitingtimes = [] 65 | 66 | for currentSecond in range(numSeconds): 67 | if newPrintTask(): 68 | task = Task(currentSecond) 69 | printQueue.put(task) 70 | 71 | if (not labprinter.busy()) and (not printQueue.empty()): 72 | nexttask = printQueue.get() 73 | waitingtimes.append(nexttask.waitTime(currentSecond)) 74 | labprinter.startNext(nexttask) 75 | 76 | labprinter.tick() 77 | 78 | avarageWait = sum(waitingtimes)/len(waitingtimes) 79 | print("Average Wait %6.2fsecs %3d tasks remaining." % (avarageWait, printQueue.qsize())) 80 | 81 | if __name__ == "__main__": 82 | for i in range(10): 83 | simulation(3600, 10) 84 | -------------------------------------------------------------------------------- /week2/practice3.py: -------------------------------------------------------------------------------- 1 | from stack import Stack1 2 | 3 | 4 | """ 5 | 中缀表达式转换为后缀表达式 6 | 如: 7 | (a*b)+(c*d) -> ab*cd*+ 8 | """ 9 | 10 | 11 | def postfixEval(postfixExpr): 12 | prec = {} 13 | prec["*"] = 3 14 | prec["/"] = 3 15 | prec["+"] = 2 16 | prec["-"] = 2 17 | prec["("] = 1 18 | opStack = Stack1() 19 | postfixList = [] 20 | tokenList = list(postfixExpr) 21 | for token in tokenList: 22 | if token in "QWERTYUIOPASDFGHJKLZXCVBNM" or token in "1234567890": 23 | postfixList.append(token) 24 | elif token == "(": 25 | opStack.push(token) 26 | elif token == ")": 27 | TopToken = opStack.pop() 28 | while TopToken != '(': 29 | postfixList.append(TopToken) 30 | TopToken = opStack.pop() 31 | else: 32 | while (not opStack.isEmpty()) and\ 33 | (prec[opStack.peek()] >= prec[token]): 34 | postfixList.append(opStack.pop()) 35 | opStack.push(token) 36 | while not opStack.isEmpty(): 37 | postfixList.append(opStack.pop()) 38 | 39 | return " ".join(postfixList) 40 | 41 | 42 | """ 43 | 中缀表达式转换为前缀表达式 44 | 如: 45 | (a*b)+(c*d) -> +*ab*cd 46 | """ 47 | 48 | 49 | def postfix(postfixExpr): 50 | postfixExpr = postfixExpr.upper() 51 | 52 | prec = {} 53 | prec["*"] = 3 54 | prec["/"] = 3 55 | prec["+"] = 2 56 | prec["-"] = 2 57 | prec["("] = 1 58 | 59 | opStack = Stack1() 60 | postfixList = [] 61 | for token in list(postfixExpr): 62 | if token in "QWERTYUIOPASDFGHJKLZXCVBNM" or token in "1234567890": 63 | postfixList.append(token) 64 | elif token == '(': 65 | opStack.push(token) 66 | elif token == ')': 67 | topTaken = opStack.pop() 68 | while topTaken != '(': 69 | postfixList.insert(-2, topTaken) 70 | topTaken = opStack.pop() 71 | else: 72 | while (not opStack.isEmpty()) and\ 73 | (prec[opStack.peek()] > prec[token]): 74 | postfixList.insert(-2, opStack.pop()) 75 | opStack.push(token) 76 | while not opStack.isEmpty(): 77 | postfixList.insert(0, opStack.pop()) 78 | 79 | return " ".join(postfixList) 80 | 81 | 82 | if __name__ == "__main__": 83 | print(postfixEval("A+B*C+D*E+F")) 84 | print(postfixEval("(A+B)*C")) 85 | print(postfix("A+B*C+D*E+F")) 86 | print(postfix("(a*b)+(c*d)")) 87 | 88 | """ 89 | A B C * + D E * + F + 90 | A B + C * 91 | + + + A * B C * D E F 92 | + * A B * C D 93 | """ 94 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # 数据结构与算法Python版(陈斌)北京大学 2 | 3 | [课程地址](https://www.icourse163.org/learn/PKU-1206307812) 4 | 5 | ## 课程内容 6 | 7 | ### 01概述(1周) 8 | 9 | > 介绍计算理论和计算复杂性 10 | 11 | - 1.引子 12 | - 2.关于计算的概念和定义:问题求解的计算之道 13 | - 3.图灵机计算模型 14 | - 4.可计算性和计算复杂度; 15 | - 5.什么是抽象 16 | - 6.什么是编程实现 17 | - 7.为什么研究数据结构与抽象数据类型 18 | - 8.为什么研究算法 19 | 20 | ### 02算法分析(1周) 21 | 22 | > 介绍算法分析,大O表示法,以及用实例来演示同一个问题的不同解决方案的算法分析。 23 | 24 | - 1.什么是算法分析? 25 | - 2.大O表示法 26 | - 3.案例分析:“变位词”判断问题 27 | - 4.Python数据结构的性能:列表List和字典Dictionary 28 | 29 | ### 03基本结构(2周) 30 | 31 | > 介绍栈、队列、双端队列和列表等线性结构。 32 | 33 | - 1.什么是线性结构? 34 | - 2.栈Stack抽象数据类型及Python实现 35 | - 3.栈的应用:简单括号匹配 36 | - 4.栈的应用:十进制转换为二进制 37 | - 5.栈的应用:中缀、前缀和后缀表达式 38 | - 6.队列Queue抽象数据类型及Python实现 39 | - 7.队列的应用:热土豆 40 | - 8.队列的应用:打印任务 41 | - 9.双端队列Deque抽象数据类型及Python实现 42 | - 10.双端队列应用:回文词判定 43 | - 11.列表List抽象数据类型及Python实现 44 | - 12.无序表实现及链表 45 | - 13.有序表抽象数据类型及Python实现 46 | 47 | ### 04 递归(3周) 48 | 49 | > 介绍递归和动态规划算法,以及分治策略解决问题。 50 | 51 | - 1.什么是递归 52 | - 2.实例分析:列表求和的递归算法 53 | - 3.递归“三定律” 54 | - 4.递归的应用:任意进制转换 55 | - 5.实现递归:调用栈 56 | - 6.递归的可视化 57 | - 7.递归的应用:塞宾斯基三角形绘制 58 | - 8.复杂递归问题 59 | - 9.递归的应用:汉诺塔 60 | - 10.递归的应用:探索迷宫 61 | - 11.动态规划Dynamic Programming 62 | 63 | ### 05排序与查找(2周) 64 | 65 | > 介绍经典的排序和查找算法 66 | 67 | - 1.什么是查找? 68 | - 2.顺序查找算法及分析 69 | - 3.二分查找算法及分析 70 | - 4.散列:散列函数、碰撞解决和映射数据类型 71 | - 5.什么是排序? 72 | - 6.冒泡排序算法及分析; 73 | - 7.选择排序算法及分析; 74 | - 8.插入排序算法及分析; 75 | - 9.谢尔排序算法及分析; 76 | - 10.归并排序算法及分析; 77 | - 11.快速排序算法及分析。 78 | 79 | ### 06树及算法(3周) 80 | 81 | > 介绍树结构和树结构的处理算法,以及应用 82 | 83 | - 1.树的基本概念及相关术语 84 | - 2.树的列表实现; 85 | - 3.树的链表实现; 86 | - 4.树的应用:表达式解析 87 | - 5.树的遍历 88 | - 6.二叉堆实现的优先队列 89 | - 7.二叉堆的实现 90 | - 8.二叉查找树及操作 91 | - 9.二叉查找树实现及算法分析 92 | - 10.平衡的二叉查找树 93 | - 11.AVL树的性能 94 | - 12.AVL树的实现 95 | 96 | ### 07图及算法(3周) 97 | 98 | > 介绍图结构和图的应用。 99 | 100 | - 1.图的基本概念及相关术语 101 | - 2.图抽象数据类型 102 | - 3.邻接矩阵和邻接表 103 | - 4.图的实现 104 | - 5.Word Ladder词梯问题 105 | - 6.构建词梯问题的图数据结构 106 | - 7.实现广度优先搜索BFS 107 | - 8.BFS算法分析 108 | - 9.骑士周游问题 109 | - 10.构建骑士周游问题的图数据结构 110 | - 11.骑士周游问题算法实现 111 | - 12.骑士周游问题算法分析 112 | - 13.通用的深度优先搜索DFS 113 | - 14.DFS算法分析 114 | - 15.拓扑排序 115 | - 16.强连通分支 116 | - 17.最短路径问题Dijkstra算法及算法分析 117 | - 18.Prim最小生成树算法 118 | 119 | ## 参考资料 120 | 121 | [北京大学地空学院数据结构与算法B课程网站](https://gis4g.pku.edu.cn/course/pythonds/) 122 | [数据结构与算法Python-中文版-内部教材](https://gis4g.pku.edu.cn/download/sessdsa-textbook/) 123 | [在线英文版教材](https://runestone.academy/runestone/books/published/pythonds/index.html) 124 | [Python3官方中文版文档](https://docs.python.org/zh-cn/3/) 125 | [Python3烹饪书](https://python3-cookbook.readthedocs.io/zh_CN/latest/index.html) 126 | [在线Python代码规范](https://python-guide.gitbooks.io/python-style-guide/content) -------------------------------------------------------------------------------- /week4/practice.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -* 2 | 3 | """ 4 | 题目内容: 5 | 给定一个M进制的数,请将其转换为N进制并输出 6 | 输入格式: 7 | 两行,第一行为空格分隔的两个数字,分别为10进制表示的M与N;其中M, N均满足2 ≤ M、N ≤ 36 8 | 第二行为待转换的数字,其中每位超过9的部分从10至36分别用大写字母A-Z表示;输入数据保证其中最大位数对应数字不超过M 9 | 输出格式: 10 | 一行字符串,表示转换后的N进制数 11 | 输入样例: 12 | 8 16 13 | ‭ 473‬ 14 | 输出样例: 15 | ‭13B‬ 16 | """ 17 | 18 | # 题目没看懂,尴了个尬 19 | # def baseConvert(n, base): 20 | # convertString = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" 21 | # if n < base: 22 | # return convertString[n] 23 | # else: 24 | # return baseConvert(n//base, base) + convertString[n % base] 25 | """ 26 | 题目内容: 27 | 如课上所说,汉诺塔问题源于印度一个古老传说。对于原始的汉诺塔游戏, 28 | 可供玩家操作的空间一共只有三根柱子,导致按原传说的要求,需要超过 29 | 1.8*10 ^ 19步才能解开。 30 | 透过新增柱子可以大幅度地减少需要的步数。此处要求在给出指定的盘数, 31 | 柱子数量为4(即限制为4根柱子)且不改变原有传说的其他规则的限制下 32 | ,找出完成迁移的最小步骤数。 33 | 输入格式: 34 | 一个非负整数M,M代表盘数,M <= 1000。 35 | 输出格式: 36 | 一个非负整数,表示完成迁移的最小步骤数。 37 | 输入样例: 38 | 3 39 | 输出样例: 40 | 5 41 | """ 42 | # count = 0 43 | 44 | 45 | def moveTower(m, fromPole, withPole1, withPole2, toPole): 46 | if m == 1: 47 | global count 48 | count += 1 49 | else: 50 | moveTower(m//2, fromPole, withPole2, toPole, withPole1) 51 | moveTower3(m-m//2, fromPole, withPole1, withPole2, toPole) 52 | moveTower(m//2, withPole1, withPole2, toPole, fromPole) 53 | 54 | 55 | def moveTower3(m, fromPole, withPole1, withPole2, toPole): 56 | if m == 1: 57 | global count 58 | count += 1 59 | else: 60 | moveTower3(m-1, fromPole, withPole1, toPole, withPole2) 61 | count += 1 62 | moveTower3(m-1, withPole2, fromPole, withPole1, toPole) 63 | 64 | # moveTower(eval(input()), "#1", "#2", "#3", "#4") 65 | # print(count) 66 | 67 | 68 | """ 69 | 题目内容: 70 | 谢尔宾斯基地毯是形如上图的正方形分形图案,每个地毯可分为等大小的9份,其中中央挖空,其余均由更小的地毯组成。 71 | 现给定地毯大小(行数)与组成地毯的字符元素,请打印相应的地毯图形。 72 | 注:空腔以半角空格表示;当给定字符元素长度不为1时空格数须与字符长度对应 73 | 输入格式: 74 | 输入为两行,分别为地毯大小正整数N与组成元素字符串c 75 | 输入数据保证N为3的正整数幂 76 | 输出格式: 77 | 由N行长度为N*len(c)的字符串构成的谢尔宾斯基地毯 78 | 例如 79 | [][][][][][][][][] 80 | [] [][] [][] [] 81 | [][][][][][][][][] 82 | [][][] [][][] 83 | [] [] [] [] 84 | [][][] [][][] 85 | [][][][][][][][][] 86 | [] [][] [][] [] 87 | [][][][][][][][][] 88 | 输入样例: 89 | 9 90 | [] 91 | """ 92 | 93 | 94 | def mark(x, y, C): 95 | if y % 3 == 1 and x % 3 == 1: 96 | print(" "*len(C), end="") 97 | else: 98 | print(C, end="") 99 | 100 | 101 | def carpet(N, C): 102 | for i in range(N): 103 | for j in range(N): 104 | mark(i, j, C) 105 | print() 106 | 107 | 108 | N = 27 109 | C = "[]" 110 | carpet(N, C) 111 | -------------------------------------------------------------------------------- /week1/exercise.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -* 2 | import time 3 | 4 | """ 5 | 问题描述 6 | 所谓“变位词”是指两个词之间存在组成字母的重新排列关系 7 | 如: heart 和earth, python和typhon 8 | 为了简单起见,假设参与判断的两个词仅由小写字母构成,而且长度相等 9 | 10 | 解题目标 11 | 写一个bool函数,以两个词作为参数,返回这两个词是否变位词 12 | 13 | 可以很好展示同一问题的不同数量级算法 14 | """ 15 | 16 | 17 | def anagramSolution1(s1, s2): # 遍历方法,逐字检查 18 | alist = list(s2) 19 | pos1 = 1 20 | StillOk = True 21 | while pos1 < len(s1) and StillOk: # 循环s1的字符 22 | pos2 = 0 23 | found = False 24 | while pos2 < len(alist) and not found: 25 | if s1[pos1] == alist[pos2]: # 在s2逐个对比 26 | found = True 27 | else: 28 | pos2 = pos2 + 1 29 | if found: 30 | alist[pos2] = None # 找到,打钩 31 | else: 32 | StillOk = False # 未找到,失败 33 | pos1 += 1 34 | return StillOk 35 | 36 | 37 | def anagramSolution2(s1, s2): # 排序比较 38 | alist1 = sorted(s1) 39 | alist2 = sorted(s2) 40 | 41 | pos = 0 42 | matches = True 43 | while pos < len(s1) and matches: 44 | if alist1[pos] == alist2[pos]: 45 | pos += 1 46 | else: 47 | matches = False 48 | return matches 49 | 50 | 51 | def anagramSolution3(s1, s2): # 计数比较 52 | c1 = [0]*26 # 映射字母到列表中 53 | c2 = [0]*26 54 | 55 | for i in range(len(s1)): 56 | 57 | pos = ord(s1[i]) - ord('a') # 字母个数统计 58 | c1[pos] += 1 59 | for i in range(len(s2)): 60 | pos = ord(s2[i]) - ord('a') 61 | c2[pos] += 1 62 | j = 0 63 | StillOk = True 64 | while(j < 26) and StillOk: 65 | if c1[j] == c2[j]: 66 | j += 1 67 | else: 68 | StillOk = False 69 | return StillOk 70 | 71 | 72 | if __name__ == "__main__": 73 | counter_time1 = 0 74 | counter_time2 = 0 75 | counter_time3 = 0 76 | for i in range(10000): 77 | 78 | start_time = time.perf_counter() 79 | anagramSolution1("python", "typhon") 80 | end_time = time.perf_counter() 81 | counter_time1 += end_time-start_time 82 | 83 | start_time = time.perf_counter() 84 | anagramSolution2("python", "typhon") 85 | end_time = time.perf_counter() 86 | counter_time2 += end_time-start_time 87 | 88 | start_time = time.perf_counter() 89 | anagramSolution3("python", "typhon") 90 | end_time = time.perf_counter() 91 | counter_time3 += end_time-start_time 92 | 93 | print("程序运行10000次时间%sS" % counter_time1) 94 | print("程序运行10000次时间%sS" % counter_time2) 95 | print("程序运行10000次时间%sS" % counter_time3) 96 | ''' 97 | 程序运行时间 98 | 程序运行10000次时间0.06652659999999812S 99 | 程序运行10000次时间0.028769400000001236S 100 | 程序运行10000次时间0.0948885999999989S 101 | ''' 102 | -------------------------------------------------------------------------------- /week2/practice4.py: -------------------------------------------------------------------------------- 1 | """ 2 | 题目内容: 3 | 给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。 4 | 有效字符串需满足: 5 | 左括号必须用相同类型的右括号闭合。 6 | 左括号必须以正确的顺序闭合。 7 | 注意空字符串可被认为是有效字符串。 8 | 输入格式: 9 | 一行字符串 10 | 输出格式: 11 | True或False,表示该输入是否为合法括号串 12 | 输入样例: 13 | ([]) 14 | 输出样例: 15 | True 16 | """ 17 | 18 | 19 | def isValid(s): 20 | if s == '': 21 | return True 22 | balanced = False 23 | s = list(s) 24 | if len(s) % 2 != 0: 25 | return False 26 | lis = [] 27 | if (s[0] != ')' and s[0] != '}' and s[0] != ']') and not balanced: 28 | for symbol in s: 29 | if symbol in "[({": 30 | lis.append(symbol) 31 | elif symbol in ")]}": 32 | if symbol == ")" and lis.pop() == "(": 33 | balanced = True 34 | if symbol == "]" and lis.pop() == "[": 35 | balanced = True 36 | if symbol == "}" and lis.pop() == "{": 37 | balanced = True 38 | return balanced 39 | 40 | 41 | # print(isValid(input())) 42 | 43 | 44 | """ 45 | 题目内容: 46 | 根据每日气温列表,请重新生成一个列表,对应位置的输入是你需要再等 47 | 待多久温度才会升高超过该日的天数。如果之后都不会升高,请在该位置用 0 来代替 48 | 输入格式: 49 | 一行以Python表达式格式给出的列表,包含数个整数 50 | 输出格式: 51 | 整数组成的列表,直接使用print输出 52 | 输入样例: 53 | [73, 74, 75, 71, 69, 72, 76, 73] 54 | 输出样例: 55 | [1, 1, 4, 2, 1, 1, 0, 0] 56 | """ 57 | 58 | 59 | def dailyTemp(T): 60 | lis = [0]*len(T) 61 | for day in range(len(T)): 62 | for date in range(day, len(T)): 63 | if T[day] < T[date]: 64 | lis[day] = date-day 65 | break 66 | return lis 67 | # t = eval(input()) 68 | # print(dailyTemp(t)) 69 | 70 | 71 | """ 72 | 题目内容: 73 | 根据后缀表达式表示法,求表达式的值。 74 | 有效的运算符包括 + , -, *, / ;其中除法仅保留整数结果。 75 | 若出现除数为0或表达式非法的情况,输出"NaN" 76 | 注: 77 | 每个数字token可包含多位,也可为负数 78 | 除法统一使用 int(a / b) 而非 a // b 进行计算 79 | 输入格式: 80 | 一行字符串,每个token间以空格分隔 81 | 输出格式: 82 | 一行,包含一个整数或"NaN" 83 | 输入样例: 84 | "4 13 5 / +" 85 | 输出样例: 86 | 6 87 | """ 88 | 89 | 90 | def calc(tokens): 91 | stack = [] 92 | result = 0 93 | for token in tokens: 94 | if token in "+-*/": 95 | try: 96 | stack.append(math_cal(int(stack.pop()), int(stack.pop()),token)) 97 | except IndexError: 98 | return "NaN" 99 | else: 100 | stack.append(token) 101 | if stack[-1] == "NaN": 102 | return "NaN" 103 | return stack[0] 104 | 105 | 106 | def math_cal(part1, part2, operation): 107 | if operation == "+": 108 | return part1 + part2 109 | elif operation == "-": 110 | return part2 - part1 111 | elif operation == "*": 112 | return part1 * part2 113 | elif operation == "/": 114 | if part1 == 0: 115 | return "NaN" 116 | else: 117 | return int(part2 / part1) 118 | 119 | 120 | # print(calc(input().split())) 121 | -------------------------------------------------------------------------------- /week3/practice1.py: -------------------------------------------------------------------------------- 1 | """ 2 | 题目内容: 3 | 一开始给出了一个由小写字母组成的字符串 S。 4 | 我们规定每次移动中,选择最左侧的字母,将其从原位置移除, 5 | 并加到字符串的末尾。这样的移动可以执行任意多次 6 | 返回我们移动之后可以拥有的最小字符串 7 | (注:在Python3中,字符串的大小可用不等号比较)。 8 | 输入格式: 9 | S。S为仅含有小写字母的字符串,长度不超过100000。 10 | 输出格式: 11 | 一个与S等长的字符串。 12 | 输入样例: 13 | "cba" 14 | 输出样例: 15 | acb 16 | """ 17 | 18 | 19 | # def func(S): 20 | # minStr = S 21 | # for i in range(len(S)-1): 22 | # S = "".join([S[1:],S[0]]) 23 | # if minStr > S: 24 | # minStr = S 25 | # return minStr 26 | 27 | 28 | # S = eval(input()) 29 | # print(func(S)) 30 | 31 | """ 32 | 题目内容: 33 | 计算每个事件发生之时,往前算10000毫秒内有多少个事件发生,包含当事件; 34 | 也即对于列表中的每个元素k,算出整个列表中有多少个元素介于k-10000和k(两端均含)之间。 35 | 输入格式: 36 | 一个已排序列表mylist,所有元素为非负整数,记录各个请求的发生时间,单位为毫秒。 37 | 输出格式: 38 | 一个与mylist等长的列表。 39 | 输入样例: 40 | [0,10,100,1000,10000,20000,100000] 41 | 输出样例: 42 | [1,2,3,4,5,2,1] 43 | """ 44 | 45 | 46 | # def func(mylist): 47 | 48 | # resultList = list() 49 | # for i in range(len(mylist)): 50 | # count = 1 51 | # for j in range(i): 52 | # if mylist[j] <= mylist[i] and mylist[j] >= mylist[i] - 10000: 53 | # count += 1 54 | # resultList.append(count) 55 | # return resultList 56 | 57 | 58 | # mylist = eval(input()) 59 | # print(func(mylist)) 60 | 61 | 62 | """ 63 | 题目内容: 64 | 实现一个基数排序算法,用于10进制的正整数从小到大的排序。 65 | 思路是保持10个队列(队列0、队列1......队列9、队列main), 66 | 开始,所有的数都在main队列,没有排序。 67 | 第一趟将所有的数根据其10进制个位(0~9),放入相应的队列0~9, 68 | 全放好后,按照FIFO的顺序,将每个队列的数合并排到main队列。 69 | 第二趟再从main队列队首取数,根据其十位的数值,放入相应队列0~9, 70 | 全放好后,仍然按照FIFO的顺序,将每个队列的数合并排到main队列。 71 | 第三趟放百位,再合并;第四趟放千位,再合并。 72 | 直到最多的位数放完,合并完,这样main队列里就是排好序的数列了。 73 | 输入格式: 74 | 一个列表mylist,其中mylist包含一些需要排序的正整数, 75 | 正整数互不相同且均不超过100000,且个数在1至1000之间。 76 | 输出格式: 77 | 一个与mylist等长的列表。 78 | 输入样例: 79 | [8, 91, 34, 22, 65, 30, 4, 55, 18] 80 | 输出样例: 81 | [4, 8, 18, 22, 30, 34, 55, 65, 91] 82 | """ 83 | 84 | 85 | def func(mylist): 86 | dictItems = {} 87 | for i in range(10): 88 | dictItems[i] = [] 89 | 90 | if len(mylist) == 0: 91 | return mylist 92 | dictItems["mainList"] = mylist 93 | temp = 0 94 | 95 | flag = True 96 | 97 | while flag: 98 | while len(dictItems["mainList"]) > 0: 99 | value = dictItems["mainList"].pop() 100 | result = int(value/10**temp) % 10 101 | dictItems[result].append(value) 102 | temp += 1 103 | 104 | for i in range(10): 105 | while len(dictItems[i]) > 0: 106 | dictItems["mainList"].append(dictItems[i].pop()) 107 | 108 | judge = 0 109 | 110 | for value in dictItems["mainList"]: 111 | if judge < value: 112 | judge = value 113 | flag = False 114 | else: 115 | flag = True 116 | return dictItems["mainList"] 117 | 118 | mylist = eval(input()) 119 | print(func(mylist)) 120 | -------------------------------------------------------------------------------- /week6/BFS&DFS.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "## 深度优先搜索\n", 15 | "使用栈来解决迷宫问题" 16 | ] 17 | }, 18 | { 19 | "cell_type": "code", 20 | "execution_count": 19, 21 | "metadata": {}, 22 | "outputs": [], 23 | "source": [ 24 | "maze = [\n", 25 | " [1,1,1,1,1,1,1,1,1,1],\n", 26 | " [1,0,0,1,0,0,0,1,0,1],\n", 27 | " [1,0,0,1,0,0,0,1,0,1],\n", 28 | " [1,0,0,0,0,1,1,0,0,1],\n", 29 | " [1,0,1,1,1,0,0,0,0,1],\n", 30 | " [1,0,0,0,1,0,0,0,0,1],\n", 31 | " [1,0,1,0,0,0,1,0,0,1], \n", 32 | " [1,0,1,1,1,0,1,1,0,1],\n", 33 | " [1,1,0,0,0,0,0,0,0,1],\n", 34 | " [1,1,1,1,1,1,1,1,1,1]\n", 35 | "]" 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": 20, 41 | "metadata": {}, 42 | "outputs": [], 43 | "source": [ 44 | "# x1和y1为起点坐标,x2和y2为终点坐标\n", 45 | "dirs = [\n", 46 | " lambda x, y: (x+1,y), # 下\n", 47 | " lambda x, y: (x-1, y), # 上\n", 48 | " lambda x, y: (x, y-1), # 左\n", 49 | " lambda x, y: (x, y+1), # 右\n", 50 | "]\n", 51 | "def solveMaze(x1,y1,x2,y2):\n", 52 | "# 建栈\n", 53 | " stack = []\n", 54 | " stack.append((x1, y1))\n", 55 | "# 2表示已经走过的点\n", 56 | " maze[x1][y1] = 2\n", 57 | " while len(stack) > 0:\n", 58 | "# 看栈的最后一个元素是不是有位置可以走\n", 59 | " cur_node = stack[-1]\n", 60 | " if cur_node == (x2, y2):\n", 61 | " print(stack)\n", 62 | " return True\n", 63 | " for d in dirs:\n", 64 | " next_node = d(*cur_node)\n", 65 | " if maze[next_node[0]][next_node[1]] == 0:\n", 66 | " stack.append(next_node)\n", 67 | " maze[next_node[0]][next_node[1]] = 2\n", 68 | " break\n", 69 | " else:\n", 70 | " stack.pop()\n", 71 | " print(\"无路\")\n", 72 | " return False" 73 | ] 74 | }, 75 | { 76 | "cell_type": "code", 77 | "execution_count": 21, 78 | "metadata": {}, 79 | "outputs": [ 80 | { 81 | "name": "stdout", 82 | "output_type": "stream", 83 | "text": [ 84 | "[(1, 1), (2, 1), (3, 1), (4, 1), (5, 1), (5, 2), (5, 3), (6, 3), (6, 4), (6, 5), (7, 5), (8, 5), (8, 6), (8, 7), (8, 8)]\n" 85 | ] 86 | }, 87 | { 88 | "data": { 89 | "text/plain": [ 90 | "True" 91 | ] 92 | }, 93 | "execution_count": 21, 94 | "metadata": {}, 95 | "output_type": "execute_result" 96 | } 97 | ], 98 | "source": [ 99 | "solveMaze(1,1,8,8)" 100 | ] 101 | }, 102 | { 103 | "cell_type": "code", 104 | "execution_count": null, 105 | "metadata": {}, 106 | "outputs": [], 107 | "source": [] 108 | } 109 | ], 110 | "metadata": { 111 | "kernelspec": { 112 | "display_name": "Python 3", 113 | "language": "python", 114 | "name": "python3" 115 | }, 116 | "language_info": { 117 | "codemirror_mode": { 118 | "name": "ipython", 119 | "version": 3 120 | }, 121 | "file_extension": ".py", 122 | "mimetype": "text/x-python", 123 | "name": "python", 124 | "nbconvert_exporter": "python", 125 | "pygments_lexer": "ipython3", 126 | "version": "3.7.5" 127 | } 128 | }, 129 | "nbformat": 4, 130 | "nbformat_minor": 2 131 | } 132 | -------------------------------------------------------------------------------- /week5/practice.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -* 2 | """ 3 | 给定一个长度为N的区域,及4种不同长度的瓷砖: 4 | 灰瓷砖(长为1格)、红瓷砖(长为2格)、 5 | 绿瓷砖(长为3格)与蓝瓷砖(长为4格), 6 | 求所有不同的铺满整个区域的方法数。 7 | 例如:当N = 5时,共有15种铺满区域的方法,示意图如下: 8 | 输入格式: 9 | 一个自然数N 10 | 输出格式: 11 | 一行数字,表示不同的方法总数 12 | 输入样例: 13 | 5 14 | 输出样例: 15 | 15 16 | """ 17 | 18 | 19 | def put(N, ceramicTileList, count): 20 | def putCeramicTile(N, ceramicTileList, count): 21 | if N == 0: 22 | count += 1 23 | else: 24 | for i in [c for c in ceramicTileList if c <= N]: 25 | count = putCeramicTile(N-i, ceramicTileList, count) # 递归余下砖块 26 | return count 27 | if N == 0: 28 | return 0 29 | else: 30 | return putCeramicTile(N, ceramicTileList, count) 31 | 32 | 33 | def dfs(N): 34 | if N == 0: 35 | return 0 36 | if N == 1: 37 | return 1 38 | if N == 2: 39 | return 1 + dfs(N-1) 40 | if N == 3: 41 | return 1 + dfs(N-1) + dfs(N-2) 42 | if N == 4: 43 | return 1 + dfs(N-1) + dfs(N-2) + dfs(N-3) 44 | else: 45 | return dfs(N-1) + dfs(N-2) + dfs(N-3) + dfs(N-4) 46 | 47 | 48 | # for N in range(10): 49 | # print(put(N, [1, 2, 3, 4], 0)) 50 | 51 | """ 52 | 题目内容: 53 | 老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分。 54 | 你需要按照以下要求,帮助老师给这些孩子分发糖果: 55 | 每个孩子至少分配到 1 个糖果。 56 | 相邻的孩子中,评分高的孩子必须获得更多的糖果。 57 | 那么这样下来,老师至少需要准备多少颗糖果呢? 58 | 输入格式: 59 | 一个列表,以文本格式的有效Python表达式给出 60 | 输出格式: 61 | 一行数字,表示满足分配条件所需的最少糖果数 62 | 输入样例: 63 | [1, 2, 2] 64 | 输出样例: 65 | 4 66 | 注:可行的分配方案为1、2、1 颗糖果;第三个孩子只得到1颗糖果也满足题目条件 67 | """ 68 | """ 69 | 左右遍历观点 70 | 先没人给一个苹果 71 | 从左向右遍历一遍,再从右向左遍历一遍 72 | 从右向左遍历中,左侧高于右侧,但左侧苹果比右侧少 73 | 左边的数目为右边的数目+1 74 | """ 75 | 76 | 77 | def candy(ratings): 78 | distributions = [1]*len(ratings) 79 | for i in range(1, len(ratings)): 80 | if ratings[i] > ratings[i-1]: 81 | distributions[i] += 1 82 | for j in range(1, len(ratings)): 83 | if ratings[len(ratings)-j-1] > ratings[len(ratings)-j] and distributions[len(ratings)-j-1] <= distributions[len(ratings)-j]: 84 | distributions[len(ratings)-j-1] = distributions[len(ratings)-j]+1 85 | count = 0 86 | for distribution in distributions: 87 | count += distribution 88 | return count 89 | 90 | 91 | # lst = eval(input()) 92 | # print(candy(lst)) 93 | 94 | """ 95 | 链接:https://www.nowcoder.com/questionTerminal/74a62e876ec341de8ab5c8662e866aef 96 | 来源:牛客网 97 | 1)当前孩子的rating比前面的孩子的rating高时: 98 | 只需要考虑当前孩子的candies数目比前面孩子的candies的数目多至少一个即可; 99 | 当前面的rating等于后面孩子的rating时,则题目没有说明,则可以比他多或者少; 100 | 2)当前孩子的rating比后面孩子的raitng低时: 101 | 考虑当前孩子的后面的单调递减的孩子的数目, 102 | 因为最后一个单调递减的孩子的手里至少还剩下一个糖果存在, 103 | 则新建一个数组来存储单调递减孩子的数目, 104 | 并将当前孩子的手里的糖果的数目设定为单调递减孩子的数目+1; 105 | 3)判断左边动态规划和右边动态规划的糖果数目,取其中糖果数目最大的即可; 106 | """ 107 | 108 | 109 | def dynamicCandy(ratings): 110 | length = len(ratings) 111 | if length == 0: 112 | return 0 113 | distributions = [0]*length # 存每个小孩应发的糖果树木 114 | distributions[0] = 1 115 | for i in range(1, length): # 不断遍历ratings并更新distributions 116 | if ratings[i] > ratings[i-1]: # 如果新加入的小孩大于前一个小孩,则糖果比前一个小孩多一个 117 | distributions[i] = distributions[i-1] + 1 118 | elif ratings[i] == ratings[i-1]: # 如果等于前一个小孩,则新小孩需要分一个糖果,distributions不需要更新 119 | distributions[i] = 1 120 | 121 | else: # 如果小于前一个小孩,则新加入的小孩分一个糖果,之前的小孩应该比他分到的糖果多 122 | distributions[i] = 1 123 | if distributions[i - 1] == 1: # 如果前面的小孩只有一个糖果,则需要更新distributions 124 | j = i-1 # 前面的小孩都多分一个糖果,直到递增结束 125 | while j != 0 and distributions[j] < distributions[j-1]: 126 | distributions[j] += 1 127 | j -= 1 128 | if distributions[j] <= distributions[j+1] and\ 129 | distributions[j] != distributions[j+1]: # ratings 相等情况 130 | distributions[j] += 1 131 | 132 | sum = 0 133 | for distribution in distributions: 134 | sum += distribution 135 | return sum 136 | 137 | 138 | # lst = eval(input()) 139 | # print(dynamicCandy(lst)) 140 | 141 | """ 142 | 题目内容: 143 | 给定一个表达式字符串,求出按不同的求值顺序可能得到的所有结果 144 | 输入格式: 145 | 一行字符串,仅包含0-9与运算符+、-与* 146 | 注:字符串保证三种运算符左右均为数字字符 147 | 输出格式: 148 | 所有不重复的可能的结果,从小到大排序并以半角逗号","分隔 149 | 输入样例: 150 | 2*3-4*5 151 | 输出样例: 152 | -34,-14,-10,10 153 | 注: 154 | (2*(3-(4*5))) = -34 155 | ((2*3)-(4*5)) = -14 156 | ((2*(3-4))*5) = -10 157 | (2*((3-4)*5)) = -10 158 | (((2*3)-4)*5) = 10 159 | """ 160 | 161 | 162 | def findWays(expr): 163 | # 用于将字符串转为数字与运算符,供参考 164 | nums, ops = [], [] 165 | num = 0 166 | for c in expr: 167 | if '0' <= c <= '9': 168 | num = num * 10 + ord(c) - 48 169 | else: 170 | ops.append(c) 171 | nums.append(num) 172 | num = 0 173 | else: 174 | nums.append(num) 175 | 176 | def diffWaysToComputer(nums, ops): # 使用递归运算 177 | if not ops: 178 | return [nums[0]] 179 | if len(ops) == 1: 180 | if ops[0] == '+': 181 | return nums[0]+nums[1] 182 | elif ops[0] == '-': 183 | return nums[0]-nums[1] 184 | else: 185 | return nums[0]*nums[1] 186 | res = [] 187 | for i in range(len(ops)): 188 | result = diffWaysToComputer(nums[:i+1], ops[:i]) 189 | return diffWaysToComputer(nums, ops) 190 | 191 | 192 | expr = "2*3-4*5" 193 | print(findWays(expr)) -------------------------------------------------------------------------------- /week3/List.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -* 2 | 3 | 4 | class Node: # 节点实现 5 | def __init__(self, initdata): 6 | self.data = initdata 7 | self.next = None 8 | 9 | def getCurrent(self): 10 | return self.data 11 | 12 | def getNext(self): 13 | return self.next 14 | 15 | def addCurrent(self, item): 16 | self.data = item 17 | 18 | def addNext(self, item): 19 | self.next = item 20 | 21 | 22 | class unorderedList: # 无序列表实现 23 | def __init__(self): 24 | self.head = None 25 | 26 | def printer(self): 27 | current = self.head 28 | while current != None: 29 | print(current.getCurrent(), end="\t") 30 | current = current.getNext() 31 | 32 | def append(self, item): 33 | temp = Node(item) 34 | temp.addNext(self.head) 35 | self.head = temp 36 | 37 | def isEmpty(self): # 判断是否为空 38 | return self.head == None 39 | 40 | def size(self): 41 | current = self.head 42 | count = 0 43 | while current != None: 44 | count += 1 45 | current = current.getNext() 46 | return count 47 | 48 | def search(self, item): # 搜索函数 49 | current = self.head 50 | found = False 51 | while current != None and not found: 52 | if current.getCurrent() == item: 53 | found = True 54 | else: 55 | current = current.getNext() 56 | 57 | return found 58 | 59 | def pop(self): # pop()函数 60 | if self.head != None: 61 | self.head = self.head.getNext() 62 | else: 63 | return None 64 | 65 | def remove(self, item): 66 | current = self.head 67 | 68 | previous = None 69 | found = False 70 | while current != None and not found: 71 | if current.getCurrent() == item: 72 | found = True 73 | else: 74 | previous = current 75 | current = current.getNext() 76 | 77 | if previous == None and current == None: 78 | return None 79 | elif previous == None: # 直接找到 80 | self.head = current.getNext() 81 | elif current == None: # 未找到 82 | return None 83 | else: 84 | previous.addNext(current.getNext()) 85 | 86 | def pop(self, pos): 87 | current = self.head 88 | previous = None 89 | count = 0 90 | found = False 91 | while current != None and not found: 92 | if count == pos: 93 | found = True 94 | else: 95 | previous = current 96 | current = current.getNext() 97 | count += 1 98 | 99 | if previous == None and current == None: 100 | return None 101 | elif previous== None: 102 | self.head = current.getNext() 103 | elif current == None: 104 | return None 105 | else: 106 | previous.addNext(current.getNext()) 107 | 108 | def index(self): 109 | count = 0 110 | current = self.head 111 | while current != None: 112 | current.getNext() 113 | count += 1 114 | 115 | return count 116 | 117 | def insert(self, pos, item): 118 | current = self.head 119 | previous = None 120 | found = False 121 | count = 0 122 | while current!= None and not found: 123 | if count == pos: 124 | found = True 125 | else: 126 | previous =current 127 | current = current.getNext() 128 | count += 1 129 | 130 | temp = Node(item) 131 | if previous == None and current == None: 132 | self.head = temp 133 | elif previous == None: 134 | self.head = temp 135 | temp.addNext(current) 136 | elif current == None: 137 | return None 138 | else: 139 | previous.addNext(temp) 140 | temp.addNext(current) 141 | 142 | 143 | class orderedList: 144 | def __init__(self): 145 | self.head = None 146 | 147 | def size(self): 148 | count = 0 149 | current = self.head 150 | while current != None: 151 | currrent = current.getNext() 152 | 153 | return count 154 | 155 | def isEmpty(self): 156 | return self.head == None 157 | 158 | 159 | def append(self, item): 160 | current = self.head 161 | previous = None 162 | found = False 163 | while not found and current != None: 164 | if item < current.getCurrent(): 165 | found = True 166 | else: 167 | previous = current 168 | current = current.getNext() 169 | 170 | temp = Node(item) 171 | if previous == None: 172 | temp.addNext(current) 173 | self.head = temp 174 | else: 175 | temp.addNext(current) 176 | previous.addNext(temp) 177 | 178 | def remove(self, item): 179 | current = self.head 180 | previous = None 181 | found = False 182 | while current != None and not found: 183 | if current.getCurrent() == item: 184 | found = True 185 | else: 186 | previous = current 187 | current = current.getNext() 188 | 189 | if previous == None and current == None: 190 | return None 191 | elif previous == None: # 直接找到 192 | self.head = current.getNext() 193 | elif current == None: # 未找到 194 | return None 195 | else: 196 | previous.addNext(current.getNext()) 197 | 198 | def pop(self): 199 | current = self.head 200 | if current != None: 201 | self.head = current.getNext() 202 | else: 203 | return None 204 | 205 | def pop(self, pos): 206 | current = self.head 207 | previous = None 208 | count = 0 209 | found = False 210 | while current != None and not found: 211 | if count == pos: 212 | found = True 213 | else: 214 | previous = current 215 | current = current.getNext() 216 | count += 1 217 | 218 | if previous == None and current == None: 219 | return None 220 | elif previous == None: 221 | self.head = current.getNext() 222 | elif current == None: 223 | return None 224 | else: 225 | previous.addNext(current.getNext()) 226 | 227 | def printer(self): 228 | current = self.head 229 | while current != None: 230 | print(current.getCurrent(), end="\t") 231 | current = current.getNext() 232 | 233 | if __name__ == "__main__": 234 | x = orderedList() 235 | x.append(5) 236 | x.append(4) 237 | x.append(0) 238 | x.append(8) 239 | x.printer() 240 | -------------------------------------------------------------------------------- /week6/.ipynb_checkpoints/practice-checkpoint.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# 查找和排序算法" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": 52, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import matplotlib.pyplot as plt\n", 17 | "import random\n", 18 | "import time" 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": 2, 24 | "metadata": {}, 25 | "outputs": [], 26 | "source": [ 27 | "# %matplotlib inline\n", 28 | "plt.rcParams['font.family'] = ['sans-serif']\n", 29 | "plt.rcParams['font.sans-serif'] = ['SimHei']" 30 | ] 31 | }, 32 | { 33 | "cell_type": "markdown", 34 | "metadata": {}, 35 | "source": [ 36 | "## 顺序查找" 37 | ] 38 | }, 39 | { 40 | "cell_type": "markdown", 41 | "metadata": {}, 42 | "source": [ 43 | "### 无序表查找代码" 44 | ] 45 | }, 46 | { 47 | "cell_type": "code", 48 | "execution_count": 3, 49 | "metadata": {}, 50 | "outputs": [ 51 | { 52 | "name": "stdout", 53 | "output_type": "stream", 54 | "text": [ 55 | "Using matplotlib backend: Qt5Agg\n" 56 | ] 57 | } 58 | ], 59 | "source": [ 60 | "%matplotlib\n", 61 | "def sequentialSearch(alist, item):\n", 62 | " plt.figure()\n", 63 | " pos = 0 # 当前位置\n", 64 | " found = False # 是否查找到\n", 65 | " plt.ion()\n", 66 | " while pos < len(alist) and not found:\n", 67 | " plt.cla()\n", 68 | " bar = plt.bar(x=[i for i in range(len(alist))],height=alist)\n", 69 | " bar[pos].set_color(\"red\")\n", 70 | " if alist[pos] == item:\n", 71 | " bar[pos].set_color(\"green\")\n", 72 | " found = True # 查找到当前位置\n", 73 | " else:\n", 74 | " pos += 1\n", 75 | " plt.pause(1)\n", 76 | " plt.ioff()\n", 77 | " plt.show()\n", 78 | " return found" 79 | ] 80 | }, 81 | { 82 | "cell_type": "code", 83 | "execution_count": 5, 84 | "metadata": {}, 85 | "outputs": [ 86 | { 87 | "ename": "NameError", 88 | "evalue": "name 'testlist' is not defined", 89 | "output_type": "error", 90 | "traceback": [ 91 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 92 | "\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)", 93 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0msequentialSearch\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mtestlist\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m3\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 2\u001b[0m \u001b[1;31m# print(sequentialSearch(testlist,8))\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", 94 | "\u001b[1;31mNameError\u001b[0m: name 'testlist' is not defined" 95 | ] 96 | } 97 | ], 98 | "source": [ 99 | "\n", 100 | "print(sequentialSearch(testlist,3))\n", 101 | "# print(sequentialSearch(testlist,8))" 102 | ] 103 | }, 104 | { 105 | "cell_type": "markdown", 106 | "metadata": {}, 107 | "source": [ 108 | "### 有序表查找代码" 109 | ] 110 | }, 111 | { 112 | "cell_type": "code", 113 | "execution_count": 5, 114 | "metadata": {}, 115 | "outputs": [ 116 | { 117 | "name": "stdout", 118 | "output_type": "stream", 119 | "text": [ 120 | "Using matplotlib backend: Qt5Agg\n" 121 | ] 122 | } 123 | ], 124 | "source": [ 125 | "%matplotlib\n", 126 | "def sequentialSearch(alist, item):\n", 127 | " pos = 0 # 当前位置\n", 128 | " found = False # 是否查找到\n", 129 | " stop = False\n", 130 | " plt.figure()\n", 131 | " plt.ion()\n", 132 | " while pos < len(alist) and not found and not stop:\n", 133 | " plt.cla()\n", 134 | " bar = plt.bar(x=[i for i in range(len(alist))],height=alist)\n", 135 | " plt.title(\"查找 %d\" % item)\n", 136 | " bar[pos].set_color(\"green\")\n", 137 | " if alist[pos] == item:\n", 138 | " found = True # 查找到当前位置\n", 139 | " else:\n", 140 | " if item < alist[pos]:\n", 141 | " stop = True\n", 142 | " else:\n", 143 | " pos += 1\n", 144 | " plt.pause(0.2)\n", 145 | " plt.ioff()\n", 146 | " plt.show()\n", 147 | " return found" 148 | ] 149 | }, 150 | { 151 | "cell_type": "code", 152 | "execution_count": 21, 153 | "metadata": {}, 154 | "outputs": [ 155 | { 156 | "name": "stdout", 157 | "output_type": "stream", 158 | "text": [ 159 | "False\n", 160 | "True\n" 161 | ] 162 | } 163 | ], 164 | "source": [ 165 | "testlist = random.choices(range(1,10),k=5,weights=range(1,10))\n", 166 | "print(sequentialSearch(testlist,3))\n", 167 | "print(sequentialSearch(testlist,8))" 168 | ] 169 | }, 170 | { 171 | "cell_type": "markdown", 172 | "metadata": {}, 173 | "source": [ 174 | "## 二分查找\n", 175 | "### 二分查找建立在有序表的基礎上" 176 | ] 177 | }, 178 | { 179 | "cell_type": "code", 180 | "execution_count": 6, 181 | "metadata": {}, 182 | "outputs": [ 183 | { 184 | "name": "stdout", 185 | "output_type": "stream", 186 | "text": [ 187 | "True\n" 188 | ] 189 | } 190 | ], 191 | "source": [ 192 | "def binarySearch(alist,item):\n", 193 | " first = 0\n", 194 | " last = len(alist)-1\n", 195 | " found = False\n", 196 | " plt.figure()\n", 197 | " plt.ion()\n", 198 | " while first <= last and not found:\n", 199 | " plt.cla()\n", 200 | " bar = plt.bar(x=[i for i in range(len(alist))],height=alist)\n", 201 | " midpoint = (first+last)//2 # 查找中点\n", 202 | " bar[midpoint].set_color(\"red\")\n", 203 | " if alist[midpoint]==item: # 中点是否等于item\n", 204 | " bar[midpoint].set_color(\"green\")\n", 205 | " found = True\n", 206 | " else:\n", 207 | " if item < alist[midpoint]:\n", 208 | " last = midpoint - 1\n", 209 | " else:\n", 210 | " first = midpoint + 1\n", 211 | " plt.pause(1)\n", 212 | " plt.ioff()\n", 213 | " plt.show()\n", 214 | " return found\n", 215 | "testlist = random.choices(range(1,100),k=30,weights=range(1,100))\n", 216 | "print(binarySearch(sorted(testlist), 56))" 217 | ] 218 | }, 219 | { 220 | "cell_type": "markdown", 221 | "metadata": {}, 222 | "source": [ 223 | "### 二分查找分而治之" 224 | ] 225 | }, 226 | { 227 | "cell_type": "code", 228 | "execution_count": 7, 229 | "metadata": {}, 230 | "outputs": [], 231 | "source": [ 232 | "def binarySearchOne(alist, item):\n", 233 | " if len(alist)==0:\n", 234 | " return False\n", 235 | " else:\n", 236 | " midpoint = len(alist) // 2 # 查找中点\n", 237 | " if alist[midpoint]==item: # 是否符合主体条件\n", 238 | " return True\n", 239 | " else:\n", 240 | " if item < alist[midpoint]: # 判断是否在左侧还是右侧\n", 241 | " return binarySearchOne(alist[:midpoint],item)\n", 242 | " else:\n", 243 | " return binarySearchOne(alist[midpoint+1:],item)" 244 | ] 245 | }, 246 | { 247 | "cell_type": "code", 248 | "execution_count": 158, 249 | "metadata": {}, 250 | "outputs": [], 251 | "source": [ 252 | "def binarySearchTwo(alist,item,first,last):\n", 253 | " if first >= last:\n", 254 | " return False\n", 255 | " else:\n", 256 | " midpoint = (first+last) // 2\n", 257 | " if alist[midpoint] == item:\n", 258 | " return True\n", 259 | " else:\n", 260 | " if item < alist[midpoint]:\n", 261 | " return binarySearchTwo(alist, item, first, last=midpoint)\n", 262 | " else:\n", 263 | " first = midpoint + 1\n", 264 | " return binarySearchTwo(alist, item, first, last)" 265 | ] 266 | }, 267 | { 268 | "cell_type": "code", 269 | "execution_count": 161, 270 | "metadata": {}, 271 | "outputs": [ 272 | { 273 | "name": "stdout", 274 | "output_type": "stream", 275 | "text": [ 276 | "True\n", 277 | "True\n", 278 | "0.00025770000047486974\n", 279 | "0.00017019999995682156\n" 280 | ] 281 | } 282 | ], 283 | "source": [ 284 | "testlist = random.choices(range(1,10),k=6,weights=range(1,10))\n", 285 | "x1 = time.perf_counter()\n", 286 | "print(binarySearchOne(sorted(testlist), 8))\n", 287 | "x2 = time.perf_counter()\n", 288 | "print(binarySearchTwo(sorted(testlist), 8,first=0,last=len(sorted(testlist))-1))\n", 289 | "x3 = time.perf_counter()\n", 290 | "print(x2-x1)\n", 291 | "print(x3-x2)" 292 | ] 293 | }, 294 | { 295 | "cell_type": "markdown", 296 | "metadata": {}, 297 | "source": [ 298 | "## 冒泡排序" 299 | ] 300 | }, 301 | { 302 | "cell_type": "code", 303 | "execution_count": 8, 304 | "metadata": {}, 305 | "outputs": [ 306 | { 307 | "name": "stdout", 308 | "output_type": "stream", 309 | "text": [ 310 | "Using matplotlib backend: Qt5Agg\n", 311 | "[7, 16, 21, 32, 33, 37, 53, 53, 54, 56, 58, 59, 72, 74, 75, 75, 76, 78, 78, 86, 87, 88, 90, 90, 92, 95, 95, 96, 97, 98]\n" 312 | ] 313 | } 314 | ], 315 | "source": [ 316 | "%matplotlib\n", 317 | "def bubbleSort(alist):\n", 318 | " plt.figure()\n", 319 | " plt.ion()\n", 320 | " for passnum in range(len(alist)-1,0,-1):\n", 321 | " for i in range(passnum):\n", 322 | " plt.cla()\n", 323 | " bar = plt.bar(x=[i for i in range(len(alist))],height=alist)\n", 324 | " bar[i].set_color(\"red\")\n", 325 | " bar[i+1].set_color(\"red\")\n", 326 | " plt.pause(0.2)\n", 327 | " if alist[i]>alist[i+1]:\n", 328 | " temp = alist[i]\n", 329 | " alist[i] = alist[i+1]\n", 330 | " alist[i+1] = temp\n", 331 | " plt.cla()\n", 332 | " bar = plt.bar(x=[i for i in range(len(alist))],height=alist)\n", 333 | " bar[i].set_color(\"green\")\n", 334 | " bar[i+1].set_color(\"green\")\n", 335 | " plt.pause(0.4)\n", 336 | " plt.ioff()\n", 337 | " plt.show()\n", 338 | "testlist = random.choices(range(1,100),k=30,weights=range(1,100))\n", 339 | "bubbleSort(testlist)\n", 340 | "print(testlist)" 341 | ] 342 | }, 343 | { 344 | "cell_type": "markdown", 345 | "metadata": {}, 346 | "source": [ 347 | "# 快速排序" 348 | ] 349 | }, 350 | { 351 | "cell_type": "code", 352 | "execution_count": 65, 353 | "metadata": {}, 354 | "outputs": [], 355 | "source": [ 356 | "def quickSort(alist,left,right):\n", 357 | " if left < right:\n", 358 | " mid = partition(alist, left, right)\n", 359 | " quickSort(alist, left, mid-1)\n", 360 | " quickSort(alist, mid+1, right)\n", 361 | "\n", 362 | "\n", 363 | "def partition(li, left, right):\n", 364 | " tmp = alist[left]\n", 365 | " while left < right:\n", 366 | " while left < right and li[right] >= tmp:\n", 367 | " right -= 1\n", 368 | " li[left] = li[right]\n", 369 | " while left < right and li[left] <= tmp:\n", 370 | " left += 1\n", 371 | " li[right] = li[left]\n", 372 | " li[left] = tmp\n", 373 | " return left" 374 | ] 375 | }, 376 | { 377 | "cell_type": "code", 378 | "execution_count": 66, 379 | "metadata": {}, 380 | "outputs": [ 381 | { 382 | "name": "stdout", 383 | "output_type": "stream", 384 | "text": [ 385 | "[76, 97, 70, 71, 53, 38, 73, 59, 38, 93, 37, 64, 9, 68, 72, 72, 46, 91, 75, 79, 96, 71, 74, 91, 27, 99, 95, 60, 83, 52]\n", 386 | "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 12, 13, 14, 15, 16, 17, 18, 79, 96, 71, 74, 91, 27, 99, 95, 60, 83, 52]\n" 387 | ] 388 | } 389 | ], 390 | "source": [ 391 | "testlist = random.choices(range(1,100),k=30,weights=range(1,100))\n", 392 | "print(testlist)\n", 393 | "quickSort(testlist, 0, len(alist)-1)\n", 394 | "print(testlist)" 395 | ] 396 | }, 397 | { 398 | "cell_type": "code", 399 | "execution_count": 54, 400 | "metadata": {}, 401 | "outputs": [], 402 | "source": [] 403 | }, 404 | { 405 | "cell_type": "code", 406 | "execution_count": null, 407 | "metadata": {}, 408 | "outputs": [], 409 | "source": [] 410 | } 411 | ], 412 | "metadata": { 413 | "kernelspec": { 414 | "display_name": "Python 3", 415 | "language": "python", 416 | "name": "python3" 417 | }, 418 | "language_info": { 419 | "codemirror_mode": { 420 | "name": "ipython", 421 | "version": 3 422 | }, 423 | "file_extension": ".py", 424 | "mimetype": "text/x-python", 425 | "name": "python", 426 | "nbconvert_exporter": "python", 427 | "pygments_lexer": "ipython3", 428 | "version": "3.7.5" 429 | } 430 | }, 431 | "nbformat": 4, 432 | "nbformat_minor": 2 433 | } 434 | -------------------------------------------------------------------------------- /week6/practice.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# 查找和排序算法" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": 1, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import matplotlib.pyplot as plt\n", 17 | "import matplotlib.animation as animation\n", 18 | "import random\n", 19 | "import time" 20 | ] 21 | }, 22 | { 23 | "cell_type": "code", 24 | "execution_count": 2, 25 | "metadata": {}, 26 | "outputs": [], 27 | "source": [ 28 | "# %matplotlib inline\n", 29 | "plt.rcParams['font.family'] = ['sans-serif']\n", 30 | "plt.rcParams['font.sans-serif'] = ['SimHei']" 31 | ] 32 | }, 33 | { 34 | "cell_type": "code", 35 | "execution_count": 10, 36 | "metadata": {}, 37 | "outputs": [], 38 | "source": [ 39 | "def cal_time(func):\n", 40 | " def wrapper(*args, **kw):\n", 41 | " time1 = time.perf_counter()\n", 42 | " func(*args, **kw)\n", 43 | " time2 = time.perf_counter()\n", 44 | " print(\"call %s for %s second\"% (func.__name__, time2-time1))\n", 45 | " return wrapper" 46 | ] 47 | }, 48 | { 49 | "cell_type": "markdown", 50 | "metadata": {}, 51 | "source": [ 52 | "## 顺序查找" 53 | ] 54 | }, 55 | { 56 | "cell_type": "markdown", 57 | "metadata": {}, 58 | "source": [ 59 | "### 无序表查找代码" 60 | ] 61 | }, 62 | { 63 | "cell_type": "code", 64 | "execution_count": 12, 65 | "metadata": {}, 66 | "outputs": [ 67 | { 68 | "name": "stdout", 69 | "output_type": "stream", 70 | "text": [ 71 | "Using matplotlib backend: Qt5Agg\n" 72 | ] 73 | } 74 | ], 75 | "source": [ 76 | "%matplotlib\n", 77 | "@cal_time\n", 78 | "def sequentialSearch(alist, item):\n", 79 | " plt.figure()\n", 80 | " pos = 0 # 当前位置\n", 81 | " found = False # 是否查找到\n", 82 | " plt.ion()\n", 83 | " while pos < len(alist) and not found:\n", 84 | " plt.cla()\n", 85 | " bar = plt.bar(x=[i for i in range(len(alist))],height=alist)\n", 86 | " bar[pos].set_color(\"red\")\n", 87 | " if alist[pos] == item:\n", 88 | " bar[pos].set_color(\"green\")\n", 89 | " found = True # 查找到当前位置\n", 90 | " else:\n", 91 | " pos += 1\n", 92 | " plt.pause(1)\n", 93 | " plt.ioff()\n", 94 | " plt.show()\n", 95 | " return found" 96 | ] 97 | }, 98 | { 99 | "cell_type": "code", 100 | "execution_count": null, 101 | "metadata": {}, 102 | "outputs": [], 103 | "source": [ 104 | "sequentialSearch()" 105 | ] 106 | }, 107 | { 108 | "cell_type": "code", 109 | "execution_count": 5, 110 | "metadata": {}, 111 | "outputs": [ 112 | { 113 | "ename": "NameError", 114 | "evalue": "name 'testlist' is not defined", 115 | "output_type": "error", 116 | "traceback": [ 117 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 118 | "\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)", 119 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0msequentialSearch\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mtestlist\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m3\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 2\u001b[0m \u001b[1;31m# print(sequentialSearch(testlist,8))\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", 120 | "\u001b[1;31mNameError\u001b[0m: name 'testlist' is not defined" 121 | ] 122 | } 123 | ], 124 | "source": [ 125 | "\n", 126 | "print(sequentialSearch(testlist,3))\n", 127 | "# print(sequentialSearch(testlist,8))" 128 | ] 129 | }, 130 | { 131 | "cell_type": "markdown", 132 | "metadata": {}, 133 | "source": [ 134 | "### 有序表查找代码" 135 | ] 136 | }, 137 | { 138 | "cell_type": "code", 139 | "execution_count": 5, 140 | "metadata": {}, 141 | "outputs": [ 142 | { 143 | "name": "stdout", 144 | "output_type": "stream", 145 | "text": [ 146 | "Using matplotlib backend: Qt5Agg\n" 147 | ] 148 | } 149 | ], 150 | "source": [ 151 | "%matplotlib\n", 152 | "def sequentialSearch(alist, item):\n", 153 | " pos = 0 # 当前位置\n", 154 | " found = False # 是否查找到\n", 155 | " stop = False\n", 156 | " plt.figure()\n", 157 | " plt.ion()\n", 158 | " while pos < len(alist) and not found and not stop:\n", 159 | " plt.cla()\n", 160 | " bar = plt.bar(x=[i for i in range(len(alist))],height=alist)\n", 161 | " plt.title(\"查找 %d\" % item)\n", 162 | " bar[pos].set_color(\"green\")\n", 163 | " if alist[pos] == item:\n", 164 | " found = True # 查找到当前位置\n", 165 | " else:\n", 166 | " if item < alist[pos]:\n", 167 | " stop = True\n", 168 | " else:\n", 169 | " pos += 1\n", 170 | " plt.pause(0.2)\n", 171 | " plt.ioff()\n", 172 | " plt.show()\n", 173 | " return found" 174 | ] 175 | }, 176 | { 177 | "cell_type": "code", 178 | "execution_count": 21, 179 | "metadata": {}, 180 | "outputs": [ 181 | { 182 | "name": "stdout", 183 | "output_type": "stream", 184 | "text": [ 185 | "False\n", 186 | "True\n" 187 | ] 188 | } 189 | ], 190 | "source": [ 191 | "testlist = random.choices(range(1,10),k=5,weights=range(1,10))\n", 192 | "print(sequentialSearch(testlist,3))\n", 193 | "print(sequentialSearch(testlist,8))" 194 | ] 195 | }, 196 | { 197 | "cell_type": "markdown", 198 | "metadata": {}, 199 | "source": [ 200 | "## 二分查找\n", 201 | "### 二分查找建立在有序表的基礎上" 202 | ] 203 | }, 204 | { 205 | "cell_type": "code", 206 | "execution_count": 6, 207 | "metadata": {}, 208 | "outputs": [ 209 | { 210 | "name": "stdout", 211 | "output_type": "stream", 212 | "text": [ 213 | "True\n" 214 | ] 215 | } 216 | ], 217 | "source": [ 218 | "def binarySearch(alist,item):\n", 219 | " first = 0\n", 220 | " last = len(alist)-1\n", 221 | " found = False\n", 222 | " plt.figure()\n", 223 | " plt.ion()\n", 224 | " while first <= last and not found:\n", 225 | " plt.cla()\n", 226 | " bar = plt.bar(x=[i for i in range(len(alist))],height=alist)\n", 227 | " midpoint = (first+last)//2 # 查找中点\n", 228 | " bar[midpoint].set_color(\"red\")\n", 229 | " if alist[midpoint]==item: # 中点是否等于item\n", 230 | " bar[midpoint].set_color(\"green\")\n", 231 | " found = True\n", 232 | " else:\n", 233 | " if item < alist[midpoint]:\n", 234 | " last = midpoint - 1\n", 235 | " else:\n", 236 | " first = midpoint + 1\n", 237 | " plt.pause(1)\n", 238 | " plt.ioff()\n", 239 | " plt.show()\n", 240 | " return found\n", 241 | "testlist = random.choices(range(1,100),k=30,weights=range(1,100))\n", 242 | "print(binarySearch(sorted(testlist), 56))" 243 | ] 244 | }, 245 | { 246 | "cell_type": "markdown", 247 | "metadata": {}, 248 | "source": [ 249 | "### 二分查找分而治之" 250 | ] 251 | }, 252 | { 253 | "cell_type": "code", 254 | "execution_count": 7, 255 | "metadata": {}, 256 | "outputs": [], 257 | "source": [ 258 | "def binarySearchOne(alist, item):\n", 259 | " if len(alist)==0:\n", 260 | " return False\n", 261 | " else:\n", 262 | " midpoint = len(alist) // 2 # 查找中点\n", 263 | " if alist[midpoint]==item: # 是否符合主体条件\n", 264 | " return True\n", 265 | " else:\n", 266 | " if item < alist[midpoint]: # 判断是否在左侧还是右侧\n", 267 | " return binarySearchOne(alist[:midpoint],item)\n", 268 | " else:\n", 269 | " return binarySearchOne(alist[midpoint+1:],item)" 270 | ] 271 | }, 272 | { 273 | "cell_type": "code", 274 | "execution_count": 158, 275 | "metadata": {}, 276 | "outputs": [], 277 | "source": [ 278 | "def binarySearchTwo(alist,item,first,last):\n", 279 | " if first >= last:\n", 280 | " return False\n", 281 | " else:\n", 282 | " midpoint = (first+last) // 2\n", 283 | " if alist[midpoint] == item:\n", 284 | " return True\n", 285 | " else:\n", 286 | " if item < alist[midpoint]:\n", 287 | " return binarySearchTwo(alist, item, first, last=midpoint)\n", 288 | " else:\n", 289 | " first = midpoint + 1\n", 290 | " return binarySearchTwo(alist, item, first, last)" 291 | ] 292 | }, 293 | { 294 | "cell_type": "code", 295 | "execution_count": 161, 296 | "metadata": {}, 297 | "outputs": [ 298 | { 299 | "name": "stdout", 300 | "output_type": "stream", 301 | "text": [ 302 | "True\n", 303 | "True\n", 304 | "0.00025770000047486974\n", 305 | "0.00017019999995682156\n" 306 | ] 307 | } 308 | ], 309 | "source": [ 310 | "testlist = random.choices(range(1,10),k=6,weights=range(1,10))\n", 311 | "x1 = time.perf_counter()\n", 312 | "print(binarySearchOne(sorted(testlist), 8))\n", 313 | "x2 = time.perf_counter()\n", 314 | "print(binarySearchTwo(sorted(testlist), 8,first=0,last=len(sorted(testlist))-1))\n", 315 | "x3 = time.perf_counter()\n", 316 | "print(x2-x1)\n", 317 | "print(x3-x2)" 318 | ] 319 | }, 320 | { 321 | "cell_type": "markdown", 322 | "metadata": {}, 323 | "source": [ 324 | "## 冒泡排序" 325 | ] 326 | }, 327 | { 328 | "cell_type": "code", 329 | "execution_count": 8, 330 | "metadata": {}, 331 | "outputs": [ 332 | { 333 | "name": "stdout", 334 | "output_type": "stream", 335 | "text": [ 336 | "Using matplotlib backend: Qt5Agg\n", 337 | "[7, 16, 21, 32, 33, 37, 53, 53, 54, 56, 58, 59, 72, 74, 75, 75, 76, 78, 78, 86, 87, 88, 90, 90, 92, 95, 95, 96, 97, 98]\n" 338 | ] 339 | } 340 | ], 341 | "source": [ 342 | "%matplotlib\n", 343 | "def bubbleSort(alist):\n", 344 | " plt.figure()\n", 345 | " plt.ion()\n", 346 | " for passnum in range(len(alist)-1,0,-1):\n", 347 | " for i in range(passnum):\n", 348 | " plt.cla()\n", 349 | " bar = plt.bar(x=[i for i in range(len(alist))],height=alist)\n", 350 | " bar[i].set_color(\"red\")\n", 351 | " bar[i+1].set_color(\"red\")\n", 352 | " plt.pause(0.2)\n", 353 | " if alist[i]>alist[i+1]:\n", 354 | " temp = alist[i]\n", 355 | " alist[i] = alist[i+1]\n", 356 | " alist[i+1] = temp\n", 357 | " plt.cla()\n", 358 | " bar = plt.bar(x=[i for i in range(len(alist))],height=alist)\n", 359 | " bar[i].set_color(\"green\")\n", 360 | " bar[i+1].set_color(\"green\")\n", 361 | " plt.pause(0.4)\n", 362 | " plt.ioff()\n", 363 | " plt.show()\n", 364 | "testlist = random.choices(range(1,100),k=30,weights=range(1,100))\n", 365 | "bubbleSort(testlist)\n", 366 | "print(testlist)" 367 | ] 368 | }, 369 | { 370 | "cell_type": "markdown", 371 | "metadata": {}, 372 | "source": [ 373 | "## 快速排序" 374 | ] 375 | }, 376 | { 377 | "cell_type": "code", 378 | "execution_count": 91, 379 | "metadata": {}, 380 | "outputs": [], 381 | "source": [ 382 | "def quickSort(alist,left,right):\n", 383 | " if left < right:\n", 384 | " mid = random_partition(alist, left, right)\n", 385 | " quickSort(alist, left, mid-1)\n", 386 | " quickSort(alist, mid+1, right)\n", 387 | "\n", 388 | "def partition(li, left, right):\n", 389 | " tmp = li[left]\n", 390 | " while left < right:\n", 391 | " while left < right and li[right] >= tmp:\n", 392 | " right -= 1\n", 393 | " li[left] = li[right]\n", 394 | " while left < right and li[left] <= tmp:\n", 395 | " left += 1\n", 396 | " li[right] = li[left]\n", 397 | " li[left] = tmp\n", 398 | " return left\n", 399 | "\n", 400 | "def random_partition(li, left, right):\n", 401 | " i = random.randint(left,right)\n", 402 | " li[i],li[left] = li[left],li[i]\n", 403 | " return partition(li, left, right)" 404 | ] 405 | }, 406 | { 407 | "cell_type": "code", 408 | "execution_count": 109, 409 | "metadata": {}, 410 | "outputs": [], 411 | "source": [ 412 | "def quickSort2(alist):\n", 413 | " if len(alist) < 2:\n", 414 | " return alic st\n", 415 | " pviot = alist[0]\n", 416 | " left = [v for v in alist[1:] if v <= pviot]\n", 417 | " right = [v for v in alist[1:] if v > pviot]\n", 418 | " left = quickSort2(left)\n", 419 | " right = quickSort2(right)\n", 420 | " return left + [pviot] + right" 421 | ] 422 | }, 423 | { 424 | "cell_type": "code", 425 | "execution_count": 138, 426 | "metadata": { 427 | "scrolled": false 428 | }, 429 | "outputs": [ 430 | { 431 | "name": "stdout", 432 | "output_type": "stream", 433 | "text": [ 434 | "0.00011630000017248676\n", 435 | "9.520000003249152e-05\n" 436 | ] 437 | } 438 | ], 439 | "source": [ 440 | "testlist1 = random.choices(range(1,100),k=10,weights=range(1,100))\n", 441 | "testlist2 = testlist1\n", 442 | "start = time.perf_counter()\n", 443 | "quickSort(testlist1,0,len(testlist1)-1)\n", 444 | "end1 = time.perf_counter()\n", 445 | "quickSort2(testlist2)\n", 446 | "end2 = time.perf_counter()\n", 447 | "print(end1-start)\n", 448 | "print(end2-end1)" 449 | ] 450 | }, 451 | { 452 | "cell_type": "code", 453 | "execution_count": 5, 454 | "metadata": {}, 455 | "outputs": [ 456 | { 457 | "name": "stdout", 458 | "output_type": "stream", 459 | "text": [ 460 | "Using matplotlib backend: Qt5Agg\n" 461 | ] 462 | }, 463 | { 464 | "name": "stderr", 465 | "output_type": "stream", 466 | "text": [ 467 | "Traceback (most recent call last):\n", 468 | " File \"D:\\Miniconda3\\envs\\datascience\\lib\\site-packages\\matplotlib\\cbook\\__init__.py\", line 216, in process\n", 469 | " func(*args, **kwargs)\n", 470 | " File \"D:\\Miniconda3\\envs\\datascience\\lib\\site-packages\\matplotlib\\animation.py\", line 957, in _start\n", 471 | " self.event_source.add_callback(self._step)\n", 472 | "AttributeError: 'NoneType' object has no attribute 'add_callback'\n" 473 | ] 474 | } 475 | ], 476 | "source": [ 477 | "import numpy as np\n", 478 | "import matplotlib.pyplot as plt\n", 479 | "import matplotlib.animation as animation\n", 480 | "\n", 481 | "\n", 482 | "def data_gen(t=0):\n", 483 | " cnt = 0\n", 484 | " while cnt < 1000:\n", 485 | " cnt += 1\n", 486 | " t += 0.1\n", 487 | " yield t, np.sin(2*np.pi*t) * np.exp(-t/10.)\n", 488 | "\n", 489 | "\n", 490 | "def init():\n", 491 | " ax.set_ylim(-1.1, 1.1)\n", 492 | " ax.set_xlim(0, 10)\n", 493 | " del xdata[:]\n", 494 | " del ydata[:]\n", 495 | " line.set_data(xdata, ydata)\n", 496 | " return line,\n", 497 | "\n", 498 | "fig, ax = plt.subplots()\n", 499 | "line, = ax.plot([], [], lw=2)\n", 500 | "ax.grid()\n", 501 | "xdata, ydata = [], []\n", 502 | "\n", 503 | "\n", 504 | "def run(data):\n", 505 | " # update the data\n", 506 | " t, y = data\n", 507 | " xdata.append(t)\n", 508 | " ydata.append(y)\n", 509 | " xmin, xmax = ax.get_xlim()\n", 510 | "\n", 511 | " if t >= xmax:\n", 512 | " ax.set_xlim(xmin, 2*xmax)\n", 513 | " ax.figure.canvas.draw()\n", 514 | " line.set_data(xdata, ydata)\n", 515 | "\n", 516 | " return line,\n", 517 | "\n", 518 | "ani = animation.FuncAnimation(fig, run, data_gen, blit=False, interval=10,\n", 519 | " repeat=False, init_func=init)\n", 520 | "plt.show()" 521 | ] 522 | }, 523 | { 524 | "cell_type": "code", 525 | "execution_count": 129, 526 | "metadata": {}, 527 | "outputs": [ 528 | { 529 | "data": { 530 | "text/plain": [ 531 | "61.921875" 532 | ] 533 | }, 534 | "execution_count": 129, 535 | "metadata": {}, 536 | "output_type": "execute_result" 537 | } 538 | ], 539 | "source": [ 540 | "end1" 541 | ] 542 | }, 543 | { 544 | "cell_type": "code", 545 | "execution_count": null, 546 | "metadata": {}, 547 | "outputs": [], 548 | "source": [] 549 | } 550 | ], 551 | "metadata": { 552 | "kernelspec": { 553 | "display_name": "Python 3", 554 | "language": "python", 555 | "name": "python3" 556 | }, 557 | "language_info": { 558 | "codemirror_mode": { 559 | "name": "ipython", 560 | "version": 3 561 | }, 562 | "file_extension": ".py", 563 | "mimetype": "text/x-python", 564 | "name": "python", 565 | "nbconvert_exporter": "python", 566 | "pygments_lexer": "ipython3", 567 | "version": "3.7.5" 568 | } 569 | }, 570 | "nbformat": 4, 571 | "nbformat_minor": 2 572 | } 573 | -------------------------------------------------------------------------------- /week6/.ipynb_checkpoints/algorithm-checkpoint.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import time\n", 10 | "import random" 11 | ] 12 | }, 13 | { 14 | "cell_type": "code", 15 | "execution_count": 2, 16 | "metadata": {}, 17 | "outputs": [], 18 | "source": [ 19 | "def cal_time(func):\n", 20 | " def wrapper(*args, **kw):\n", 21 | " start = time.perf_counter()\n", 22 | " func(*args, **kw)\n", 23 | " end = time.perf_counter()\n", 24 | " print(\"runs %s for %f second\" % (func.__name__, end-start))\n", 25 | " return wrapper" 26 | ] 27 | }, 28 | { 29 | "cell_type": "code", 30 | "execution_count": 3, 31 | "metadata": {}, 32 | "outputs": [], 33 | "source": [ 34 | "# 判断列表是否有序\n", 35 | "def sequenceList(li):\n", 36 | " for i in range(len(li)-1):\n", 37 | " if li[i] > li[i+1]:\n", 38 | " print(\"the list is not ordered\")\n", 39 | " return\n", 40 | " print(\"the list is ordered\")" 41 | ] 42 | }, 43 | { 44 | "cell_type": "markdown", 45 | "metadata": {}, 46 | "source": [ 47 | "## 二分查找" 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": 72, 53 | "metadata": {}, 54 | "outputs": [], 55 | "source": [ 56 | "@cal_time\n", 57 | "def binSearch(li, value):\n", 58 | " low = 0\n", 59 | " high = len(li)-1\n", 60 | " while low <= high:\n", 61 | " mid = (high + low) // 2\n", 62 | " if li[mid] == value:\n", 63 | " return mid\n", 64 | " elif value < li[mid]:\n", 65 | " high = mid - 1\n", 66 | " else:\n", 67 | " low = mid + 1\n", 68 | " return -1" 69 | ] 70 | }, 71 | { 72 | "cell_type": "code", 73 | "execution_count": 91, 74 | "metadata": {}, 75 | "outputs": [ 76 | { 77 | "name": "stdout", 78 | "output_type": "stream", 79 | "text": [ 80 | "the situation is 19958\n", 81 | "runs binSearch for 0.000012 second\n" 82 | ] 83 | } 84 | ], 85 | "source": [ 86 | "x = list(range(0,100000))\n", 87 | "key = random.choice(x)\n", 88 | "binSearch(x, key)" 89 | ] 90 | }, 91 | { 92 | "cell_type": "markdown", 93 | "metadata": {}, 94 | "source": [ 95 | "## 顺序查找" 96 | ] 97 | }, 98 | { 99 | "cell_type": "code", 100 | "execution_count": 86, 101 | "metadata": {}, 102 | "outputs": [], 103 | "source": [ 104 | "@cal_time\n", 105 | "def sequentialSearch(li, value):\n", 106 | " pos = 0\n", 107 | " while pos < len(li):\n", 108 | " if li[pos] == value:\n", 109 | " return pos\n", 110 | " pos += 1\n", 111 | " return -1 " 112 | ] 113 | }, 114 | { 115 | "cell_type": "code", 116 | "execution_count": 93, 117 | "metadata": {}, 118 | "outputs": [ 119 | { 120 | "name": "stdout", 121 | "output_type": "stream", 122 | "text": [ 123 | "the situation is 19958\n", 124 | "runs sequentialSearch for 0.005913 second\n" 125 | ] 126 | } 127 | ], 128 | "source": [ 129 | "sequentialSearch(x, key)" 130 | ] 131 | }, 132 | { 133 | "cell_type": "markdown", 134 | "metadata": {}, 135 | "source": [ 136 | "## 冒泡排序" 137 | ] 138 | }, 139 | { 140 | "cell_type": "code", 141 | "execution_count": 4, 142 | "metadata": {}, 143 | "outputs": [], 144 | "source": [ 145 | "@cal_time\n", 146 | "def bubbleSort(li):\n", 147 | " pos = 0\n", 148 | " amount = len(li)\n", 149 | " for i in range(amount-1):\n", 150 | " cycle = False\n", 151 | " for j in range(amount-i-1):\n", 152 | " if li[j] > li[j+1]:\n", 153 | " li[j], li[j+1] = li[j+1], li[j]\n", 154 | " cycle= True\n", 155 | " if not cycle:\n", 156 | " break" 157 | ] 158 | }, 159 | { 160 | "cell_type": "code", 161 | "execution_count": 8, 162 | "metadata": {}, 163 | "outputs": [ 164 | { 165 | "name": "stdout", 166 | "output_type": "stream", 167 | "text": [ 168 | "runs bubbleSort for 17.740258 second\n" 169 | ] 170 | } 171 | ], 172 | "source": [ 173 | "li = random.choices(range(1,100000), k=10000)\n", 174 | "bubbleSort(li)" 175 | ] 176 | }, 177 | { 178 | "cell_type": "markdown", 179 | "metadata": {}, 180 | "source": [ 181 | "## 选择排序" 182 | ] 183 | }, 184 | { 185 | "cell_type": "code", 186 | "execution_count": 20, 187 | "metadata": {}, 188 | "outputs": [], 189 | "source": [ 190 | "@cal_time\n", 191 | "def selectSort(li):\n", 192 | " for i in range(len(li)):\n", 193 | " exchange = False\n", 194 | " for j in range(i+1, len(li)):\n", 195 | " if li[j] < li[i]:\n", 196 | " li[i], li[j] = li[j], li[i]\n", 197 | " exhange = True\n", 198 | " if not exhange:\n", 199 | " break" 200 | ] 201 | }, 202 | { 203 | "cell_type": "code", 204 | "execution_count": 21, 205 | "metadata": {}, 206 | "outputs": [ 207 | { 208 | "name": "stdout", 209 | "output_type": "stream", 210 | "text": [ 211 | "runs selectSort for 8.556294 second\n" 212 | ] 213 | } 214 | ], 215 | "source": [ 216 | "li = random.choices(range(1,100000), k=10000)\n", 217 | "selectSort(li)" 218 | ] 219 | }, 220 | { 221 | "cell_type": "code", 222 | "execution_count": 68, 223 | "metadata": {}, 224 | "outputs": [], 225 | "source": [ 226 | "@cal_time\n", 227 | "def selectSort2(li):\n", 228 | " for i in range(len(li)):\n", 229 | " min_pos = i\n", 230 | " exchange = False\n", 231 | " for j in range(i+1, len(li)):\n", 232 | " if li[j] < li[i]:\n", 233 | " min_pos = j\n", 234 | " exchange = True\n", 235 | " if not exchange:\n", 236 | " break\n", 237 | " li[i], li[min_pos] = li[min_pos], li[i]" 238 | ] 239 | }, 240 | { 241 | "cell_type": "code", 242 | "execution_count": 69, 243 | "metadata": {}, 244 | "outputs": [ 245 | { 246 | "name": "stdout", 247 | "output_type": "stream", 248 | "text": [ 249 | "runs selectSort2 for 4.063522 second\n" 250 | ] 251 | } 252 | ], 253 | "source": [ 254 | "li = random.choices(range(1,100000), k=10000)\n", 255 | "selectSort2(li)" 256 | ] 257 | }, 258 | { 259 | "cell_type": "markdown", 260 | "metadata": {}, 261 | "source": [ 262 | "## 插入排序" 263 | ] 264 | }, 265 | { 266 | "cell_type": "code", 267 | "execution_count": 76, 268 | "metadata": {}, 269 | "outputs": [], 270 | "source": [ 271 | "@cal_time\n", 272 | "def insertSort(li):\n", 273 | " for i in range(len(li)-1):\n", 274 | " exhange = True\n", 275 | " while i >= 0 and exhange:\n", 276 | " if li[i+1] < li[i]:\n", 277 | " li[i],li[i+1] = li[i+1],li[i]\n", 278 | " else:\n", 279 | " exhange = False\n", 280 | " i -= 1\n", 281 | "\n", 282 | "@cal_time\n", 283 | "def insertSort2(li):\n", 284 | " for i in range(1, len(li)):\n", 285 | " tmp = li[i] # 当前位置\n", 286 | " j = i - 1\n", 287 | " while j >= 0 and li[j] > tmp:\n", 288 | " li[j+1] = li[j]\n", 289 | " j -= 1\n", 290 | " li[j+1] = tmp" 291 | ] 292 | }, 293 | { 294 | "cell_type": "code", 295 | "execution_count": null, 296 | "metadata": {}, 297 | "outputs": [], 298 | "source": [ 299 | "li = random.choices(range(1,100000), k=100000)\n", 300 | "insertSort(li)\n", 301 | "li = random.choices(range(1,100000), k=100000)\n", 302 | "insertSort2(li)" 303 | ] 304 | }, 305 | { 306 | "cell_type": "code", 307 | "execution_count": 64, 308 | "metadata": {}, 309 | "outputs": [ 310 | { 311 | "name": "stdout", 312 | "output_type": "stream", 313 | "text": [ 314 | "the list is ordered\n" 315 | ] 316 | } 317 | ], 318 | "source": [ 319 | "sequenceList(li)" 320 | ] 321 | }, 322 | { 323 | "cell_type": "markdown", 324 | "metadata": {}, 325 | "source": [ 326 | "## 快速排序算法" 327 | ] 328 | }, 329 | { 330 | "cell_type": "code", 331 | "execution_count": 12, 332 | "metadata": {}, 333 | "outputs": [], 334 | "source": [ 335 | "@cal_time\n", 336 | "def quickSort(li):\n", 337 | " left = 0\n", 338 | " right = len(li)-1\n", 339 | " def _quickSort(li, left, right):\n", 340 | " if left < right:\n", 341 | " mid = partition(li, left, right)\n", 342 | " _quickSort(li, left, mid-1)\n", 343 | " _quickSort(li, mid+1, right)\n", 344 | " _quickSort(li, left, right)\n", 345 | "\n", 346 | "def partition(li, left, right):\n", 347 | " tmp = li[left]\n", 348 | " while left < right:\n", 349 | " while left < right and li[right] > tmp:\n", 350 | " right -= 1\n", 351 | " li[left] = li[right]\n", 352 | " while left < right and li[left] <= tmp:\n", 353 | " left += 1\n", 354 | " li[right] = li[left]\n", 355 | " li[left] = tmp\n", 356 | " return left\n", 357 | "\n" 358 | ] 359 | }, 360 | { 361 | "cell_type": "code", 362 | "execution_count": 13, 363 | "metadata": {}, 364 | "outputs": [ 365 | { 366 | "name": "stdout", 367 | "output_type": "stream", 368 | "text": [ 369 | "runs quickSort for 0.426368 second\n" 370 | ] 371 | } 372 | ], 373 | "source": [ 374 | "li = random.choices(range(1,100000), k=100000)\n", 375 | "quickSort(li)" 376 | ] 377 | }, 378 | { 379 | "cell_type": "markdown", 380 | "metadata": {}, 381 | "source": [ 382 | "## 堆排序" 383 | ] 384 | }, 385 | { 386 | "cell_type": "code", 387 | "execution_count": 10, 388 | "metadata": {}, 389 | "outputs": [], 390 | "source": [ 391 | "# 构建堆\n", 392 | "def sift(li, low, high):\n", 393 | " tmp = li[low]\n", 394 | " i = low\n", 395 | " j = 2 * i + 1\n", 396 | " while j <= high: # 退出的第一种情况\n", 397 | " if j + 1 <= high and li[j] < li[j+1]: # 如果右孩子存在并且比左孩子大, 右孩子\n", 398 | " j += 1\n", 399 | " if li[j] > tmp:\n", 400 | " li[i] = li[j]\n", 401 | " i = j\n", 402 | " j = 2 * i + 1\n", 403 | " else:\n", 404 | " break # 推出的第二种情况\n", 405 | " li[i] = tmp\n", 406 | "\n", 407 | "@cal_time\n", 408 | "def heapSort(li):\n", 409 | " n = len(li)\n", 410 | " # 构造堆\n", 411 | " for low in range(n//2-1,-1,-1):\n", 412 | " sift(li, low, n-1)\n", 413 | " # 2. 挨个出数\n", 414 | " for high in range(n-1, -1, -1):\n", 415 | " li[0], li[high] = li[high], li[0]\n", 416 | " sift(li, 0, high-1)" 417 | ] 418 | }, 419 | { 420 | "cell_type": "code", 421 | "execution_count": 11, 422 | "metadata": {}, 423 | "outputs": [ 424 | { 425 | "name": "stdout", 426 | "output_type": "stream", 427 | "text": [ 428 | "runs heapSort for 0.323002 second\n" 429 | ] 430 | } 431 | ], 432 | "source": [ 433 | "li = random.choices(range(1,100000), k=100000)\n", 434 | "heapSort(li)" 435 | ] 436 | }, 437 | { 438 | "cell_type": "code", 439 | "execution_count": 88, 440 | "metadata": {}, 441 | "outputs": [], 442 | "source": [ 443 | "# 大顶堆\n", 444 | "def sift(li, low, high):\n", 445 | " tmp = li[low]\n", 446 | " i = low\n", 447 | " j = 2 * i + 1\n", 448 | " while j <= high:\n", 449 | " if j + 1 <= high and li[j+1] > li[j]:\n", 450 | " j += 1\n", 451 | " if li[j] > tmp:\n", 452 | " li[i] = li[j]\n", 453 | " i = j\n", 454 | " j = 2 * i + 1\n", 455 | " else:\n", 456 | " break\n", 457 | " li[i] = tmp\n", 458 | " \n", 459 | "def heapSort(li):\n", 460 | " n = len(li)\n", 461 | " # 构造堆\n", 462 | " for low in range(n//2-1, -1, -1):\n", 463 | " sift(li, low, n-1)\n", 464 | " # 挨个出数\n", 465 | " for high in range(n-1, -1, -1):\n", 466 | " li[0],li[high] = li[high], li[0]\n", 467 | " sift(li, 0, high-1)\n", 468 | "\n", 469 | "# 移除最大元素\n", 470 | "def removeMix(li):\n", 471 | " n = len(li)\n", 472 | " newLi = []\n", 473 | " for low in range(n//2-1, -1, -1):\n", 474 | " sift(li, low, n-1)\n", 475 | " return li[0]\n", 476 | "\n", 477 | "# 添加一个元素\n", 478 | "def addNumber(li, x):\n", 479 | " li.append(x)\n", 480 | " for low in range(n//2-1, -1, -1):\n", 481 | " sift(li, low, n-1)\n", 482 | " for high in range(n-1, -1, -1):\n", 483 | " li[0],li[high] = li[high], li[0]\n", 484 | " sift(li, 0, high-1)\n" 485 | ] 486 | }, 487 | { 488 | "cell_type": "code", 489 | "execution_count": 83, 490 | "metadata": {}, 491 | "outputs": [], 492 | "source": [ 493 | "# 构建小顶堆\n", 494 | "def sift(li, low, high):\n", 495 | " tmp = li[low]\n", 496 | " i = low\n", 497 | " j = 2 * i + 1\n", 498 | " while j <= high:\n", 499 | " if j + 1 <= high and li[j+1] < li[j]:\n", 500 | " j += 1\n", 501 | " if li[j] < tmp:\n", 502 | " li[i] = li[j]\n", 503 | " i = j\n", 504 | " j = j * 2 + 1\n", 505 | " else:\n", 506 | " break\n", 507 | " li[i] = tmp\n", 508 | "\n", 509 | "def heapSort(li):\n", 510 | " n = len(li)\n", 511 | " for low in range(n//2-1,-1,-1):\n", 512 | " sift(li, low, n-1)\n", 513 | "# 这样排出来是倒叙\n", 514 | "# for high in range(n-1, -1, -1):\n", 515 | "# li[0],li[high] = li[high],li[0]\n", 516 | "# sift(li,0,high-1)\n", 517 | "# 正序排列\n", 518 | " liDou = []\n", 519 | " for high in range(0, n, -1):\n", 520 | " liDou.append(li[0])\n", 521 | " li[0],li[n-high-1] = li[n-1-high],li[0]\n", 522 | " sift(li, 0, n-high-2)\n", 523 | " return liDou" 524 | ] 525 | }, 526 | { 527 | "cell_type": "code", 528 | "execution_count": 89, 529 | "metadata": { 530 | "scrolled": true 531 | }, 532 | "outputs": [ 533 | { 534 | "data": { 535 | "text/plain": [ 536 | "[3, 0, 4, 1, 2, 0, 1, 0, 0]" 537 | ] 538 | }, 539 | "execution_count": 89, 540 | "metadata": {}, 541 | "output_type": "execute_result" 542 | } 543 | ], 544 | "source": [ 545 | "x = list(range(10))\n", 546 | "random.shuffle(x)\n", 547 | "removeMix(x)" 548 | ] 549 | }, 550 | { 551 | "cell_type": "markdown", 552 | "metadata": {}, 553 | "source": [ 554 | "## 归并排序" 555 | ] 556 | }, 557 | { 558 | "cell_type": "code", 559 | "execution_count": 24, 560 | "metadata": {}, 561 | "outputs": [], 562 | "source": [ 563 | "def merge(li, low, mid, high):\n", 564 | " # 列表两段有序,[low, mid], [mid+1, high]\n", 565 | " i = low\n", 566 | " j = mid + 1\n", 567 | " li_tmp = []\n", 568 | " while i <= mid and j <= high:\n", 569 | " if li[i] <= li[j]:\n", 570 | " li_tmp.append(li[i])\n", 571 | " i += 1\n", 572 | " else:\n", 573 | " li_tmp.append(li[j])\n", 574 | " j += 1\n", 575 | " \n", 576 | " while i <= mid:\n", 577 | " li_tmp.append(li[i])\n", 578 | " i += 1\n", 579 | " while j <= high:\n", 580 | " li_tmp.append(li[j])\n", 581 | " j += 1\n", 582 | " for i in range(low, high+1):\n", 583 | " li[i] = li_tmp[i-low]\n", 584 | "# li[low:high+1] = li_tmp\n", 585 | "\n", 586 | "@cal_time\n", 587 | "def mergeSort(li):\n", 588 | " def _mergeSort(li, low, high):\n", 589 | " if low < high:\n", 590 | " mid = (low + high) // 2\n", 591 | " _mergeSort(li, low, mid)\n", 592 | " _mergeSort(li, mid+1, high)\n", 593 | " merge(li, low, mid, high)\n", 594 | " _mergeSort(li, 0, len(li)-1)" 595 | ] 596 | }, 597 | { 598 | "cell_type": "code", 599 | "execution_count": null, 600 | "metadata": {}, 601 | "outputs": [], 602 | "source": [ 603 | "li = list(range(1000))\n", 604 | "random.shuffle(li)\n", 605 | "mergeSort(li)" 606 | ] 607 | }, 608 | { 609 | "cell_type": "markdown", 610 | "metadata": {}, 611 | "source": [ 612 | "## 希尔排序" 613 | ] 614 | }, 615 | { 616 | "cell_type": "code", 617 | "execution_count": 6, 618 | "metadata": {}, 619 | "outputs": [], 620 | "source": [ 621 | "def insertGap(li, d):\n", 622 | " for i in range(d, len(li)):\n", 623 | " tmp = li[i]\n", 624 | " j = i - d\n", 625 | " while j >= 0 and li[j] > tmp:\n", 626 | " li[j+d] = li[j]\n", 627 | " j -= d\n", 628 | " li[j+d] = tmp\n", 629 | "\n", 630 | "@cal_time \n", 631 | "def shellSort(li):\n", 632 | " d = len(li) // 2\n", 633 | " while d > 0:\n", 634 | " insertGap(li, d)\n", 635 | " d //= 2" 636 | ] 637 | }, 638 | { 639 | "cell_type": "code", 640 | "execution_count": 12, 641 | "metadata": {}, 642 | "outputs": [ 643 | { 644 | "name": "stdout", 645 | "output_type": "stream", 646 | "text": [ 647 | "runs shellSort for 18.845328 second\n" 648 | ] 649 | } 650 | ], 651 | "source": [ 652 | "li = list(range(1000))\n", 653 | "random.shuffle(li)\n", 654 | "shellSort(li)" 655 | ] 656 | }, 657 | { 658 | "cell_type": "markdown", 659 | "metadata": {}, 660 | "source": [ 661 | "## 计数排序" 662 | ] 663 | }, 664 | { 665 | "cell_type": "code", 666 | "execution_count": 14, 667 | "metadata": {}, 668 | "outputs": [], 669 | "source": [ 670 | "@cal_time\n", 671 | "def countSort(li, max_num=100):\n", 672 | " count = [0 for _ in range(max_num+1)]\n", 673 | " for val in li:\n", 674 | " count[val] += 1\n", 675 | " li.clear()\n", 676 | " for i, v in enumerate(count):\n", 677 | " for _ in range(v):\n", 678 | " li.append(i)" 679 | ] 680 | }, 681 | { 682 | "cell_type": "code", 683 | "execution_count": 17, 684 | "metadata": {}, 685 | "outputs": [ 686 | { 687 | "name": "stdout", 688 | "output_type": "stream", 689 | "text": [ 690 | "runs countSort for 0.000141 second\n" 691 | ] 692 | } 693 | ], 694 | "source": [ 695 | "li = list(range(100))\n", 696 | "countSort(li)" 697 | ] 698 | }, 699 | { 700 | "cell_type": "markdown", 701 | "metadata": {}, 702 | "source": [ 703 | "## 基数排序" 704 | ] 705 | }, 706 | { 707 | "cell_type": "code", 708 | "execution_count": 7, 709 | "metadata": {}, 710 | "outputs": [ 711 | { 712 | "name": "stdout", 713 | "output_type": "stream", 714 | "text": [ 715 | "5\n" 716 | ] 717 | } 718 | ], 719 | "source": [ 720 | "# 选取某一位上的数字\n", 721 | "def getDigit(number, i):\n", 722 | " return number // (10 ** i) % 10\n", 723 | "\n", 724 | "print(getDigit(156,1))\n", 725 | "\n", 726 | "def bucketSort(li):\n", 727 | " maxnumber = max(li)\n", 728 | " i = 0\n", 729 | " while(10 ** i <= maxnumber):\n", 730 | " buckets = [[] for _ in range(10)]\n", 731 | " for number in li:\n", 732 | " serial = getDigit(number, i)\n", 733 | " buckets[serial].append(number)\n", 734 | " \n", 735 | " li.clear()\n", 736 | " for bucket in buckets:\n", 737 | " li.append(bucket)\n", 738 | " i += 1" 739 | ] 740 | } 741 | ], 742 | "metadata": { 743 | "kernelspec": { 744 | "display_name": "Python 3", 745 | "language": "python", 746 | "name": "python3" 747 | }, 748 | "language_info": { 749 | "codemirror_mode": { 750 | "name": "ipython", 751 | "version": 3 752 | }, 753 | "file_extension": ".py", 754 | "mimetype": "text/x-python", 755 | "name": "python", 756 | "nbconvert_exporter": "python", 757 | "pygments_lexer": "ipython3", 758 | "version": "3.7.5" 759 | } 760 | }, 761 | "nbformat": 4, 762 | "nbformat_minor": 2 763 | } 764 | -------------------------------------------------------------------------------- /week6/algorithm.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 14, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import time\n", 10 | "import random" 11 | ] 12 | }, 13 | { 14 | "cell_type": "code", 15 | "execution_count": 11, 16 | "metadata": {}, 17 | "outputs": [], 18 | "source": [ 19 | "def cal_time(func):\n", 20 | " def wrapper(*args, **kw):\n", 21 | " start = time.perf_counter()\n", 22 | " func(*args, **kw)\n", 23 | " end = time.perf_counter()\n", 24 | " print(\"runs %s for %f second\" % (func.__name__, end-start))\n", 25 | " return wrapper" 26 | ] 27 | }, 28 | { 29 | "cell_type": "code", 30 | "execution_count": 3, 31 | "metadata": {}, 32 | "outputs": [], 33 | "source": [ 34 | "# 判断列表是否有序\n", 35 | "def sequenceList(li):\n", 36 | " for i in range(len(li)-1):\n", 37 | " if li[i] > li[i+1]:\n", 38 | " print(\"the list is not ordered\")\n", 39 | " return\n", 40 | " print(\"the list is ordered\")" 41 | ] 42 | }, 43 | { 44 | "cell_type": "markdown", 45 | "metadata": {}, 46 | "source": [ 47 | "## 二分查找" 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": 72, 53 | "metadata": {}, 54 | "outputs": [], 55 | "source": [ 56 | "@cal_time\n", 57 | "def binSearch(li, value):\n", 58 | " low = 0\n", 59 | " high = len(li)-1\n", 60 | " while low <= high:\n", 61 | " mid = (high + low) // 2\n", 62 | " if li[mid] == value:\n", 63 | " return mid\n", 64 | " elif value < li[mid]:\n", 65 | " high = mid - 1\n", 66 | " else:\n", 67 | " low = mid + 1\n", 68 | " return -1" 69 | ] 70 | }, 71 | { 72 | "cell_type": "code", 73 | "execution_count": 91, 74 | "metadata": {}, 75 | "outputs": [ 76 | { 77 | "name": "stdout", 78 | "output_type": "stream", 79 | "text": [ 80 | "the situation is 19958\n", 81 | "runs binSearch for 0.000012 second\n" 82 | ] 83 | } 84 | ], 85 | "source": [ 86 | "x = list(range(0,100000))\n", 87 | "key = random.choice(x)\n", 88 | "binSearch(x, key)" 89 | ] 90 | }, 91 | { 92 | "cell_type": "markdown", 93 | "metadata": {}, 94 | "source": [ 95 | "## 顺序查找" 96 | ] 97 | }, 98 | { 99 | "cell_type": "code", 100 | "execution_count": 86, 101 | "metadata": {}, 102 | "outputs": [], 103 | "source": [ 104 | "@cal_time\n", 105 | "def sequentialSearch(li, value):\n", 106 | " pos = 0\n", 107 | " while pos < len(li):\n", 108 | " if li[pos] == value:\n", 109 | " return pos\n", 110 | " pos += 1\n", 111 | " return -1 " 112 | ] 113 | }, 114 | { 115 | "cell_type": "code", 116 | "execution_count": 93, 117 | "metadata": {}, 118 | "outputs": [ 119 | { 120 | "name": "stdout", 121 | "output_type": "stream", 122 | "text": [ 123 | "the situation is 19958\n", 124 | "runs sequentialSearch for 0.005913 second\n" 125 | ] 126 | } 127 | ], 128 | "source": [ 129 | "sequentialSearch(x, key)" 130 | ] 131 | }, 132 | { 133 | "cell_type": "markdown", 134 | "metadata": {}, 135 | "source": [ 136 | "## 冒泡排序" 137 | ] 138 | }, 139 | { 140 | "cell_type": "code", 141 | "execution_count": 4, 142 | "metadata": {}, 143 | "outputs": [], 144 | "source": [ 145 | "@cal_time\n", 146 | "def bubbleSort(li):\n", 147 | " pos = 0\n", 148 | " amount = len(li)\n", 149 | " for i in range(amount-1):\n", 150 | " cycle = False\n", 151 | " for j in range(amount-i-1):\n", 152 | " if li[j] > li[j+1]:\n", 153 | " li[j], li[j+1] = li[j+1], li[j]\n", 154 | " cycle= True\n", 155 | " if not cycle:\n", 156 | " break" 157 | ] 158 | }, 159 | { 160 | "cell_type": "code", 161 | "execution_count": 8, 162 | "metadata": {}, 163 | "outputs": [ 164 | { 165 | "name": "stdout", 166 | "output_type": "stream", 167 | "text": [ 168 | "runs bubbleSort for 17.740258 second\n" 169 | ] 170 | } 171 | ], 172 | "source": [ 173 | "li = random.choices(range(1,100000), k=10000)\n", 174 | "bubbleSort(li)" 175 | ] 176 | }, 177 | { 178 | "cell_type": "markdown", 179 | "metadata": {}, 180 | "source": [ 181 | "## 选择排序" 182 | ] 183 | }, 184 | { 185 | "cell_type": "code", 186 | "execution_count": 20, 187 | "metadata": {}, 188 | "outputs": [], 189 | "source": [ 190 | "@cal_time\n", 191 | "def selectSort(li):\n", 192 | " for i in range(len(li)):\n", 193 | " exchange = False\n", 194 | " for j in range(i+1, len(li)):\n", 195 | " if li[j] < li[i]:\n", 196 | " li[i], li[j] = li[j], li[i]\n", 197 | " exhange = True\n", 198 | " if not exhange:\n", 199 | " break" 200 | ] 201 | }, 202 | { 203 | "cell_type": "code", 204 | "execution_count": 21, 205 | "metadata": {}, 206 | "outputs": [ 207 | { 208 | "name": "stdout", 209 | "output_type": "stream", 210 | "text": [ 211 | "runs selectSort for 8.556294 second\n" 212 | ] 213 | } 214 | ], 215 | "source": [ 216 | "li = random.choices(range(1,100000), k=10000)\n", 217 | "selectSort(li)" 218 | ] 219 | }, 220 | { 221 | "cell_type": "code", 222 | "execution_count": 68, 223 | "metadata": {}, 224 | "outputs": [], 225 | "source": [ 226 | "@cal_time\n", 227 | "def selectSort2(li):\n", 228 | " for i in range(len(li)):\n", 229 | " min_pos = i\n", 230 | " exchange = False\n", 231 | " for j in range(i+1, len(li)):\n", 232 | " if li[j] < li[i]:\n", 233 | " min_pos = j\n", 234 | " exchange = True\n", 235 | " if not exchange:\n", 236 | " break\n", 237 | " li[i], li[min_pos] = li[min_pos], li[i]" 238 | ] 239 | }, 240 | { 241 | "cell_type": "code", 242 | "execution_count": 69, 243 | "metadata": {}, 244 | "outputs": [ 245 | { 246 | "name": "stdout", 247 | "output_type": "stream", 248 | "text": [ 249 | "runs selectSort2 for 4.063522 second\n" 250 | ] 251 | } 252 | ], 253 | "source": [ 254 | "li = random.choices(range(1,100000), k=10000)\n", 255 | "selectSort2(li)" 256 | ] 257 | }, 258 | { 259 | "cell_type": "markdown", 260 | "metadata": {}, 261 | "source": [ 262 | "## 插入排序" 263 | ] 264 | }, 265 | { 266 | "cell_type": "code", 267 | "execution_count": 76, 268 | "metadata": {}, 269 | "outputs": [], 270 | "source": [ 271 | "@cal_time\n", 272 | "def insertSort(li):\n", 273 | " for i in range(len(li)-1):\n", 274 | " exhange = True\n", 275 | " while i >= 0 and exhange:\n", 276 | " if li[i+1] < li[i]:\n", 277 | " li[i],li[i+1] = li[i+1],li[i]\n", 278 | " else:\n", 279 | " exhange = False\n", 280 | " i -= 1\n", 281 | "\n", 282 | "@cal_time\n", 283 | "def insertSort2(li):\n", 284 | " for i in range(1, len(li)):\n", 285 | " tmp = li[i] # 当前位置\n", 286 | " j = i - 1\n", 287 | " while j >= 0 and li[j] > tmp:\n", 288 | " li[j+1] = li[j]\n", 289 | " j -= 1\n", 290 | " li[j+1] = tmp" 291 | ] 292 | }, 293 | { 294 | "cell_type": "code", 295 | "execution_count": null, 296 | "metadata": {}, 297 | "outputs": [], 298 | "source": [ 299 | "li = random.choices(range(1,100000), k=100000)\n", 300 | "insertSort(li)\n", 301 | "li = random.choices(range(1,100000), k=100000)\n", 302 | "insertSort2(li)" 303 | ] 304 | }, 305 | { 306 | "cell_type": "code", 307 | "execution_count": 64, 308 | "metadata": {}, 309 | "outputs": [ 310 | { 311 | "name": "stdout", 312 | "output_type": "stream", 313 | "text": [ 314 | "the list is ordered\n" 315 | ] 316 | } 317 | ], 318 | "source": [ 319 | "sequenceList(li)" 320 | ] 321 | }, 322 | { 323 | "cell_type": "markdown", 324 | "metadata": {}, 325 | "source": [ 326 | "## 快速排序算法" 327 | ] 328 | }, 329 | { 330 | "cell_type": "code", 331 | "execution_count": 12, 332 | "metadata": {}, 333 | "outputs": [], 334 | "source": [ 335 | "@cal_time\n", 336 | "def quickSort(li):\n", 337 | " left = 0\n", 338 | " right = len(li)-1\n", 339 | " def _quickSort(li, left, right):\n", 340 | " if left < right:\n", 341 | " mid = partition(li, left, right)\n", 342 | " _quickSort(li, left, mid-1)\n", 343 | " _quickSort(li, mid+1, right)\n", 344 | " _quickSort(li, left, right)\n", 345 | "\n", 346 | "def partition(li, left, right):\n", 347 | " tmp = li[left]\n", 348 | " while left < right:\n", 349 | " while left < right and li[right] > tmp:\n", 350 | " right -= 1\n", 351 | " li[left] = li[right]\n", 352 | " while left < right and li[left] <= tmp:\n", 353 | " left += 1\n", 354 | " li[right] = li[left]\n", 355 | " li[left] = tmp\n", 356 | " return left\n", 357 | "\n" 358 | ] 359 | }, 360 | { 361 | "cell_type": "code", 362 | "execution_count": 13, 363 | "metadata": {}, 364 | "outputs": [ 365 | { 366 | "name": "stdout", 367 | "output_type": "stream", 368 | "text": [ 369 | "runs quickSort for 0.426368 second\n" 370 | ] 371 | } 372 | ], 373 | "source": [ 374 | "li = random.choices(range(1,100000), k=100000)\n", 375 | "quickSort(li)" 376 | ] 377 | }, 378 | { 379 | "cell_type": "markdown", 380 | "metadata": {}, 381 | "source": [ 382 | "## 堆排序" 383 | ] 384 | }, 385 | { 386 | "cell_type": "code", 387 | "execution_count": 10, 388 | "metadata": {}, 389 | "outputs": [], 390 | "source": [ 391 | "# 构建堆\n", 392 | "def sift(li, low, high):\n", 393 | " tmp = li[low]\n", 394 | " i = low\n", 395 | " j = 2 * i + 1\n", 396 | " while j <= high: # 退出的第一种情况\n", 397 | " if j + 1 <= high and li[j] < li[j+1]: # 如果右孩子存在并且比左孩子大, 右孩子\n", 398 | " j += 1\n", 399 | " if li[j] > tmp:\n", 400 | " li[i] = li[j]\n", 401 | " i = j\n", 402 | " j = 2 * i + 1\n", 403 | " else:\n", 404 | " break # 推出的第二种情况\n", 405 | " li[i] = tmp\n", 406 | "\n", 407 | "@cal_time\n", 408 | "def heapSort(li):\n", 409 | " n = len(li)\n", 410 | " # 构造堆\n", 411 | " for low in range(n//2-1,-1,-1):\n", 412 | " sift(li, low, n-1)\n", 413 | " # 2. 挨个出数\n", 414 | " for high in range(n-1, -1, -1):\n", 415 | " li[0], li[high] = li[high], li[0]\n", 416 | " sift(li, 0, high-1)" 417 | ] 418 | }, 419 | { 420 | "cell_type": "code", 421 | "execution_count": 11, 422 | "metadata": {}, 423 | "outputs": [ 424 | { 425 | "name": "stdout", 426 | "output_type": "stream", 427 | "text": [ 428 | "runs heapSort for 0.323002 second\n" 429 | ] 430 | } 431 | ], 432 | "source": [ 433 | "li = random.choices(range(1,100000), k=100000)\n", 434 | "heapSort(li)" 435 | ] 436 | }, 437 | { 438 | "cell_type": "code", 439 | "execution_count": 88, 440 | "metadata": {}, 441 | "outputs": [], 442 | "source": [ 443 | "# 大顶堆\n", 444 | "def sift(li, low, high):\n", 445 | " tmp = li[low]\n", 446 | " i = low\n", 447 | " j = 2 * i + 1\n", 448 | " while j <= high:\n", 449 | " if j + 1 <= high and li[j+1] > li[j]:\n", 450 | " j += 1\n", 451 | " if li[j] > tmp:\n", 452 | " li[i] = li[j]\n", 453 | " i = j\n", 454 | " j = 2 * i + 1\n", 455 | " else:\n", 456 | " break\n", 457 | " li[i] = tmp\n", 458 | " \n", 459 | "def heapSort(li):\n", 460 | " n = len(li)\n", 461 | " # 构造堆\n", 462 | " for low in range(n//2-1, -1, -1):\n", 463 | " sift(li, low, n-1)\n", 464 | " # 挨个出数\n", 465 | " for high in range(n-1, -1, -1):\n", 466 | " li[0],li[high] = li[high], li[0]\n", 467 | " sift(li, 0, high-1)\n", 468 | "\n", 469 | "# 移除最大元素\n", 470 | "def removeMix(li):\n", 471 | " n = len(li)\n", 472 | " newLi = []\n", 473 | " for low in range(n//2-1, -1, -1):\n", 474 | " sift(li, low, n-1)\n", 475 | " return li[0]\n", 476 | "\n", 477 | "# 添加一个元素\n", 478 | "def addNumber(li, x):\n", 479 | " li.append(x)\n", 480 | " for low in range(n//2-1, -1, -1):\n", 481 | " sift(li, low, n-1)\n", 482 | " for high in range(n-1, -1, -1):\n", 483 | " li[0],li[high] = li[high], li[0]\n", 484 | " sift(li, 0, high-1)\n" 485 | ] 486 | }, 487 | { 488 | "cell_type": "code", 489 | "execution_count": 83, 490 | "metadata": {}, 491 | "outputs": [], 492 | "source": [ 493 | "# 构建小顶堆\n", 494 | "def sift(li, low, high):\n", 495 | " tmp = li[low]\n", 496 | " i = low\n", 497 | " j = 2 * i + 1\n", 498 | " while j <= high:\n", 499 | " if j + 1 <= high and li[j+1] < li[j]:\n", 500 | " j += 1\n", 501 | " if li[j] < tmp:\n", 502 | " li[i] = li[j]\n", 503 | " i = j\n", 504 | " j = j * 2 + 1\n", 505 | " else:\n", 506 | " break\n", 507 | " li[i] = tmp\n", 508 | "\n", 509 | "def heapSort(li):\n", 510 | " n = len(li)\n", 511 | " for low in range(n//2-1,-1,-1):\n", 512 | " sift(li, low, n-1)\n", 513 | "# 这样排出来是倒叙\n", 514 | "# for high in range(n-1, -1, -1):\n", 515 | "# li[0],li[high] = li[high],li[0]\n", 516 | "# sift(li,0,high-1)\n", 517 | "# 正序排列\n", 518 | " liDou = []\n", 519 | " for high in range(0, n, -1):\n", 520 | " liDou.append(li[0])\n", 521 | " li[0],li[n-high-1] = li[n-1-high],li[0]\n", 522 | " sift(li, 0, n-high-2)\n", 523 | " return liDou" 524 | ] 525 | }, 526 | { 527 | "cell_type": "code", 528 | "execution_count": 89, 529 | "metadata": { 530 | "scrolled": true 531 | }, 532 | "outputs": [ 533 | { 534 | "data": { 535 | "text/plain": [ 536 | "[3, 0, 4, 1, 2, 0, 1, 0, 0]" 537 | ] 538 | }, 539 | "execution_count": 89, 540 | "metadata": {}, 541 | "output_type": "execute_result" 542 | } 543 | ], 544 | "source": [ 545 | "x = list(range(10))\n", 546 | "random.shuffle(x)\n", 547 | "removeMix(x)" 548 | ] 549 | }, 550 | { 551 | "cell_type": "markdown", 552 | "metadata": {}, 553 | "source": [ 554 | "## 归并排序" 555 | ] 556 | }, 557 | { 558 | "cell_type": "code", 559 | "execution_count": 24, 560 | "metadata": {}, 561 | "outputs": [], 562 | "source": [ 563 | "def merge(li, low, mid, high):\n", 564 | " # 列表两段有序,[low, mid], [mid+1, high]\n", 565 | " i = low\n", 566 | " j = mid + 1\n", 567 | " li_tmp = []\n", 568 | " while i <= mid and j <= high:\n", 569 | " if li[i] <= li[j]:\n", 570 | " li_tmp.append(li[i])\n", 571 | " i += 1\n", 572 | " else:\n", 573 | " li_tmp.append(li[j])\n", 574 | " j += 1\n", 575 | " \n", 576 | " while i <= mid:\n", 577 | " li_tmp.append(li[i])\n", 578 | " i += 1\n", 579 | " while j <= high:\n", 580 | " li_tmp.append(li[j])\n", 581 | " j += 1\n", 582 | " for i in range(low, high+1):\n", 583 | " li[i] = li_tmp[i-low]\n", 584 | "# li[low:high+1] = li_tmp\n", 585 | "\n", 586 | "@cal_time\n", 587 | "def mergeSort(li):\n", 588 | " def _mergeSort(li, low, high):\n", 589 | " if low < high:\n", 590 | " mid = (low + high) // 2\n", 591 | " _mergeSort(li, low, mid)\n", 592 | " _mergeSort(li, mid+1, high)\n", 593 | " merge(li, low, mid, high)\n", 594 | " _mergeSort(li, 0, len(li)-1)" 595 | ] 596 | }, 597 | { 598 | "cell_type": "code", 599 | "execution_count": null, 600 | "metadata": {}, 601 | "outputs": [], 602 | "source": [ 603 | "li = list(range(1000))\n", 604 | "random.shuffle(li)\n", 605 | "mergeSort(li)" 606 | ] 607 | }, 608 | { 609 | "cell_type": "markdown", 610 | "metadata": {}, 611 | "source": [ 612 | "## 希尔排序" 613 | ] 614 | }, 615 | { 616 | "cell_type": "code", 617 | "execution_count": 6, 618 | "metadata": {}, 619 | "outputs": [], 620 | "source": [ 621 | "def insertGap(li, d):\n", 622 | " for i in range(d, len(li)):\n", 623 | " tmp = li[i]\n", 624 | " j = i - d\n", 625 | " while j >= 0 and li[j] > tmp:\n", 626 | " li[j+d] = li[j]\n", 627 | " j -= d\n", 628 | " li[j+d] = tmp\n", 629 | "\n", 630 | "@cal_time \n", 631 | "def shellSort(li):\n", 632 | " d = len(li) // 2\n", 633 | " while d > 0:\n", 634 | " insertGap(li, d)\n", 635 | " d //= 2" 636 | ] 637 | }, 638 | { 639 | "cell_type": "code", 640 | "execution_count": 12, 641 | "metadata": {}, 642 | "outputs": [ 643 | { 644 | "name": "stdout", 645 | "output_type": "stream", 646 | "text": [ 647 | "runs shellSort for 18.845328 second\n" 648 | ] 649 | } 650 | ], 651 | "source": [ 652 | "li = list(range(1000))\n", 653 | "random.shuffle(li)\n", 654 | "shellSort(li)" 655 | ] 656 | }, 657 | { 658 | "cell_type": "markdown", 659 | "metadata": {}, 660 | "source": [ 661 | "## 计数排序" 662 | ] 663 | }, 664 | { 665 | "cell_type": "code", 666 | "execution_count": 14, 667 | "metadata": {}, 668 | "outputs": [], 669 | "source": [ 670 | "@cal_time\n", 671 | "def countSort(li, max_num=100):\n", 672 | " count = [0 for _ in range(max_num+1)]\n", 673 | " for val in li:\n", 674 | " count[val] += 1\n", 675 | " li.clear()\n", 676 | " for i, v in enumerate(count):\n", 677 | " for _ in range(v):\n", 678 | " li.append(i)" 679 | ] 680 | }, 681 | { 682 | "cell_type": "code", 683 | "execution_count": 17, 684 | "metadata": {}, 685 | "outputs": [ 686 | { 687 | "name": "stdout", 688 | "output_type": "stream", 689 | "text": [ 690 | "runs countSort for 0.000141 second\n" 691 | ] 692 | } 693 | ], 694 | "source": [ 695 | "li = list(range(100))\n", 696 | "countSort(li)" 697 | ] 698 | }, 699 | { 700 | "cell_type": "markdown", 701 | "metadata": {}, 702 | "source": [ 703 | "## 基数排序" 704 | ] 705 | }, 706 | { 707 | "cell_type": "code", 708 | "execution_count": 12, 709 | "metadata": {}, 710 | "outputs": [], 711 | "source": [ 712 | "@cal_time\n", 713 | "def bucketSort(li):\n", 714 | " maxnumber = max(li)\n", 715 | " i = 0\n", 716 | " while(10 ** i <= maxnumber):\n", 717 | " buckets = [[] for _ in range(10)]\n", 718 | " for number in li:\n", 719 | " digit = number // (10 ** i) % 10\n", 720 | " buckets[digit].append(number)\n", 721 | " \n", 722 | " li.clear()\n", 723 | " for bucket in buckets:\n", 724 | " for val in bucket:\n", 725 | " li.append(val)\n", 726 | " i += 1" 727 | ] 728 | }, 729 | { 730 | "cell_type": "code", 731 | "execution_count": 22, 732 | "metadata": {}, 733 | "outputs": [ 734 | { 735 | "name": "stdout", 736 | "output_type": "stream", 737 | "text": [ 738 | "runs bucketSort for 0.000119 second\n" 739 | ] 740 | } 741 | ], 742 | "source": [ 743 | "li = list(range(100))\n", 744 | "random.shuffle(li)\n", 745 | "bucketSort(li)" 746 | ] 747 | }, 748 | { 749 | "cell_type": "code", 750 | "execution_count": null, 751 | "metadata": {}, 752 | "outputs": [], 753 | "source": [] 754 | } 755 | ], 756 | "metadata": { 757 | "kernelspec": { 758 | "display_name": "Python 3", 759 | "language": "python", 760 | "name": "python3" 761 | }, 762 | "language_info": { 763 | "codemirror_mode": { 764 | "name": "ipython", 765 | "version": 3 766 | }, 767 | "file_extension": ".py", 768 | "mimetype": "text/x-python", 769 | "name": "python", 770 | "nbconvert_exporter": "python", 771 | "pygments_lexer": "ipython3", 772 | "version": "3.7.5" 773 | } 774 | }, 775 | "nbformat": 4, 776 | "nbformat_minor": 2 777 | } 778 | --------------------------------------------------------------------------------