├── .gitignore ├── Divede-and-conquer ├── binary_search.py ├── max2.py └── maximum_subarray.py ├── DynamicProgramming ├── EditDistance.py ├── IsInterleave.py ├── LCS.py ├── LIS.py ├── MaxProductSubstring.py ├── MinimumPathSum.py ├── Triangle.py ├── UniquePaths.py └── UniquePathsII.py ├── Graph ├── MaxFlow │ ├── maxflow.py │ └── mincostmaxflow.py └── ShortestPath │ ├── dijkstra.py │ └── floyd.py ├── Optimization └── light_24_improve.m ├── README.md └── Sorting ├── bubble_sort.py ├── insertion_sort.py ├── merge_sort.py ├── quick_sort.py ├── selection_sort.py └── shell_sort.py /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | .idea 3 | test.py -------------------------------------------------------------------------------- /Divede-and-conquer/binary_search.py: -------------------------------------------------------------------------------- 1 | def binary_search(A, x, low, high): 2 | if low == high: 3 | return -1 4 | mid = (low + high) // 2 5 | if A[mid] == x: 6 | return mid 7 | result_left = binary_search(A, x, low, mid) 8 | print("left", result_left) 9 | result_right = binary_search(A, x, mid+1, high) 10 | print("right", result_right) 11 | if result_left != -1: 12 | return result_left 13 | elif result_right != -1: 14 | return result_right 15 | else: 16 | return -1 17 | 18 | A = list(range(10)) 19 | print(binary_search(A, 3, 0, len(A)-1)) -------------------------------------------------------------------------------- /Divede-and-conquer/max2.py: -------------------------------------------------------------------------------- 1 | ''' 2 | input: an array 3 | output: the max 2 numbers in the array 4 | ''' 5 | 6 | from timeit import Timer 7 | 8 | def max2_force(A): 9 | x1 = -float('inf') 10 | x2 = -float('inf') 11 | for i in range(len(A)): 12 | if A[i] > x1: 13 | x1 = A[i] 14 | j = i 15 | for i in range(j): 16 | if A[i] > x2: 17 | x2 = A[i] 18 | for i in range(j + 1, len(A)): 19 | if A[i] > x2: 20 | x2 = A[i] 21 | return x1, x2 22 | 23 | 24 | def max2_force_improve(A): 25 | x1 = -float('inf') 26 | x2 = -float('inf') 27 | for i in range(len(A)): 28 | if A[i] > x2: 29 | x2 = A[i] 30 | if x2 > x1: 31 | x1, x2 = x2, x1 32 | return x1, x2 33 | 34 | def max2_divide_and_conquer(A, low, high): 35 | if low == high: 36 | return A[low], A[low] 37 | elif low + 1 == high: 38 | if A[low] > A[high]: 39 | return A[low], A[high] 40 | else: 41 | return A[high], A[low] 42 | else: 43 | mid = (low + high) // 2 44 | x1_left, x2_left = max2_divide_and_conquer(A, low, mid) 45 | x1_right, x2_right = max2_divide_and_conquer(A, mid + 1, high) 46 | if x1_left > x1_right: 47 | if x2_left > x1_right: 48 | return x1_left, x2_left 49 | else: 50 | return x1_left, x1_right 51 | else: 52 | if x2_right > x1_left: 53 | return x1_right, x2_right 54 | else: 55 | return x1_right, x1_left 56 | 57 | A = [5,9,9,1] 58 | print("max2_force: x1 = %s, x2 = %s" 59 | %(max2_force(A)[0], max2_force(A)[1])) 60 | 61 | print("max2_force_improve: x1 = %s, x2 = %s" 62 | %(max2_force_improve(A)[0], max2_force_improve(A)[1])) 63 | 64 | print("max2_divide_and_conquer: x1 = %s, x2 = %s" 65 | %(max2_divide_and_conquer(A, 0, len(A)-1)[0], max2_divide_and_conquer(A, 0, len(A)-1)[1])) 66 | 67 | print("---------test speed--------") 68 | 69 | t1 = Timer("max2_force([9,2,3,5,12,4,7,1,0])", "from __main__ import max2_force") 70 | print("max2_force(A) ", t1.timeit(number=1000), "seconds") 71 | 72 | t1 = Timer("max2_force_improve([9,2,3,5,12,4,7,1,0])", "from __main__ import max2_force_improve") 73 | print("max2_force_improve(A) ", t1.timeit(number=1000), "seconds") 74 | 75 | t1 = Timer("max2_divide_and_conquer([9,2,3,5,12,4,7,1,0], 0, len([9,2,3,5,12,4,7,1,0])-1)", 76 | "from __main__ import max2_divide_and_conquer") 77 | print("max2_divide_and_conquer(A, low, high) ", t1.timeit(number=1000), "seconds") 78 | -------------------------------------------------------------------------------- /Divede-and-conquer/maximum_subarray.py: -------------------------------------------------------------------------------- 1 | from timeit import Timer 2 | 3 | 4 | def di_cal_wrong(A): 5 | max_sub_sum = -float('inf') # init 6 | for i in range(len(A)): 7 | for j in range(i+1, len(A)): 8 | if sum(A[i:j+1]) > max_sub_sum: 9 | max_sub_sum = sum(A[i:j+1]) 10 | low = i 11 | high = j 12 | return(max_sub_sum, low, high) 13 | 14 | 15 | def di_cal(A): 16 | sum = A[0] 17 | max_sub_sum = -float('inf') # init 18 | for i in range(len(A)): 19 | sum = A[i] 20 | for j in range(i+1, len(A)): 21 | sum += A[j] 22 | if sum > max_sub_sum: 23 | max_sub_sum = sum 24 | low = i 25 | high = j 26 | return(max_sub_sum, low, high) 27 | 28 | 29 | def find_cross_suming_subarray(A, mid, low, high): 30 | # 最大子数组横跨中点,所以最大子数组的左边是A[i..mid],右边是A[mid+1..j] 31 | # 求出某边的最大子数组可以直接用暴力求解法,暴力运行时间是 n ,分治操作是 logn ,所以这种方法能实现 O(nlogn) 32 | left_sum, right_sum = 0, 0 33 | max_left_sum, max_right_sum = -float('inf'), -float('inf') 34 | # 注意 range(start,stop,step),包括start,不包括stop,所以对应的low-1与high+1 35 | for i in range(mid, low-1, -1): 36 | left_sum += A[i] 37 | if left_sum > max_left_sum: 38 | max_left_sum = left_sum 39 | low = i 40 | for j in range(mid+1, high+1, 1): 41 | right_sum += A[j] 42 | if right_sum > max_right_sum: 43 | max_right_sum = right_sum 44 | high = j 45 | return max_right_sum+max_left_sum, low, high 46 | 47 | 48 | def divide_and_conquer(A, low, high): 49 | if low == high: 50 | return A[low], low, high 51 | mid = (low + high) // 2 52 | left_sum, left_low, left_high = divide_and_conquer(A, low, mid) 53 | print("left:", left_sum, left_low, left_high) 54 | right_sum, right_low, right_high = divide_and_conquer(A, mid+1, high) 55 | print("right:", right_sum, right_low, right_high) 56 | cross_sum, cross_low, cross_high = find_cross_suming_subarray(A, mid, low, high) 57 | print("cross:", cross_sum, cross_low, cross_high) 58 | if left_sum > right_sum and left_sum > cross_sum: 59 | return left_sum, left_low, left_high 60 | elif right_sum > left_sum and right_sum > cross_sum: 61 | return right_sum, right_low, right_high 62 | else: 63 | return cross_sum, cross_low, cross_high 64 | 65 | def dp(A): 66 | low, high = 0, 0 67 | B = list(range(len(A))) 68 | B[0] = A[0] 69 | max_sub_sum = A[0] 70 | for i in range(1, len(A)): 71 | if B[i-1] > 0: 72 | B[i] = B[i-1] + A[i] 73 | else: 74 | B[i] = A[i] 75 | low = i 76 | if B[i] > max_sub_sum: 77 | max_sub_sum = B[i] 78 | high = i 79 | return max_sub_sum, low, high 80 | 81 | def linear_time(A): 82 | sum, max_sub_sum, low, high, cur = 0, 0, 0, 0, 0 83 | for i in range(0, len(A)): 84 | sum += A[i] 85 | if sum > max_sub_sum: 86 | max_sub_sum = sum 87 | # 起点从0开始,从左往右操作 88 | low = cur 89 | high = i 90 | # 每当和小于0时,丢弃之前处理过的所有记录,最大和清0,并且起点从下一位开始 91 | if sum < 0: 92 | sum = 0 93 | cur = i + 1 94 | return max_sub_sum, low, high 95 | 96 | A = [13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7] 97 | 98 | # print(di_cal_wrong(A)) 99 | # print(di_cal(A)) 100 | # 101 | # t1 = Timer("di_cal([13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7])", "from __main__ import di_cal") 102 | # print("di_cal ", t1.timeit(number=1000), "seconds") 103 | # 104 | # t1 = Timer("di_cal_wrong([13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7])", "from __main__ import di_cal_wrong") 105 | # print("di_cal_wrong ", t1.timeit(number=1000), "seconds") 106 | # 107 | # print(divide_and_conquer(A, 0, len(A)-1)) 108 | # 109 | # print(linear_time(A)) 110 | print(dp(A)) -------------------------------------------------------------------------------- /DynamicProgramming/EditDistance.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode:72. Edit Distance 3 | 题目描述: 4 | 给定一个源串和目标串,能够对源串进行如下操作: 5 | 1. 在给定位置上插入一个字符 6 | 2. 替换任意字符 7 | 3. 删除任意字符 8 | 写一个程序,返回最小操作数,使得对源串进行这些操作后等于目标串,源串和目标串的长度都小于2000。 9 | 10 | 思路: 11 | 动态规划,构建二维数组,注意二维数组的第0行和第0列不是全0的。 12 | 可以想象,如果source 为空,想要转换为 target,则肯定要执行 len(target) = n 次操作,所以dp[i][j]赋初值时要注意这点。 13 | 14 | 递推方程: 15 | //dp[i,j]表示表示源串S[0…i] 和目标串T[0…j] 的最短编辑距离 16 | dp[i, j] = min { dp[i - 1, j] + 1, dp[i, j - 1] + 1, dp[i - 1, j - 1] + (s[i] == t[j] ? 0 : 1) } 17 | //分别表示:删除1个,添加1个,替换1个(相同就不用替换)。 18 | 19 | 解释: 20 | 插入是A在和B的前j-1个比,然后再在A的基础上进行插入一个字符,插入的字符是B的第j位,所以插入的代价是dp[i][j-1]+c0 21 | 删除是A的前i-1个和B的j个比,因为把A删除了一个字符,所以删除的代价是dp[i-1][j]+c1 22 | 替换是A的前i-1个和B的j-1个比,然后把A的第i位变成B的第j位。所以编辑的代价是dp[i-1][j-1]+c2 23 | ''' 24 | 25 | def editDistance(source, target): 26 | m = len(source) 27 | n = len(target) 28 | 29 | dp = [[0 for i in range(n+1)] for i in range(m+1)] 30 | for i in range(n+1): 31 | dp[0][i] = i 32 | for i in range(m+1): 33 | dp[i][0] = i 34 | 35 | for i in range(1, m+1): 36 | for j in range(1, n+1): 37 | if source[i-1] == target[j-1]: 38 | dp[i][j] = dp[i-1][j-1] 39 | else: 40 | dp[i][j] = min(min(dp[i][j-1], dp[i-1][j]), dp[i-1][j-1]) + 1 41 | return dp[m][n] 42 | 43 | source = "abc" 44 | target = "axxxbxxxc" 45 | print(editDistance(source, target)) -------------------------------------------------------------------------------- /DynamicProgramming/IsInterleave.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode: 97 Interleaving String 3 | 题目描述: 4 | 输入三个字符串s1、s2和s3,判断第三个字符串s3是否由前两个字符串s1和s2交错而成,即不改变s1和s2中各个字符原有的相对顺序, 5 | 例如当s1 = “aabcc”,s2 = “dbbca”,s3 = “aadbbcbcac”时,则输出true,但如果s3=“accabdbbca”,则输出false。 6 | 7 | 思路: 8 | 多个字符串做“比较”的问题,大多都可以用DP求解。 9 | 构建二维数组,令dp[i][j]代表s3[0...i+j-1]是否由s1[0...i-1]和s2[0...j-1]的字符组成。 10 | 自然,我们的想法是遍历s3中的每个元素,然而要如何找到递推关系呢? 11 | 因为只需要输出true或false,那么我们可以只计算true的情形,其余情况全是false。 12 | 假设dp[i-1][j]为true,那么dp[i][j]为true的条件就是s1[i-1]是否等于s3[i+j-1]。 13 | 假设dp[i][j-1]为true,那么dp[i][j]为true的条件就是s2[j-1]是否等于s3[i+j-1]。 14 | 由此递推关系就可以求出。 15 | ''' 16 | 17 | def isInterleave(s1, s2, s3): 18 | m = len(s1) 19 | n = len(s2) 20 | k = len(s3) 21 | if k != m + n: 22 | return False 23 | dp = [[False for i in range(n + 1)] for i in range(m + 1)] 24 | dp[0][0] = True 25 | # if s1[0] == s3[0]: 26 | # dp[1][0] = True 27 | # if s2[0] == s3[0]: 28 | # dp[0][1] = True 29 | for i in range(m+1): 30 | for j in range(n+1): 31 | if i != 0 or j != 0: 32 | if dp[i-1][j] is True and s1[i-1] == s3[i+j-1]: 33 | dp[i][j] = True 34 | elif dp[i][j-1] is True and s2[j-1] == s3[i+j-1]: 35 | dp[i][j] = True 36 | else: 37 | dp[i][j] = False 38 | return dp[i][j] 39 | 40 | s1 = "xyz" 41 | s2 = "abc" 42 | s3 = "xyzabc" 43 | print(isInterleave(s1, s2, s3)) -------------------------------------------------------------------------------- /DynamicProgramming/LCS.py: -------------------------------------------------------------------------------- 1 | def LCS_LENGTH(X, Y): 2 | m = len(X) 3 | n = len(Y) 4 | c = [[0 for i in range(n+1)] for i in range(m+1)] 5 | b = [[0 for i in range(n)] for i in range(m)] 6 | for i in range(1, m + 1): 7 | for j in range(1, n + 1): 8 | if X[i-1] == Y[j-1]: 9 | c[i][j] = c[i-1][j-1] + 1 10 | b[i-1][j-1] = "A" 11 | elif c[i-1][j] >= c[i][j-1]: 12 | c[i][j] = c[i-1][j] 13 | b[i-1][j-1] = "T" 14 | else: 15 | c[i][j] = c[i][j-1] 16 | b[i-1][j-1] = "L" 17 | return c, b 18 | 19 | 20 | def print_lcs(b, X, i, j): 21 | if i == -1 or j == -1: 22 | return 23 | if b[i][j] == "A": 24 | print_lcs(b, X, i-1, j-1) 25 | print(X[i]) 26 | elif b[i][j] == "T": 27 | print_lcs(b, X, i-1, j) 28 | else: 29 | print_lcs(b, X, i, j-1) 30 | return 31 | 32 | Y = "BDCABA" 33 | X = "ABCBDAB" 34 | c, b = LCS_LENGTH(X, Y) 35 | print_lcs(b, X, len(X)-1, len(Y)-1) -------------------------------------------------------------------------------- /DynamicProgramming/LIS.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 问题描述: 3 | 一个序列有N个数:A[1],A[2],…,A[N],求出最长非降子序列的长度。 4 | (讲DP基本都会讲到的一个问题LIS:longest increasing subsequence) 5 | 6 | 思路: 7 | 假如我们考虑求A[1],A[2],…,A[i]的最长非降子序列的长度,其中i= A[j] and d[j]+1 > d[i]: 23 | d[i] = d[j] + 1 24 | return max(d) 25 | 26 | A = [5, 3, 4, 8, 6, 7] 27 | print(LIS(A)) 28 | -------------------------------------------------------------------------------- /DynamicProgramming/MaxProductSubstring.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目描述: 3 | 给一个浮点数序列,取最大乘积连续子串的值,例如 -2.5,4,0,3,0.5,8,-1,则取出的最大乘积连续子串为3,0.5,8。 4 | 也就是说,上述数组中,3 0.5 8这3个数的乘积30.58=12是最大的,而且是连续的。 5 | 6 | 思路: 7 | 因为有正有负,所以每次都要存储最小的子串乘积值,因为下次要处理的 a[i] 可能是负,负负得正。 8 | 9 | 递推方程: 10 | maxend = max(max(maxend * a[i], minend * a[i]), a[i]); 11 | minend = min(min(maxend * a[i], minend * a[i]), a[i]); 12 | ''' 13 | 14 | def maxProductSubstring(a): 15 | maxend, minend, maxresult = a[0], a[0], a[0] 16 | for i in range(1,len(A)): 17 | maxend = max(max(maxend * a[i], minend * a[i]), a[i]) 18 | minend = min(min(maxend * a[i], minend * a[i]), a[i]) 19 | maxresult = max(maxend, maxresult) 20 | return maxresult 21 | 22 | A = [-2.5, 4, 0, 3, 0.5, 8, -1] 23 | print(maxProductSubstring(A)) -------------------------------------------------------------------------------- /DynamicProgramming/MinimumPathSum.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode: 3 | 64. Minimum Path Sum 4 | Given a m x n grid filled with non-negative numbers, 5 | find a path from top left to bottom right which minimizes the sum of all numbers along its path. 6 | 7 | Note: You can only move either down or right at any point in time. 8 | ''' 9 | 10 | 11 | class Solution(object): 12 | def minPathSum(self, grid): 13 | """ 14 | :type grid: List[List[int]] 15 | :rtype: int 16 | """ 17 | m = len(grid) 18 | if m > 0 and len(grid[0]) > 0: 19 | n = len(grid[0]) 20 | else: 21 | return 0 22 | 23 | dp = [[0 for i in range(n+1)] for i in range(m+1)] 24 | for i in range(m+1): 25 | dp[i][0] = float('inf') 26 | for i in range(n+1): 27 | dp[0][i] = float('inf') 28 | dp[1][1] = grid[0][0] 29 | for i in range(1, m+1): 30 | for j in range(1, n+1): 31 | if i == 1 and j == 1: 32 | dp[i][j] = grid[i-1][j-1] 33 | elif dp[i-1][j] < dp[i][j-1]: 34 | dp[i][j] = dp[i-1][j] + grid[i-1][j-1] 35 | else: 36 | dp[i][j] = dp[i][j-1] + grid[i-1][j-1] 37 | return dp[m][n] 38 | 39 | grid = [ 40 | [1] 41 | ] 42 | print(Solution.minPathSum(Solution, grid)) -------------------------------------------------------------------------------- /DynamicProgramming/Triangle.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode:120. Triangle 3 | Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below. 4 | 5 | For example, given the following triangle 6 | [ 7 | [2], 8 | [3,4], 9 | [6,5,7], 10 | [4,1,8,3] 11 | ] 12 | The minimum path sum from top to bottom is 11 (i.e., 2 + 3 + 5 + 1 = 11). 13 | 14 | Note: 15 | Bonus point if you are able to do this using only O(n) extra space, where n is the total number of rows in the triangle. 16 | 17 | ''' 18 | 19 | 20 | class Solution(object): 21 | ''' 22 | extra space: O(n^2) 23 | using 'top to bottom' thought 24 | ''' 25 | def minimumTotal(self, triangle): 26 | """ 27 | :type triangle: List[List[int]] 28 | :rtype: int 29 | """ 30 | length = len(triangle) 31 | dp = [[0 for i in range(j+1)] for j in range(length)] # dp[i][j] means element of row i column j is the last one of the min_path 32 | dp[0][0] = triangle[0][0] 33 | for i in range(1, length): 34 | for j in range(i+1): 35 | if j == 0: 36 | dp[i][j] = dp[i-1][j] + triangle[i][j] 37 | elif j == i: 38 | dp[i][j] = dp[i-1][j-1] + triangle[i][j] 39 | elif dp[i-1][j] < dp[i-1][j-1]: 40 | dp[i][j] = dp[i-1][j] + triangle[i][j] 41 | else: 42 | dp[i][j] = dp[i-1][j-1] + triangle[i][j] 43 | return min(dp[length-1]) 44 | 45 | ''' 46 | extra space: O(n) 47 | using 'bottom to top' thought 48 | ''' 49 | def minimumTotal_bottomtotop(self, triangle): 50 | """ 51 | :type triangle: List[List[int]] 52 | :rtype: int 53 | """ 54 | length = len(triangle) 55 | dp = triangle[length-1] 56 | for i in range(length-2, -1, -1): 57 | for j in range(i+1): 58 | dp[j] = min(dp[j], dp[j+1]) + triangle[i][j] 59 | return dp[0] 60 | 61 | triangle = [ 62 | [2], 63 | [3, 4], 64 | [6, 5, 7], 65 | [4, 1, 8, 3] 66 | ] 67 | 68 | # print(Solution.minimumTotal(Solution, triangle)) 69 | print(Solution.minimumTotal_bottomtotop(Solution, triangle)) -------------------------------------------------------------------------------- /DynamicProgramming/UniquePaths.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode: 3 | 62. Unique Paths 4 | 5 | A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). 6 | 7 | The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below). 8 | 9 | How many possible unique paths are there? 10 | ''' 11 | class Solution(object): 12 | def uniquePaths(self, m, n): 13 | """ 14 | :type m: int 15 | :type n: int 16 | :rtype: int 17 | """ 18 | c = [[0 for i in range(n+1)] for i in range(m+1)] 19 | for i in range(n+1): 20 | c[0][i] = 0 21 | for i in range(m+1): 22 | c[i][0] = 0 23 | for i in range(1, m+1): 24 | for j in range(1, n+1): 25 | if i == 1 and j == 1: 26 | c[i][j] = 1 27 | else: 28 | c[i][j] = c[i-1][j] + c[i][j-1] 29 | return c[i][j] 30 | 31 | sol = Solution() 32 | print(sol.uniquePaths(1, 1)) -------------------------------------------------------------------------------- /DynamicProgramming/UniquePathsII.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode: 3 | 63. Unique Paths II 4 | 5 | Follow up for "Unique Paths": 6 | 7 | Now consider if some obstacles are added to the grids. How many unique paths would there be? 8 | 9 | An obstacle and empty space is marked as 1 and 0 respectively in the grid. 10 | 11 | For example, 12 | There is one obstacle in the middle of a 3x3 grid as illustrated below. 13 | 14 | [ 15 | [0,0,0], 16 | [0,1,0], 17 | [0,0,0] 18 | ] 19 | The total number of unique paths is 2. 20 | 21 | Note: m and n will be at most 100. 22 | ''' 23 | 24 | class Solution(object): 25 | def uniquePathsWithObstacles(self, obstacleGrid): 26 | """ 27 | :type obstacleGrid: List[List[int]] 28 | :rtype: int 29 | """ 30 | 31 | m = len(obstacleGrid) 32 | n = len(obstacleGrid[0]) 33 | dp = [[0 for i in range(n+1)] for i in range(m+1)] 34 | dp[1][1] = 1 35 | for i in range(1, m+1): 36 | for j in range(1, n+1): 37 | if obstacleGrid[i-1][j-1] == 1: 38 | dp[i][j] = 0 39 | elif i == 1 and j == 1: 40 | dp[1][1] = 1 41 | else: 42 | dp[i][j] = dp[i-1][j] + dp[i][j-1] 43 | 44 | return dp[m][n] 45 | 46 | sol = Solution 47 | obstacleGrid = [ 48 | [0, 0, 0], 49 | [0, 1, 0], 50 | [0, 0, 0] 51 | ] 52 | print(sol.uniquePathsWithObstacles(sol, obstacleGrid)) -------------------------------------------------------------------------------- /Graph/MaxFlow/maxflow.py: -------------------------------------------------------------------------------- 1 | import copy 2 | from collections import deque 3 | 4 | 5 | def hasPath(Gf, s, t, path): 6 | # BFS algorithm 7 | V = len(Gf) 8 | visited = list(range(V)) 9 | for i in range(V): 10 | visited[i] = False 11 | visited[s] = True 12 | queue = deque([s]) 13 | while queue: 14 | temp = queue.popleft() 15 | if temp == t: 16 | return True 17 | print("temp =", temp) 18 | for i in range(V): 19 | if not visited[i] and (Gf[temp][i] > 0): 20 | queue.append(i) 21 | visited[i] = True 22 | path[i] = temp # record precursor 23 | return visited[t] 24 | 25 | 26 | def max_flow(graph, s, t): 27 | maxFlow = 0 28 | Gf = copy.deepcopy(graph) 29 | V = len(Gf) 30 | path = list(range(V)) 31 | while hasPath(Gf, s, t, path): 32 | min_flow = float('inf') 33 | 34 | # find cf(p) 35 | v = t 36 | while v != s: 37 | u = path[v] 38 | min_flow = min(min_flow, Gf[u][v]) 39 | v = path[v] 40 | print(min_flow) 41 | 42 | # add flow in every edge of the augument path 43 | v = t 44 | while v != s: 45 | u = path[v] 46 | Gf[u][v] -= min_flow 47 | Gf[v][u] += min_flow 48 | v = path[v] 49 | 50 | maxFlow += min_flow 51 | return maxFlow 52 | 53 | M=0 54 | capacity = [ 55 | [0,16,13,M,M,M], 56 | [M,0,10,12,M,M], 57 | [M,4,0,M,14,M], 58 | [M,M,9,0,M,20], 59 | [M,M,M,7,0,4], 60 | [M,M,M,M,M,0] 61 | ] 62 | 63 | flow = max_flow(capacity, 0, 5) 64 | print("flow =", flow) 65 | 66 | -------------------------------------------------------------------------------- /Graph/MaxFlow/mincostmaxflow.py: -------------------------------------------------------------------------------- 1 | import copy 2 | from heapq import * 3 | # 最小堆 4 | 5 | def hasPath(Gf, s, t): 6 | # Dijkstra algorithm using "heapq" 7 | V = len(Gf) 8 | visited = list(range(V)) 9 | for i in range(V): 10 | visited[i] = False 11 | h = [(0, s, list(range(V)))] 12 | while h: 13 | (cost, v1, path) = heappop(h) 14 | if visited[v1] is False: 15 | visited[v1] = True 16 | if v1 == t: 17 | return True, path 18 | for i in range(V): 19 | if not visited[i] and (Gf[v1][i][0] > 0): 20 | path[i] = v1 # record precursor 21 | heappush(h, (cost + Gf[v1][i][1], i, copy.deepcopy(path))) # 必须要深拷贝,不然heap里的各个path都会随之改变 22 | return visited[t], path 23 | 24 | 25 | def max_flow(graph, s, t): 26 | maxFlow = 0 27 | minCost = 0 28 | Gf = copy.deepcopy(graph) 29 | V = len(Gf) 30 | path = list(range(V)) 31 | while hasPath(Gf, s, t)[0]: 32 | path = hasPath(Gf, s, t)[1] 33 | print("path =", path) 34 | min_flow = float('inf') 35 | 36 | # find cf(p) 37 | v = t 38 | while v != s: 39 | u = path[v] 40 | min_flow = min(min_flow, Gf[u][v][0]) 41 | v = path[v] 42 | print("min_flow =", min_flow) 43 | 44 | # add flow in every edge of the augument path 45 | v = t 46 | while v != s: 47 | u = path[v] 48 | Gf[u][v][0] = Gf[u][v][0] - min_flow 49 | Gf[v][u][0] = Gf[v][u][0] + min_flow 50 | Gf[v][u][1] = Gf[u][v][1] 51 | minCost = minCost + min_flow * Gf[u][v][1] 52 | v = path[v] 53 | maxFlow += min_flow 54 | path = list(range(V)) 55 | return maxFlow, minCost 56 | 57 | capacity = [ 58 | [[0,0],[16,1],[13,3],[0,0],[0,0],[0,0]], 59 | [[0,0],[0,0],[10,1],[12,4],[0,0],[0,0]], 60 | [[0,0],[10,1],[0,0],[9,4],[10,2],[0,0]], 61 | [[0,0],[0,0],[9,4],[0,0],[0,0],[20,2]], 62 | [[0,0],[0,0],[0,0],[7,1],[0,0],[4,2]], 63 | [[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]] 64 | ] 65 | 66 | flow, cost = max_flow(capacity, 0, 5) 67 | print("\nflow =", flow) 68 | 69 | print("cost =", cost) 70 | -------------------------------------------------------------------------------- /Graph/ShortestPath/dijkstra.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | from heapq import * 3 | 4 | def dijkstra(graph_dict, from_node, to_node): 5 | cost = -1 6 | Shortest_path=[] 7 | q, seen = [(0,from_node,())], set() 8 | while q: 9 | (cost,v1,path) = heappop(q) 10 | if v1 not in seen: 11 | seen.add(v1) 12 | path = (v1, path) 13 | if v1 == to_node: # Find the to_node!!! 14 | break; 15 | for v2,c in graph_dict.get(v1, ()): 16 | if v2 not in seen: 17 | heappush(q, (cost+c, v2, path)) 18 | 19 | # Check the way to quit 'while' loop 20 | if v1 != to_node: 21 | # IF there isn't a path from from_node to to_node, THEN return null!!! 22 | print("node: %s cannot reach node: %s" %(from_node,to_node)) 23 | cost = -1 24 | Shortest_path=[] 25 | return cost,Shortest_path 26 | else: 27 | # IF there is a path from from_node to to_node, THEN format the path and return!!! 28 | left = path[0] 29 | Shortest_path.append(left) 30 | right = path[1] 31 | while len(right)>0: 32 | left = right[0] 33 | Shortest_path.append(left) 34 | right = right[1] 35 | Shortest_path.reverse() 36 | 37 | return cost,Shortest_path 38 | 39 | def dijkstra_all(graph_dict): 40 | Shortest_path_dict = defaultdict(dict) 41 | for i in nodes: 42 | for j in nodes: 43 | if i != j: 44 | cost,Shortest_path = dijkstra(graph_dict,i,j) 45 | Shortest_path_dict[i][j] = Shortest_path 46 | 47 | return Shortest_path_dict 48 | 49 | nodes=['s1','s2','s3','s4','s5','s6'] 50 | print("nodes =",nodes) 51 | M=float("inf") 52 | # Describing graph by 2-D list 53 | graph_list = [ 54 | [0,30,15,M,M,M], 55 | [5,0,M,M,20,30], 56 | [M,10,0,M,M,15], 57 | [M,M,M,0,M,M], 58 | [M,M,M,10,0,M], 59 | [M,M,M,30,10,0] 60 | ] 61 | print("graph_list = [") 62 | for l in graph_list: 63 | print(str(l)+",") 64 | print("]\n") 65 | 66 | # Describing graph by a list of tuple 67 | graph_edges = [] 68 | print ("graph_edges = [") 69 | for i in nodes: 70 | for j in nodes: 71 | if i!=j and graph_list[nodes.index(i)][nodes.index(j)]!=M: 72 | graph_edges.append((i,j,graph_list[nodes.index(i)][nodes.index(j)])) 73 | print (str((i,j,graph_list[nodes.index(i)][nodes.index(j)]))+", ",end="") 74 | print() 75 | print("]\n") 76 | 77 | # Describing graph by dict 78 | graph_dict = defaultdict(list) 79 | print("graph_dict = {") 80 | for tail,head,cost in graph_edges: 81 | graph_dict[tail].append((head,cost)) 82 | for key in graph_dict: 83 | print("'%s': %s" %(key, graph_dict[key])) 84 | print("}\n") 85 | 86 | print ("----------------Dijkstra----------------") 87 | #from_node = input ("Please input the from_node = ") 88 | #to_node = input("Please input the to_node = ") 89 | #cost,Shortest_path = dijkstra(graph_dict, from_node, to_node) 90 | #print ('The shortest path = %s, cost = %s'%(Shortest_path,cost)) 91 | Shortest_path_dict = dijkstra_all(graph_dict) 92 | print("Shortest_path_dict = {") 93 | for key in Shortest_path_dict: 94 | print("'%s': %s," %(key, Shortest_path_dict[key])) 95 | print("}") 96 | -------------------------------------------------------------------------------- /Graph/ShortestPath/floyd.py: -------------------------------------------------------------------------------- 1 | # ------------------函数------------------- 2 | def back_path(path,i,j,shortestPath): #递归回溯 3 | print ("path[%s][%s] = "%(i,j),path[i][j]) 4 | if -1 != path[i][j]: 5 | shortestPath = back_path(path,i,path[i][j],shortestPath) 6 | shortestPath = back_path(path,path[i][j],j,shortestPath) 7 | if j not in shortestPath: 8 | shortestPath.append(j) 9 | return shortestPath 10 | 11 | def getShortestPath(graph,path,i,j): 12 | shortestPath = [] 13 | if graph[i][j] == float('inf') or i == j: 14 | print("顶点%s 不能到达 顶点%s!"%(i,j)) 15 | return shortestPath 16 | elif path[i][j] == -1: 17 | shortestPath.append(i) 18 | shortestPath.append(j) 19 | else : 20 | shortestPath.append(i) 21 | shortestPath = back_path(path,i,j,shortestPath) 22 | print("顶点%s 到 顶点%s 的路径为:"%(i,j),shortestPath) 23 | return shortestPath 24 | 25 | def getAllShortestPath(graph,path): 26 | print("------正在生成全局最短路径------") 27 | ShortestPath_dict = {} 28 | for i in range(N): 29 | ShortestPath_dict[i] = {} 30 | for j in range(N): 31 | print("尝试生成顶点%s到顶点%s的最短路径..."%(i,j)) 32 | if i !=j : 33 | shortestPath = getShortestPath(graph,path,i,j) 34 | ShortestPath_dict[i][j] = shortestPath 35 | print("--------------------------------") 36 | return ShortestPath_dict 37 | 38 | # ----------------------定义-------------------- 39 | M=float('inf') #无穷大 40 | graph = [ 41 | [0,30,15,M,M,M], 42 | [5,0,M,M,20,30], 43 | [M,10,0,M,M,15], 44 | [M,M,M,0,M,M], 45 | [M,M,M,10,0,M], 46 | [M,M,M,30,10,0] 47 | ] 48 | N = len(graph) 49 | path = [] 50 | for i in range(N): 51 | path.append([]) 52 | for j in range(N): 53 | path[i].append(-1) 54 | 55 | print ("Original Graph:\n",graph) 56 | # -----------------Floyd Algorithm---------------- 57 | for k in range(N): 58 | for i in range(N): 59 | for j in range(N): 60 | if graph[i][j] > graph[i][k] + graph[k][j]: 61 | graph[i][j] = graph[i][k] + graph[k][j] 62 | path[i][j] = k 63 | 64 | print ("Shortest Graph:\n",graph) 65 | print ("Path:\n",path) 66 | 67 | print("ShortestPath_dict =\n",getAllShortestPath(graph,path)) 68 | -------------------------------------------------------------------------------- /Optimization/light_24_improve.m: -------------------------------------------------------------------------------- 1 | function main() 2 | x= 0:0.01:17.5; 3 | y= 0:0.01:12; 4 | m=length(y); 5 | n=length(x); 6 | [xx,yy]=meshgrid(x,y,'r'); 7 | 8 | number = 24; % given 24 lights 9 | 10 | % initialize 11 | popsize=50; 12 | elite=0.2; 13 | maxiter=500; 14 | mutprob=0.2; 15 | 16 | pop=[]; 17 | cost=[]; 18 | for i=1:popsize 19 | sol=unifrnd(0,1,2,number); 20 | sol(1,:) = sol(1,:).*12; 21 | sol(2,:) = sol(2,:).*17.5; 22 | cost = [cost, costf(sol,xx,yy,m,n,number)]; 23 | pop = [pop, sol]; 24 | end 25 | 26 | topelite = floor(elite*popsize); 27 | 28 | % main iteration 29 | for i = 1:maxiter 30 | [ranked_cost,index_array] = sort(cost); 31 | ranked = []; 32 | for r = 1:length(index_array) 33 | ranked = [ranked, pop(1:2, (number*(index_array(r)-1)+1):number*index_array(r))]; 34 | end 35 | 36 | % REBUILD the pop 37 | pop = []; 38 | cost = []; 39 | % First: add elite generation 40 | pop = ranked(1:2, 1:topelite*number); 41 | for j = 1:topelite 42 | sol = pop(1:2, (number*(j-1)+1):number*j); 43 | cost = [cost, costf(sol,xx,yy,m,n,number)]; 44 | end 45 | % Second: add descendant of the origin pop from mutate and crossover 46 | while (length(pop)/number) 1/3 78 | disp('not a good algo') 79 | else 80 | disp('a good algo') 81 | end 82 | 83 | % Plot the solution figure 84 | plot(result(1,:),result(2,:),'*r'); 85 | axis([0 17.5 0 12]); 86 | figure; 87 | mesh(xx,yy,zz); 88 | end 89 | 90 | % calculate the cost 91 | function cost=costf(sol,xx,yy,m,n,number) 92 | zz=0; 93 | for i=1:number 94 | zz = zz + 1./((yy-sol(1,i)).^2+(xx-sol(2,i)).^2+9); 95 | end 96 | AVG = sum(sum(zz))./(m*n); 97 | MAX = max(max(zz)); 98 | cost = sum(sum((zz-AVG).^2)); 99 | end 100 | 101 | % vec is a 2-d matrix, number is the length of the solution(number of lights) 102 | function vec=mutate(vec,number) 103 | i = floor(rand*(number-1)+0.5)+1; 104 | flag = rand; 105 | if flag<0.25 & vec(1,i)>1 & vec(2,i)>1 106 | vec = [vec(1:2,1:i-1),[vec(1,i)-1,vec(2,i)-1]',vec(1:2,i+1:length(vec))]; 107 | elseif flag<0.5 & vec(1,i)>1 & vec(2,i)<16.5 108 | vec = [vec(1:2,1:i-1),[vec(1,i)-1,vec(2,i)+1]',vec(1:2,i+1:length(vec))]; 109 | elseif flag<0.75 & vec(1,i)<11 & vec(2,i)>1 110 | vec = [vec(1:2,1:i-1),[vec(1,i)+1,vec(2,i)-1]',vec(1:2,i+1:length(vec))]; 111 | elseif vec(1,i)<11 & vec(2,i)<16.5 112 | vec = [vec(1:2,1:i-1),[vec(1,i)+1,vec(2,i)+1]',vec(1:2,i+1:length(vec))]; 113 | else 114 | end 115 | end 116 | 117 | % r1 and r2 is 2-D matrix, just like parameter 'vec' in the mutate function 118 | function vec=crossover(r1,r2,number) 119 | i = floor(rand*(number-1)+0.5)+1; 120 | vec = [r1(1:2,1:i), r2(1:2,i+1:length(r2))]; 121 | end -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DataStructure&Algorithm 2 | 3 | ## [Divide-and-conquer](https://github.com/edisonleolhl/DataStructure-Algorithm/tree/master/Divede-and-conquer) 4 | 5 | - [Binary_search](https://github.com/edisonleolhl/DataStructure-Algorithm/blob/master/Divede-and-conquer/binary_search.py) 6 | 7 | - [Maximum_subarray](https://github.com/edisonleolhl/DataStructure-Algorithm/blob/master/Divede-and-conquer/maximum_subarray.py) 8 | 9 | - [Max2](https://github.com/edisonleolhl/DataStructure-Algorithm/blob/master/Divede-and-conquer/max2.py) 10 | 11 | ## [DynamicProgramming](https://github.com/edisonleolhl/DataStructure-Algorithm/tree/master/DynamicProgramming) 12 | 13 | - [EditDistance](https://github.com/edisonleolhl/DataStructure-Algorithm/tree/master/DynamicProgramming/EditDistance.py) 14 | 15 | - [IsInterleave](https://github.com/edisonleolhl/DataStructure-Algorithm/tree/master/DynamicProgramming/IsInterleave.py) 16 | 17 | - [LCS](https://github.com/edisonleolhl/DataStructure-Algorithm/tree/master/DynamicProgramming/LCS.py) 18 | 19 | - [LIS](https://github.com/edisonleolhl/DataStructure-Algorithm/tree/master/DynamicProgramming/LIS.py) 20 | 21 | - [MaxProductSubstring](https://github.com/edisonleolhl/DataStructure-Algorithm/tree/master/DynamicProgramming/MaxProductSubstring.py) 22 | 23 | - [MinimumPathSum](https://github.com/edisonleolhl/DataStructure-Algorithm/tree/master/DynamicProgramming/MinimumPathSum.py) 24 | 25 | - [Triangle](https://github.com/edisonleolhl/DataStructure-Algorithm/tree/master/DynamicProgramming/Triangle.py) 26 | 27 | - [UniquePaths](https://github.com/edisonleolhl/DataStructure-Algorithm/tree/master/DynamicProgramming/UniquePaths.py) 28 | 29 | - [UniquePathsII](https://github.com/edisonleolhl/DataStructure-Algorithm/tree/master/DynamicProgramming/UniquePathsII.py) 30 | 31 | ## [Graph](https://github.com/edisonleolhl/DataStructure-Algorithm/blob/master/Graph) 32 | 33 | ### [Max Flow](https://github.com/edisonleolhl/DataStructure-Algorithm/blob/master/Graph/MaxFlow) 34 | 35 | - [MaxFlow](https://github.com/edisonleolhl/DataStructure-Algorithm/blob/master/Graph/MaxFlow/maxflow.py) 36 | 37 | - [MinCostMaxFLow](https://github.com/edisonleolhl/DataStructure-Algorithm/blob/master/Graph/MaxFlow/mincostmaxflow.py) 38 | 39 | ### [Shortest Path](https://github.com/edisonleolhl/DataStructure-Algorithm/blob/master/Graph/ShortestPath) 40 | 41 | - [Dijkstra](https://github.com/edisonleolhl/DataStructure-Algorithm/blob/master/Graph/ShortestPath/dijkstra.py) 42 | 43 | - [Floyd](https://github.com/edisonleolhl/DataStructure-Algorithm/blob/master/Graph/ShortestPath/floyd.py) 44 | 45 | ## [Optimization](https://github.com/edisonleolhl/DataStructure-Algorithm/tree/master/Optimization) 46 | 47 | - [GeneticAlgorithm](https://github.com/edisonleolhl/DataStructure-Algorithm/blob/master/Optimization/light_24_improve.m) 48 | 49 | ## [Sorting](https://github.com/edisonleolhl/DataStructure-Algorithm/blob/master/Sorting) 50 | 51 | - [bubble_sort](https://github.com/edisonleolhl/DataStructure-Algorithm/blob/master/Sorting/bubble_sort.py) 52 | 53 | - [insertion_sort](https://github.com/edisonleolhl/DataStructure-Algorithm/blob/master/Sorting/insertion_sort.py) 54 | 55 | - [selection_sort](https://github.com/edisonleolhl/DataStructure-Algorithm/blob/master/Sorting/selection_sort.py) 56 | 57 | - [quick_sort](https://github.com/edisonleolhl/DataStructure-Algorithm/blob/master/Sorting/quick_sort.py) 58 | 59 | - [shell_sort](https://github.com/edisonleolhl/DataStructure-Algorithm/blob/master/Sorting/shell_sort.py) -------------------------------------------------------------------------------- /Sorting/bubble_sort.py: -------------------------------------------------------------------------------- 1 | def bubble_sort(L): 2 | N = len(L) 3 | if N <= 0 : 4 | print("Please input correct list.") 5 | return 6 | for i in range(N): 7 | for j in range(0,N-1-i): 8 | if L[j] > L[j+1] : 9 | L[j],L[j+1] = L[j+1],L[j] 10 | print(L) 11 | return L 12 | 13 | if __name__ == '__main__': 14 | L = [9,8,7,6,5,4,3,2,1] 15 | print(bubble_sort(L)) 16 | -------------------------------------------------------------------------------- /Sorting/insertion_sort.py: -------------------------------------------------------------------------------- 1 | def insertion_sort(L): 2 | N = len(L) 3 | if N <= 0: 4 | print("Please input correct list.") 5 | return 6 | for i in range(1, N): # i指示当前待排元素 7 | temp = L[i] 8 | for j in range(i-1, -1, -1): # i-1指示已排序列的最后一项,然后以此与当前待排元素比较,往前移动 9 | if L[j] <= temp: 10 | L[j+1] = temp 11 | else: 12 | L[j+1] = L[j] 13 | if j == 0: 14 | L[j] = temp 15 | return L 16 | 17 | def insertion_sort_desc(L): 18 | N = len(L) 19 | if N <= 0: 20 | print("Please input correct list.") 21 | return 22 | for i in range(1, N): 23 | temp = L[i] 24 | for j in range(i-1, -1, -1): 25 | if L[j] >= temp: 26 | L[j+1] = temp 27 | else: 28 | L[j+1] = L[j] 29 | if j == 0: 30 | L[j] = temp 31 | return L 32 | 33 | if __name__ == '__main__': 34 | L = [2, 8, 7, 6, 5, 4, 3, 2, 1] 35 | print("ordered sequence =", insertion_sort(L)) 36 | print("ordered sequence descending = ", insertion_sort_desc(L)) -------------------------------------------------------------------------------- /Sorting/merge_sort.py: -------------------------------------------------------------------------------- 1 | def merge(left, right): 2 | lp, rp = 0, 0 3 | result = [] 4 | while lp < len(left) and rp < len(right): 5 | if left[lp] <= right[rp]: 6 | result.append(left[lp]) 7 | lp += 1 8 | else: 9 | result.append(right[rp]) 10 | rp += 1 11 | result += left[lp:] 12 | result += right[rp:] 13 | return result 14 | 15 | def merge_sort(alist): 16 | length = len(alist) 17 | if length == 1: 18 | return alist 19 | mid = length // 2 20 | left = merge_sort(alist[:mid]) 21 | right = merge_sort(alist[mid:]) 22 | print("left = %s, right = %s"%(left,right)) 23 | result = merge(left, right) 24 | print("merge:",result) 25 | return result 26 | 27 | if __name__ == '__main__': 28 | alist = [1, 8, 7, 6, 5, 4, 3, 2, 1] 29 | print("ordered sequence =",merge_sort(alist)) 30 | -------------------------------------------------------------------------------- /Sorting/quick_sort.py: -------------------------------------------------------------------------------- 1 | def quick_sort(L,low,high): 2 | if(low < high): 3 | pivotloc = partition(L,low,high) 4 | quick_sort(L,low,pivotloc-1) 5 | quick_sort(L,pivotloc+1,high) 6 | return L 7 | 8 | 9 | def partition(L,low,high): 10 | if(low >= high): 11 | return 12 | pivotkey = L[low] 13 | while(low < high): 14 | while(low < high and L[high] >= pivotkey): 15 | high = high - 1 16 | L[low],L[high] = L[high],L[low] 17 | while(low < high and L[low] <= pivotkey): 18 | low = low + 1 19 | L[high],L[low] = L[low],L[high] 20 | print("pivotkey =",pivotkey) 21 | print(L,"\n") 22 | return low 23 | 24 | if __name__ == '__main__': 25 | L = [1,8,7,6,5,4,3,2,1] 26 | print(quick_sort(L, 0, len(L)-1)) 27 | -------------------------------------------------------------------------------- /Sorting/selection_sort.py: -------------------------------------------------------------------------------- 1 | def select_sort(L): 2 | N = len(L) 3 | if N <= 0 : 4 | print("Please input correct list.") 5 | return 6 | for i in range(N-1): 7 | indexOfMax = 0 8 | for j in range(1,N-i): 9 | if L[j] > L[indexOfMax] : 10 | indexOfMax = j 11 | L[N-1-i], L[indexOfMax] = L[indexOfMax], L[N-1-i] 12 | print(L) 13 | return L 14 | 15 | if __name__ == '__main__': 16 | L = [9,8,7,6,5,4,3,2,1] 17 | select_sort(L) 18 | -------------------------------------------------------------------------------- /Sorting/shell_sort.py: -------------------------------------------------------------------------------- 1 | def shell_sort(L,delta): 2 | N = len(L) 3 | for inc in delta: 4 | L = shell_insert(L,inc) 5 | print(L,"\n") 6 | return L 7 | 8 | def shell_insert(L,inc): 9 | N = len(L) 10 | for index in range(inc): # 整个序列分为若干子序列,index是每个子序列的头元素 11 | for i in range(index+inc,N,inc): # 默认每个子序列的头元素为“已排序列”,除了头元素的子序列为“待排序列” 12 | temp = L[i] # 每个子序列的排序方式为直接插入排序,所以当前待排元素的值给temp 13 | for j in range(i-inc,-1,-inc): # 在子序列的“已排序列”中找到合适的插入地点,所以是倒序 14 | if temp < L[j]: 15 | L[j+inc] = L[j] 16 | else : 17 | break # 当前待排元素比“已排序列”中的末尾元素还要大,所以直接放入末尾 18 | if j == index or L[j-inc] < temp : 19 | L[j] = temp 20 | print(L) 21 | return L 22 | 23 | if __name__ == '__main__': 24 | L = [9,8,7,6,5,4,3,2,1] 25 | delta = [5,3,1] #构造增量序列 26 | print(shell_sort(L,delta)) 27 | --------------------------------------------------------------------------------