├── .gitmodules ├── Backtracking_and_Branch_and_Bound └── Queens.py ├── README.md ├── activity_selection.cpp ├── divide_and_conque ├── 2000.in ├── Fibonacci.cpp ├── binary_search.py ├── fib.py ├── hanoi.cpp ├── hanoi.py ├── karatsuba.py ├── matrix.py ├── merge_sort.py ├── permutations └── quick_sort_dac.py ├── dynamic_programming ├── 01bagproblem.cpp ├── 01背包.cpp ├── cut_rod.py ├── cut_rod_naive.py ├── knapsack.py ├── lcs.py ├── lianchengji.cpp └── matrix_chain.py ├── fractional_Knapsack.cpp ├── genetic_algorithm ├── ga_hello_world.py └── ga_tsp.py ├── greedy.py ├── greedy_algorithm ├── 0-1_package.py ├── Dijkstra.py ├── Kruskal.py └── Prim.py ├── quick_sort.cpp └── stochastic_and_intelligent algorithm └── Monte_Carlo_Pi.py /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "dynamic_programming/fibonacci-number-algorithms"] 2 | path = dynamic_programming/fibonacci-number-algorithms 3 | url = https://github.com/alidasdan/fibonacci-number-algorithms 4 | -------------------------------------------------------------------------------- /Backtracking_and_Branch_and_Bound/Queens.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 在n*n格的棋盘撒上放置彼此不受攻击的n个皇后。按照国际象棋的规矩, 3 | 皇后可以攻击与之处在同一行或者同一列或者同一斜线上的棋子。 4 | N皇后问题等价于在n * n格的棋盘上放置n个皇后,任何2个皇后 5 | 不放在同一行同一列同一斜线上。 6 | ''' 7 | 8 | #name:queens 9 | #全排列函数 10 | per_result = [] 11 | def per(lst,s,e): 12 | if s == e: 13 | per_result.append(list(lst)) 14 | else: 15 | for i in range(s,e): 16 | lst[i],lst[s] = lst[s],lst[i]#试探 17 | per(lst,s+1,e)#递归 18 | lst[i],lst[s] = lst[s],lst[i]#回溯 19 | #剪枝函数 20 | #args:[1,2,3,4] 21 | #return true or false 22 | def shear(lst): 23 | result = 0 24 | for i in range(len(lst)): 25 | for j in range(i+1,len(lst)): 26 | if(abs(lst[j] - lst[i]) == abs(j-i)): 27 | result += 1 28 | if(result > 0): 29 | return True 30 | else: 31 | return False 32 | #格式打印函数 33 | def stamp(st): 34 | for i in st: 35 | for j in range(len(i)): 36 | a = ("."*(i[j]-1)+"#"+"."*(len(i)-i[j])) 37 | print(a,"\t","第{}个皇后放在棋盘的第{}列".format(j+1,i[j])) 38 | print(" ")#负责空行 39 | num = eval(input("请输入皇后的个数:")) 40 | lst = [i+1 for i in range(num)] 41 | per(lst,0,num) 42 | queen_lst = [] 43 | for i in per_result: 44 | if(shear(i) == False): 45 | queen_lst.append(i) 46 | stamp(queen_lst) 47 | print("共{:d}种可能".format(len(queen_lst))) 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NBU研究生课程《高级算法设计与优化》 2 | 3 | **课程编号**:1022114 **总学时**:32 **学分**:2 4 | 5 | **开课学期**:秋季 **开课学院**:EECS **授课语言**:中文 6 | 7 | **适用学科/专业**:电子科学与技术/集成电路工程 8 | 9 | **课程类别**:专业学位课 **考核方式**:考试 10 | 11 | **成绩评定**:平时成绩,占比30%(其中思政成绩占比5%);小组展示成绩,占20%;期末考试成绩,占比50%。 12 | 13 | **主要教学方式**: 14 | 15 | - [x] 讲授 16 | 17 | - [x] 讨论 18 | 19 | - [x] 专题讲座 20 | 21 | - [x] 案例分析 22 | 23 | - [x] 自学 24 | 25 | 26 | 27 | | 章节 | 标题 | 教学内容 | 学时分配 | 28 | | :--: | :----------------: | :----------------------------------------------------------: | :------: | 29 | | 1 | 绪论 | 算法概念、性质及意义;问题求解流程;算法的例子与描述;复杂性的概念与计算;算法复杂性的渐近性态的数学表述;渐近阶的求解方法 | 2 | 30 | | 2 | 递归与分治策略 | 递归的概念;递归方程构建的思想;阶乘函数、Fibonacci数列、Ackerman函数、排列问题、整数划分问题、Hanoi塔问题的递归算法分析;分治法的基本思想;二分查找、大整数的乘法、Strassen矩阵乘法、棋盘覆盖、合并排序、快速排序、循环赛日程表问题的算法分析 | 4 | 31 | | 3 | 动态规划 | 动态规划算法的思想、特征和步骤;矩阵连乘积问题分析;动态规划算法的基本要素;备忘录的方法;0-1背包问题分析;最长公共子序列、最大子段和问题分析 | 8 | 32 | | 4 | 贪心算法 | 贪心算法的概念、思想;贪心算法的基本要素;贪心算法的理论基础;背包问题分析;活动安排、最优装载问题分析;最小生成树的Prim、Kruskal算法;单源最短路径的Dijkstra算法 | 4 | 33 | | 5 | 回溯法与分支限界法 | 回溯法的概念、思想和步骤;子集数、排列树、搜索树的构造;N后问题、着色问题分析;分支限界的概念、思想和步骤;0-1背包问题分析;作业调度问题 | 8 | 34 | | 6 | 随机算法与智能算法 | 随机算法概述;蒙特卡罗算法;拉斯维加斯算法;舍伍德算法;蒙特卡罗算法、拉斯维加斯算法、舍伍德算法算的比较与应用;智能算法概述;遗传算法;模拟退火算法 | 6 | 35 | 36 | 37 | 38 | 主要参考书目: 39 | 40 | | 名称 | 编者 | 出版社 | 版次 | 出版时间 | 41 | | :------------------------------------------------------: | :---------------------------------------------------: | :------------: | :---: | :------: | 42 | | 《计算机算法设计与分析》 | 王晓东 | 电子工业出版社 | 第5版 | 2018.8 | 43 | | 算法导论 (原书:Introduction to Algorithms,第3版) | T.H. Cormen, C.E. Leiserson等著,殷建平,徐云等译 | 机械工业出版社 | 第3版 | 2012.12 | 44 | | 算法概论 (原书:Algorithms) | S. Dasgupta, C. Papadimitriou等著,王沛,唐扬斌等译 | 清华大学出版社 | 第1版 | 2008.7 | 45 | | 算法设计 (原书:Algorithm Design) | J. Kleinberg, É. Tardos著,张立昂,屈婉玲译 | 清华大学出版社 | 第1版 | 2007.3 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /activity_selection.cpp: -------------------------------------------------------------------------------- 1 | //利用贪心算法求解活动选择问题 2 | #include 3 | using namespace std; 4 | #define n 5 //商品数量 5 | struct action 6 | { 7 | int s ;//起始时间 8 | int f;//结束时间 9 | int index;//活动的编号 10 | }; 11 | //利用二分归并排序对结束时间进行排序 12 | void Merge(action *a,int p, int q, int r) 13 | { 14 | int n1 = q - p + 1; //左部分的的元素个数 15 | int n2 = r - q; //同上 16 | int i, j, k; 17 | action *L = new action[n1+1]; 18 | action *R = new action[n2+1]; 19 | for(i=0;i=a[k].f) 78 | { 79 | cout<<"choose action "< 7 | 8 | using namespace std; 9 | 10 | int64_t Fib(int n) 11 | { 12 | if (n == 0) 13 | return 0; 14 | else if (n == 1) 15 | return 1; 16 | else 17 | return Fib(n - 1) + Fib(n - 2); 18 | } 19 | 20 | int main(int argc, char const *argv[]) 21 | { 22 | for (int i = 0; i < 100; i++) 23 | { 24 | cout << "Fib(" << i << ")" 25 | << "=" << Fib(i) << endl; 26 | } 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /divide_and_conque/binary_search.py: -------------------------------------------------------------------------------- 1 | # Python Program for recursive binary search. 2 | 3 | # Returns index of x in arr if present, else -1 4 | def binarySearch (arr, l, r, x): 5 | 6 | # Check base case 7 | if r >= l: 8 | 9 | mid = l + (r - l)/2 10 | 11 | # If element is present at the middle itself 12 | if arr[mid] == x: 13 | return mid 14 | 15 | # If element is smaller than mid, then it 16 | # can only be present in left subarray 17 | elif arr[mid] > x: 18 | return binarySearch(arr, l, mid-1, x) 19 | 20 | # Else the element can only be present 21 | # in right subarray 22 | else: 23 | return binarySearch(arr, mid+1, r, x) 24 | 25 | else: 26 | # Element is not present in the array 27 | return -1 28 | 29 | # Test array 30 | arr = [ 2, 3, 4, 10, 40 ] 31 | x = 50 32 | 33 | # Function call 34 | result = binarySearch(arr, 0, len(arr)-1, x) 35 | 36 | if result != -1: 37 | print "Element is present at index %d" % result 38 | else: 39 | print "Element is not present in array" 40 | -------------------------------------------------------------------------------- /divide_and_conque/fib.py: -------------------------------------------------------------------------------- 1 | def F(n): 2 | if n == 0: return 0 3 | elif n == 1: return 1 4 | else: return F(n-1)+F(n-2) 5 | 6 | def M(n): 7 | if n == 0: return 1 8 | else: return M(n-1)*n 9 | 10 | for i in range(5): 11 | print F(i) 12 | 13 | print "____________" 14 | 15 | for i in range(10): 16 | print M(i) 17 | -------------------------------------------------------------------------------- /divide_and_conque/hanoi.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | void Hanoi(int n, char A, char B, char C) 6 | { 7 | if (n == 1) 8 | { 9 | //圆盘只有一个时,只需将其从A塔移到C塔 10 | cout << "move " << n << " from " << A << " to " << C << endl; 11 | } 12 | else 13 | { 14 | Hanoi(n - 1, A, C, B);//递归,把A塔上编号1~n-1的圆盘移到B上,以C为辅助塔 15 | cout << "move " << n << " from " << A << " to " << C << endl;//把A塔上编号为n的圆盘移到C上 16 | Hanoi(n - 1, B, A, C);//递归,把B塔上编号1~n-1的圆盘移到C上,以A为辅助塔 17 | } 18 | } 19 | 20 | void Hanoi(int n) 21 | { 22 | if (n <= 0) 23 | return; 24 | Hanoi(n, 'A', 'B', 'C'); 25 | } 26 | 27 | int main() 28 | { 29 | int a = 0; 30 | cout << "输入盘数: " << endl; 31 | cin >> a; 32 | Hanoi(a); 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /divide_and_conque/hanoi.py: -------------------------------------------------------------------------------- 1 | def hanoi(n, source, helper, target): 2 | # print "hanoi( ", n, source, helper, target, " called" 3 | if n > 0: 4 | # move tower of size n - 1 to helper: 5 | hanoi(n - 1, source, target, helper) 6 | # move disk from source peg to target peg 7 | if source[0]: 8 | disk = source[0].pop() 9 | print ("moving " + str(disk) + " from " + source[1] + " to " + target[1]) 10 | target[0].append(disk) 11 | # move tower of size n-1 from helper to target 12 | hanoi(n - 1, helper, source, target) 13 | 14 | source = ([5,4,3,2,1], "A") 15 | #source = ([2,1], "source") 16 | target = ([], "C") 17 | helper = ([], "B") 18 | hanoi(len(source[0]),source,helper,target) 19 | 20 | print (source, helper, target) 21 | -------------------------------------------------------------------------------- /divide_and_conque/karatsuba.py: -------------------------------------------------------------------------------- 1 | def karatsuba(num1, num2): 2 | num1Str = str(num1) 3 | num2Str = str(num2) 4 | if (num1 < 10) or (num2 < 10): 5 | return num1*num2 6 | 7 | maxLength = max(len(num1Str), len(num2Str)) 8 | splitPosition = maxLength / 2 9 | high1, low1= int(num1Str[:-splitPosition]), int(num1Str[-splitPosition:]) 10 | high2, low2= int(num2Str[:-splitPosition]), int(num2Str[-splitPosition:]) 11 | z0 = karatsuba(low1, low2) 12 | z1 = karatsuba((low1 + high1), (low2 + high2)) 13 | z2 = karatsuba(high1, high2) 14 | 15 | return (z2*10**(2*splitPosition)) + ((z1-z2-z0)*10**(splitPosition))+z0 16 | 17 | print("300 * 500 = %ld" % karatsuba( 300, 500) ) 18 | -------------------------------------------------------------------------------- /divide_and_conque/matrix.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | from optparse import OptionParser 5 | from math import ceil, log 6 | import random 7 | random.seed(1234) 8 | 9 | def createRandomMatrix(n): 10 | maxVal = 1000 # I don't want to get Java / C++ into trouble 11 | matrix = [] 12 | for i in xrange(n): 13 | matrix.append([random.randint(0,maxVal) for el in xrange(n)]) 14 | return matrix 15 | 16 | def saveMatrix(matrixA, matrixB, filename): 17 | f = open(filename, 'w') 18 | for i, matrix in enumerate([matrixA, matrixB]): 19 | if i != 0: 20 | f.write("\n") 21 | for line in matrix: 22 | f.write("\t".join(map(str, line)) + "\n") 23 | n = 3 24 | matrixA = createRandomMatrix(n) 25 | matrixB = createRandomMatrix(n) 26 | saveMatrix(matrixA, matrixB, "2000.in") 27 | 28 | def read(filename): 29 | lines = open(filename, 'r').read().splitlines() 30 | A = [] 31 | B = [] 32 | matrix = A 33 | for line in lines: 34 | if line != "": 35 | matrix.append(map(int, line.split("\t"))) 36 | else: 37 | matrix = B 38 | return A, B 39 | 40 | def printMatrix(matrix): 41 | for line in matrix: 42 | print "\t".join(map(str,line)) 43 | 44 | def ikjMatrixProduct(A, B): 45 | n = len(A) 46 | C = [[0 for i in xrange(n)] for j in xrange(n)] 47 | for i in xrange(n): 48 | for k in xrange(n): 49 | for j in xrange(n): 50 | C[i][j] += A[i][k] * B[k][j] 51 | return C 52 | 53 | def add(A, B): 54 | n = len(A) 55 | C = [[0 for j in xrange(0, n)] for i in xrange(0, n)] 56 | for i in xrange(0, n): 57 | for j in xrange(0, n): 58 | C[i][j] = A[i][j] + B[i][j] 59 | return C 60 | 61 | def subtract(A, B): 62 | n = len(A) 63 | C = [[0 for j in xrange(0, n)] for i in xrange(0, n)] 64 | for i in xrange(0, n): 65 | for j in xrange(0, n): 66 | C[i][j] = A[i][j] - B[i][j] 67 | return C 68 | 69 | def strassenR(A, B): 70 | """ 71 | Implementation of the strassen algorithm. 72 | """ 73 | n = len(A) 74 | 75 | if n <= LEAF_SIZE: 76 | return ikjMatrixProduct(A, B) 77 | else: 78 | # initializing the new sub-matrices 79 | newSize = n/2 80 | a11 = [[0 for j in xrange(0, newSize)] for i in xrange(0, newSize)] 81 | a12 = [[0 for j in xrange(0, newSize)] for i in xrange(0, newSize)] 82 | a21 = [[0 for j in xrange(0, newSize)] for i in xrange(0, newSize)] 83 | a22 = [[0 for j in xrange(0, newSize)] for i in xrange(0, newSize)] 84 | 85 | b11 = [[0 for j in xrange(0, newSize)] for i in xrange(0, newSize)] 86 | b12 = [[0 for j in xrange(0, newSize)] for i in xrange(0, newSize)] 87 | b21 = [[0 for j in xrange(0, newSize)] for i in xrange(0, newSize)] 88 | b22 = [[0 for j in xrange(0, newSize)] for i in xrange(0, newSize)] 89 | 90 | aResult = [[0 for j in xrange(0, newSize)] for i in xrange(0, newSize)] 91 | bResult = [[0 for j in xrange(0, newSize)] for i in xrange(0, newSize)] 92 | 93 | # dividing the matrices in 4 sub-matrices: 94 | for i in xrange(0, newSize): 95 | for j in xrange(0, newSize): 96 | a11[i][j] = A[i][j] # top left 97 | a12[i][j] = A[i][j + newSize] # top right 98 | a21[i][j] = A[i + newSize][j] # bottom left 99 | a22[i][j] = A[i + newSize][j + newSize] # bottom right 100 | 101 | b11[i][j] = B[i][j] # top left 102 | b12[i][j] = B[i][j + newSize] # top right 103 | b21[i][j] = B[i + newSize][j] # bottom left 104 | b22[i][j] = B[i + newSize][j + newSize] # bottom right 105 | 106 | # Calculating p1 to p7: 107 | aResult = add(a11, a22) 108 | bResult = add(b11, b22) 109 | p1 = strassenR(aResult, bResult) # p1 = (a11+a22) * (b11+b22) 110 | 111 | aResult = add(a21, a22) # a21 + a22 112 | p2 = strassenR(aResult, b11) # p2 = (a21+a22) * (b11) 113 | 114 | bResult = subtract(b12, b22) # b12 - b22 115 | p3 = strassenR(a11, bResult) # p3 = (a11) * (b12 - b22) 116 | 117 | bResult = subtract(b21, b11) # b21 - b11 118 | p4 =strassenR(a22, bResult) # p4 = (a22) * (b21 - b11) 119 | 120 | aResult = add(a11, a12) # a11 + a12 121 | p5 = strassenR(aResult, b22) # p5 = (a11+a12) * (b22) 122 | 123 | aResult = subtract(a21, a11) # a21 - a11 124 | bResult = add(b11, b12) # b11 + b12 125 | p6 = strassenR(aResult, bResult) # p6 = (a21-a11) * (b11+b12) 126 | 127 | aResult = subtract(a12, a22) # a12 - a22 128 | bResult = add(b21, b22) # b21 + b22 129 | p7 = strassenR(aResult, bResult) # p7 = (a12-a22) * (b21+b22) 130 | 131 | # calculating c21, c21, c11 e c22: 132 | c12 = add(p3, p5) # c12 = p3 + p5 133 | c21 = add(p2, p4) # c21 = p2 + p4 134 | 135 | aResult = add(p1, p4) # p1 + p4 136 | bResult = add(aResult, p7) # p1 + p4 + p7 137 | c11 = subtract(bResult, p5) # c11 = p1 + p4 - p5 + p7 138 | 139 | aResult = add(p1, p3) # p1 + p3 140 | bResult = add(aResult, p6) # p1 + p3 + p6 141 | c22 = subtract(bResult, p2) # c22 = p1 + p3 - p2 + p6 142 | 143 | # Grouping the results obtained in a single matrix: 144 | C = [[0 for j in xrange(0, n)] for i in xrange(0, n)] 145 | for i in xrange(0, newSize): 146 | for j in xrange(0, newSize): 147 | C[i][j] = c11[i][j] 148 | C[i][j + newSize] = c12[i][j] 149 | C[i + newSize][j] = c21[i][j] 150 | C[i + newSize][j + newSize] = c22[i][j] 151 | return C 152 | 153 | def strassen(A, B): 154 | assert type(A) == list and type(B) == list 155 | assert len(A) == len(A[0]) == len(B) == len(B[0]) 156 | 157 | # Make the matrices bigger so that you can apply the strassen 158 | # algorithm recursively without having to deal with odd 159 | # matrix sizes 160 | nextPowerOfTwo = lambda n: 2**int(ceil(log(n,2))) 161 | n = len(A) 162 | m = nextPowerOfTwo(n) 163 | APrep = [[0 for i in xrange(m)] for j in xrange(m)] 164 | BPrep = [[0 for i in xrange(m)] for j in xrange(m)] 165 | for i in xrange(n): 166 | for j in xrange(n): 167 | APrep[i][j] = A[i][j] 168 | BPrep[i][j] = B[i][j] 169 | CPrep = strassenR(APrep, BPrep) 170 | C = [[0 for i in xrange(n)] for j in xrange(n)] 171 | for i in xrange(n): 172 | for j in xrange(n): 173 | C[i][j] = CPrep[i][j] 174 | return C 175 | 176 | if __name__ == "__main__": 177 | parser = OptionParser() 178 | parser.add_option("-i", dest="filename", default="2000.in", 179 | help="input file with two matrices", metavar="FILE") 180 | parser.add_option("-l", dest="LEAF_SIZE", default="8", 181 | help="when do you start using ikj", metavar="LEAF_SIZE") 182 | (options, args) = parser.parse_args() 183 | 184 | LEAF_SIZE = options.LEAF_SIZE 185 | A, B = read(options.filename) 186 | 187 | C = strassen(A, B) 188 | printMatrix(C) 189 | -------------------------------------------------------------------------------- /divide_and_conque/merge_sort.py: -------------------------------------------------------------------------------- 1 | def merge(left, right): 2 | merged_arr = [] 3 | i = 0 4 | j = 0 5 | inv_cnt = 0 6 | 7 | while i < len(left) and j < len(right): 8 | if left[i] <= right[j]: 9 | merged_arr.append(left[i]) 10 | i += 1 11 | else: 12 | merged_arr.append(right[j]) 13 | j += 1 14 | inv_cnt += (len(left) - i) 15 | 16 | merged_arr += left[i:] 17 | merged_arr += right[j:] 18 | 19 | return merged_arr, inv_cnt 20 | 21 | 22 | def merge_sort( 23 | arr 24 | ): # this function will return a tuple as (sorted_array, inversion_count) 25 | if len(arr) > 1: 26 | mid = len(arr) // 2 27 | left = arr[:mid] 28 | right = arr[mid:] 29 | 30 | left, left_inv_cnt = merge_sort(left) 31 | right, right_inv_cnt = merge_sort(right) 32 | merged, merged_inv_cnt = merge(left, right) 33 | return merged, (left_inv_cnt + right_inv_cnt + merged_inv_cnt) 34 | else: 35 | return arr, 0 36 | 37 | 38 | arr = [1, 8, 3, 4, 9, 3] 39 | sorted_array, inversion_count = merge_sort(arr) 40 | 41 | print("Sorted array:", sorted_array, 42 | " and Inversion count = %s" % inversion_count) 43 | -------------------------------------------------------------------------------- /divide_and_conque/permutations: -------------------------------------------------------------------------------- 1 | //中心思想: 2 | //设R={r1,r2,…,rn}是要进行排列的n个元素,Ri=R-{ri}. 3 | //Perm(X)表示在全排列Perm(X)的每一个排列前加上前缀ri得到的排列。 4 | //(1)当n=1时,Perm(R)=(r),其中r是集合R中唯一的元素; 5 | //(2)当n>1时,Perm(R)可由(r1)+Perm(R1),(r2)+Perm(R2),…,(rn)+Perm(Rn)构成。 6 | 7 | 8 | #include 9 | using namespace std; 10 | void swap(int &a,int &b){ 11 | int temp=a; 12 | a=b; 13 | b=temp; 14 | } 15 | void perm(int list[],int low,int high){ 16 | if(low==high){ //当low==high时,此时list就是其中一个排列,输出list 17 | for(int i=0;i<=low;i++) 18 | cout< 2 | #include 3 | using namespace std; 4 | 5 | int knapsack(int count,int capacity,vector& weights,vector& values,vector>& res) 6 | { 7 | for(int i=1;i<=count;i++) 8 | { 9 | for(int j=1;j<=capacity;j++) 10 | { 11 | if(weights[i] > j) 12 | { 13 | res[i][j]=res[i-1][j]; 14 | } 15 | else 16 | { 17 | res[i][j] = max( res[i-1][j-weights[i]] + values[i] , res[i-1][j]); 18 | } 19 | 20 | } 21 | } 22 | return res[count][capacity]; 23 | } 24 | 25 | int main() 26 | { 27 | int count,capacity; 28 | cout << "please input products count and knapsack's capacity: " << endl; // 输入商品数量和背包容量 29 | cin>>count>>capacity; 30 | vector weights(count + 1,0); 31 | vector values(count + 1,0); 32 | cout << "please input weight array for " << count << " products" << endl; 33 | for(int i=1;i<=count;i++) 34 | cin>>weights[i]; 35 | cout << "please input value array for " << count << " products" << endl; 36 | for(int i=1;i<=count;i++) 37 | cin>>values[i]; 38 | vector> res(count + 1,vector (capacity + 1,0)); 39 | knapsack(count,capacity,weights,values,res); 40 | cout << "knapsack result is " << res[count][capacity] << endl; 41 | 42 | return 0; 43 | 44 | 45 | } -------------------------------------------------------------------------------- /dynamic_programming/01背包.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | int bag(int count,int cap,vector& weights,vector& values,vector>& res) 5 | { 6 | for(int i=1;i<=cap;i++) 7 | { 8 | for(int j=1;j<=count;j++) 9 | { 10 | if(weights[j]>i) 11 | { 12 | res[j][i]=res[j-1][i]; 13 | } 14 | else 15 | { 16 | res[j][i]=max(res[j-1][i-weights[j]]+values[j],res[j-1][i]); 17 | } 18 | } 19 | } 20 | return res[count][cap]; 21 | } 22 | 23 | int main() 24 | { 25 | int count,cap; 26 | 27 | cin >>count>>cap; 28 | vector weights(count+1,0); 29 | for(int i=0;i>weights[i]; 32 | } 33 | vector values(count+1,0); 34 | for(int i=0;i>values[i]; 37 | } 38 | vector> res(count+1,vector (cap+1,0)); 39 | bag(count,cap,weights,values,res); 40 | cout << res[count][cap]; 41 | return 0; 42 | } -------------------------------------------------------------------------------- /dynamic_programming/cut_rod.py: -------------------------------------------------------------------------------- 1 | #https://www.geeksforgeeks.org/cutting-a-rod-dp-13/ 2 | 3 | # A Dynamic Programming solution for Rod cutting problem 4 | INT_MIN = -32767 5 | 6 | # Returns the best obtainable price for a rod of length n and 7 | # price[] as prices of different pieces 8 | def cutRod(price, n): 9 | val = [0 for x in range(n+1)] 10 | val[0] = 0 11 | 12 | # Build the table val[] in bottom up manner and return 13 | # the last entry from the table 14 | for i in range(1, n+1): 15 | max_val = INT_MIN 16 | for j in range(i): 17 | max_val = max(max_val, price[j] + val[i-j-1]) 18 | val[i] = max_val 19 | 20 | return val[n] 21 | 22 | # Driver program to test above functions 23 | arr = [1, 5, 8, 9, 10, 17, 17, 20] 24 | size = len(arr) 25 | print("Maximum Obtainable Value is " + str(cutRod(arr, size))) 26 | 27 | # This code is contributed by Bhavya Jain 28 | -------------------------------------------------------------------------------- /dynamic_programming/cut_rod_naive.py: -------------------------------------------------------------------------------- 1 | #https://www.geeksforgeeks.org/cutting-a-rod-dp-13/ 2 | 3 | # A Naive recursive solution 4 | # for Rod cutting problem 5 | import sys 6 | 7 | # A utility function to get the 8 | # maximum of two integers 9 | def max(a, b): 10 | return a if (a > b) else b 11 | 12 | # Returns the best obtainable price for a rod of length n 13 | # and price[] as prices of different pieces 14 | def cutRod(price, n): 15 | if(n <= 0): 16 | return 0 17 | max_val = -sys.maxsize-1 18 | 19 | # Recursively cut the rod in different pieces 20 | # and compare different configurations 21 | for i in range(0, n): 22 | max_val = max(max_val, price[i] + 23 | cutRod(price, n - i - 1)) 24 | return max_val 25 | 26 | # Driver code 27 | arr = [1, 5, 8, 9, 10, 17, 17, 20] 28 | size = len(arr) 29 | print("Maximum Obtainable Value is", cutRod(arr, size)) 30 | -------------------------------------------------------------------------------- /dynamic_programming/knapsack.py: -------------------------------------------------------------------------------- 1 | #https://www.geeksforgeeks.org/0-1-knapsack-problem-dp-10/ 2 | # A Dynamic Programming based Python Program for 0-1 Knapsack problem 3 | # Returns the maximum value that can be put in a knapsack of capacity W 4 | def knapSack(W, wt, val, n): 5 | K = [[0 for x in range(W+1)] for x in range(n+1)] 6 | 7 | # Build table K[][] in bottom up manner 8 | for i in range(n+1): 9 | for w in range(W+1): 10 | if i==0 or w==0: 11 | K[i][w] = 0 12 | elif wt[i-1] <= w: 13 | K[i][w] = max(val[i-1] + K[i-1][w-wt[i-1]], K[i-1][w]) 14 | else: 15 | K[i][w] = K[i-1][w] 16 | 17 | return K[n][W] 18 | 19 | # Driver program to test above function 20 | val = [60, 100, 120] 21 | wt = [10, 20, 30] 22 | W = 50 23 | n = len(val) 24 | print(knapSack(W, wt, val, n)) 25 | 26 | # This code is contributed by Bhavya Jain 27 | -------------------------------------------------------------------------------- /dynamic_programming/lcs.py: -------------------------------------------------------------------------------- 1 | #https://www.geeksforgeeks.org/longest-common-subsequence-dp-4/ 2 | # Dynamic Programming implementation of LCS problem 3 | 4 | def lcs(X , Y): 5 | # find the length of the strings 6 | m = len(X) 7 | n = len(Y) 8 | 9 | # declaring the array for storing the dp values 10 | L = [[None]*(n+1) for i in xrange(m+1)] 11 | 12 | """Following steps build L[m+1][n+1] in bottom up fashion 13 | Note: L[i][j] contains length of LCS of X[0..i-1] 14 | and Y[0..j-1]""" 15 | for i in range(m+1): 16 | for j in range(n+1): 17 | if i == 0 or j == 0 : 18 | L[i][j] = 0 19 | elif X[i-1] == Y[j-1]: 20 | L[i][j] = L[i-1][j-1]+1 21 | else: 22 | L[i][j] = max(L[i-1][j] , L[i][j-1]) 23 | 24 | # L[m][n] contains the length of LCS of X[0..n-1] & Y[0..m-1] 25 | return L[m][n] 26 | #end of function lcs 27 | 28 | 29 | # Driver program to test the above function 30 | X = "AGGTAB" 31 | Y = "GXTXAYB" 32 | print "Length of LCS is ", lcs(X, Y) 33 | 34 | # This code is contributed by Nikhil Kumar Singh(nickzuck_007) 35 | 36 | -------------------------------------------------------------------------------- /dynamic_programming/lianchengji.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | const int L = 7; 5 | 6 | int RecurMatrixChain(int i,int j,int **s,int *p);//递归求最优解 7 | void Traceback(int i,int j,int **s);//构造最优解 8 | 9 | int main() 10 | { 11 | int p[L]={30,35,15,5,10,20,25}; 12 | 13 | int **s = new int *[L]; 14 | for(int i=0;i 3 | using namespace std; 4 | #define n 5 //商品数量 5 | struct bag 6 | { 7 | int p ;//商品价值 8 | int v;//商品体积 9 | double c ;//商品的性价比 10 | int index;//商品编号 11 | }; 12 | //利用二分归并排序对性价比进行排序 13 | void Merge(bag *a,int p, int q, int r) 14 | { 15 | int n1 = q - p + 1; //左部分的的元素个数 16 | int n2 = r - q; //同上 17 | int i, j, k; 18 | bag *L = new bag[n1+1]; 19 | bag *R = new bag[n2+1]; 20 | for(i=0;i0&&i>''' 57 | return len([tup for tup in population if tup[1] == 1.0]) * 1.0 / len(population) >= threshold 58 | 59 | def main(population): 60 | '''进化 generation 次,每次进化都淘汰最不相似的样本,保留最相似样本''' 61 | best_similarity = [] 62 | avg_similarity = [] 63 | worst_similarity = [] 64 | 65 | population = [(candidate, similarity(candidate, target)) for candidate in population] 66 | population.sort(key=lambda tup:tup[1], reverse=True) 67 | generation = 0 68 | 69 | best_similarity.append(population[0][1]) 70 | avg_similarity.append(sum([tup[1] for tup in population]) * 1.0 / len(population)) 71 | worst_similarity.append(population[-1][1]) 72 | 73 | while True: 74 | if reach_threshold(population): 75 | print "reach threshold in %d generation." % generation 76 | break 77 | if generation > max_generation: 78 | print 'max_generation reached.' 79 | break 80 | 81 | new_population = [] 82 | for j in xrange(int(reproduction_rate * n)): 83 | child = mutation(mating(random_element(population)[0], random_element(population)[0])) 84 | new_population.append((child, similarity(child, target))) 85 | new_population.sort(key=lambda tup:tup[1], reverse=True) 86 | population = new_population[:n] 87 | generation += 1 88 | 89 | best_similarity.append(population[0][1]) 90 | avg_similarity.append(sum([tup[1] for tup in population]) * 1.0 / len(population)) 91 | worst_similarity.append(population[-1][1]) 92 | 93 | population = [tup[0] for tup in population] 94 | return population, generation, (best_similarity, avg_similarity, worst_similarity) 95 | 96 | population = [random_string(len(target)) for i in xrange(n)] # 初始种群 97 | result, generation, statistics = main(population) 98 | 99 | X = range(generation+1) 100 | plt.plot(X, statistics[0], color="blue", label='best similarity') 101 | plt.plot(X, statistics[1], color="green", label='avg similarity') 102 | plt.plot(X, statistics[2], color="red", label='worst similarity') 103 | plt.legend(loc='upper left', frameon=False) 104 | plt.xlabel('generation') 105 | plt.ylabel('similarity') 106 | plt.show() 107 | print result[0] 108 | print result[-1] 109 | -------------------------------------------------------------------------------- /genetic_algorithm/ga_tsp.py: -------------------------------------------------------------------------------- 1 | import numpy as np, random, operator, pandas as pd, matplotlib.pyplot as plt 2 | 3 | class City: 4 | def __init__(self, x, y): 5 | self.x = x 6 | self.y = y 7 | 8 | def distance(self, city): 9 | xDis = abs(self.x - city.x) 10 | yDis = abs(self.y - city.y) 11 | distance = np.sqrt((xDis ** 2) + (yDis ** 2)) 12 | return distance 13 | 14 | def __repr__(self): 15 | return "(" + str(self.x) + "," + str(self.y) + ")" 16 | 17 | class Fitness: 18 | def __init__(self, route): 19 | self.route = route 20 | self.distance = 0 21 | self.fitness= 0.0 22 | 23 | def routeDistance(self): 24 | if self.distance ==0: 25 | pathDistance = 0 26 | for i in range(0, len(self.route)): 27 | fromCity = self.route[i] 28 | toCity = None 29 | if i + 1 < len(self.route): 30 | toCity = self.route[i + 1] 31 | else: 32 | toCity = self.route[0] 33 | pathDistance += fromCity.distance(toCity) 34 | self.distance = pathDistance 35 | return self.distance 36 | 37 | def routeFitness(self): 38 | if self.fitness == 0: 39 | self.fitness = 1 / float(self.routeDistance()) 40 | return self.fitness 41 | 42 | def createRoute(cityList): 43 | route = random.sample(cityList, len(cityList)) 44 | return route 45 | 46 | def initialPopulation(popSize, cityList): 47 | population = [] 48 | 49 | for i in range(0, popSize): 50 | population.append(createRoute(cityList)) 51 | return population 52 | 53 | def rankRoutes(population): 54 | fitnessResults = {} 55 | for i in range(0,len(population)): 56 | fitnessResults[i] = Fitness(population[i]).routeFitness() 57 | return sorted(fitnessResults.items(), key = operator.itemgetter(1), reverse = True) 58 | 59 | def selection(popRanked, eliteSize): 60 | selectionResults = [] 61 | df = pd.DataFrame(np.array(popRanked), columns=["Index","Fitness"]) 62 | df['cum_sum'] = df.Fitness.cumsum() 63 | df['cum_perc'] = 100*df.cum_sum/df.Fitness.sum() 64 | 65 | for i in range(0, eliteSize): 66 | selectionResults.append(popRanked[i][0]) 67 | for i in range(0, len(popRanked) - eliteSize): 68 | pick = 100*random.random() 69 | for i in range(0, len(popRanked)): 70 | if pick <= df.iat[i,3]: 71 | selectionResults.append(popRanked[i][0]) 72 | break 73 | return selectionResults 74 | 75 | def matingPool(population, selectionResults): 76 | matingpool = [] 77 | for i in range(0, len(selectionResults)): 78 | index = selectionResults[i] 79 | matingpool.append(population[index]) 80 | return matingpool 81 | 82 | def breed(parent1, parent2): 83 | child = [] 84 | childP1 = [] 85 | childP2 = [] 86 | 87 | geneA = int(random.random() * len(parent1)) 88 | geneB = int(random.random() * len(parent1)) 89 | 90 | startGene = min(geneA, geneB) 91 | endGene = max(geneA, geneB) 92 | 93 | for i in range(startGene, endGene): 94 | childP1.append(parent1[i]) 95 | 96 | childP2 = [item for item in parent2 if item not in childP1] 97 | 98 | child = childP1 + childP2 99 | return child 100 | 101 | def breedPopulation(matingpool, eliteSize): 102 | children = [] 103 | length = len(matingpool) - eliteSize 104 | pool = random.sample(matingpool, len(matingpool)) 105 | 106 | for i in range(0,eliteSize): 107 | children.append(matingpool[i]) 108 | 109 | for i in range(0, length): 110 | child = breed(pool[i], pool[len(matingpool)-i-1]) 111 | children.append(child) 112 | return children 113 | 114 | def mutate(individual, mutationRate): 115 | for swapped in range(len(individual)): 116 | if(random.random() < mutationRate): 117 | swapWith = int(random.random() * len(individual)) 118 | 119 | city1 = individual[swapped] 120 | city2 = individual[swapWith] 121 | 122 | individual[swapped] = city2 123 | individual[swapWith] = city1 124 | return individual 125 | 126 | def mutatePopulation(population, mutationRate): 127 | mutatedPop = [] 128 | 129 | for ind in range(0, len(population)): 130 | mutatedInd = mutate(population[ind], mutationRate) 131 | mutatedPop.append(mutatedInd) 132 | return mutatedPop 133 | 134 | def nextGeneration(currentGen, eliteSize, mutationRate): 135 | popRanked = rankRoutes(currentGen) 136 | selectionResults = selection(popRanked, eliteSize) 137 | matingpool = matingPool(currentGen, selectionResults) 138 | children = breedPopulation(matingpool, eliteSize) 139 | nextGeneration = mutatePopulation(children, mutationRate) 140 | return nextGeneration 141 | 142 | def geneticAlgorithm(population, popSize, eliteSize, mutationRate, generations): 143 | pop = initialPopulation(popSize, population) 144 | print("Initial distance: " + str(1 / rankRoutes(pop)[0][1])) 145 | 146 | for i in range(0, generations): 147 | pop = nextGeneration(pop, eliteSize, mutationRate) 148 | 149 | print("Final distance: " + str(1 / rankRoutes(pop)[0][1])) 150 | bestRouteIndex = rankRoutes(pop)[0][0] 151 | bestRoute = pop[bestRouteIndex] 152 | return bestRoute 153 | 154 | cityList = [] 155 | 156 | for i in range(0,25): 157 | cityList.append(City(x=int(random.random() * 200), y=int(random.random() * 200))) 158 | 159 | geneticAlgorithm(population=cityList, popSize=100, eliteSize=20, mutationRate=0.01, generations=500) 160 | 161 | def geneticAlgorithmPlot(population, popSize, eliteSize, mutationRate, generations): 162 | pop = initialPopulation(popSize, population) 163 | progress = [] 164 | progress.append(1 / rankRoutes(pop)[0][1]) 165 | 166 | for i in range(0, generations): 167 | pop = nextGeneration(pop, eliteSize, mutationRate) 168 | progress.append(1 / rankRoutes(pop)[0][1]) 169 | 170 | plt.plot(progress) 171 | plt.ylabel('Distance') 172 | plt.xlabel('Generation') 173 | plt.show() 174 | 175 | geneticAlgorithmPlot(population=cityList, popSize=100, eliteSize=20, mutationRate=0.01, generations=500) 176 | -------------------------------------------------------------------------------- /greedy.py: -------------------------------------------------------------------------------- 1 | #https://gist.github.com/gcallah/bb22ea72d8b15fa965d2f50e6798ae50 2 | 3 | #!/usr/bin/env python 4 | # -*- coding: utf-8 -*- 5 | """ 6 | This file contains Python implementations of greedy algorithms 7 | from Intro to Algorithms (Cormen et al.). 8 | The aim here is not efficient Python implementations 9 | but to duplicate the pseudo-code in the book as closely as possible. 10 | Also, since the goal is to help students to see how the algorithm 11 | works, there are print statements placed at key points in the code. 12 | The performance of each function is stated in the docstring, and 13 | loop invariants are expressed as assert statements when they 14 | are not too complex. 15 | This file contains: 16 | recursive_activity_selector() 17 | greedy_activity_selector() 18 | """ 19 | 20 | smalls = [1] 21 | smallf = [0, 4] 22 | 23 | start = [0, 1, 3, 0, 5, 3, 5, 6, 8, 8, 2, 12] 24 | finish = [0, 4, 5, 6, 7, 9, 9, 10, 11, 12, 14, 16] 25 | 26 | def recursive_activity_selector(s, f, k, n): 27 | """ 28 | Args: 29 | s: a list of start times 30 | f: a list of finish times 31 | k: current position in 32 | n: total possible activities 33 | Returns: 34 | A maximal set of activities that can be scheduled. 35 | (We use a list to hold the set.) 36 | """ 37 | m = k + 1 38 | while m < n and s[m] < f[k]: # find an activity starting after our last 39 | # finish 40 | m = m + 1 41 | if m < n: 42 | print("Adding activity " + str(m) + " that finishes at " 43 | + str(f[m])) 44 | return [m] + recursive_activity_selector(s, f, m, n) 45 | else: 46 | return [] 47 | 48 | 49 | def greedy_activity_selector(s, f): 50 | """ 51 | Args: 52 | s: a list of start times 53 | f: a list of finish times 54 | Returns: 55 | A maximal set of activities that can be scheduled. 56 | (We use a list to hold the set.) 57 | """ 58 | assert(len(s) == len(f)) # each start time must match a finish time 59 | n = len(s) # could be len f as well! 60 | a = [] 61 | k = 0 62 | for m in range(1, n): 63 | if s[m] >= f[k]: 64 | a.append(m) 65 | k = m 66 | return a 67 | -------------------------------------------------------------------------------- /greedy_algorithm/0-1_package.py: -------------------------------------------------------------------------------- 1 | class goods: 2 | def __init__(self, name, weight=0, value=0): 3 | self.name = name 4 | self.weight = weight 5 | self.value = value 6 | def __repr__(self): 7 | return self.__str__() 8 | def __str__(self): 9 | return "('%s',%d,%.2f)" % (self.name, self.weight, self.value) 10 | 11 | def knapsack(bag_volume=0, goods_set=[]): 12 | #利用lambda函数对goods_set以单位价值作为规则进行排序,由大到小排列 13 | goods_set.sort(key=lambda x: x.value / x.weight, reverse=True) 14 | result = [] 15 | the_cost = 0 16 | for good in goods_set: 17 | if bag_volume < good.weight: 18 | break 19 | #如果存在空间,则将此商品装入背包即放进result中,同时修改背包容量 20 | else: 21 | result.append(good) 22 | bag_volume = bag_volume - good.weight 23 | 24 | if len(result) < len(goods_set) and bag_volume != 0: 25 | result.append(goods(good.name, bag_volume, good.value *(bag_volume / 26 | good.weight))) 27 | #计算背包的最终价值the_cost并输出(保留两位小数) 28 | for x in result: 29 | the_cost += x.value 30 | print('%.2f' % the_cost) 31 | return result 32 | 33 | if __name__ == '__main__': 34 | some_goods = [goods(0, 3, 5), goods(1, 5, 7), goods(2, 6, 2), goods(3, 4, 7), goods(4, 1, 3)] 35 | #调用knapsack函数,输出背包容量为6公斤时候背包的最大价值与商品选择 36 | print(knapsack(6, some_goods)) 37 | -------------------------------------------------------------------------------- /greedy_algorithm/Dijkstra.py: -------------------------------------------------------------------------------- 1 | # dijjkstra算法(原生最短路径,还未优化) 2 | def dij(start, graph): 3 | n = len(graph) 4 | # 初始化各项数据,把costs[start]初始化为0,其他为无穷大 5 | # 把各个顶点的父结点设置成-1 6 | costs = [99999 for _ in range(n)] 7 | costs[start] = 0 8 | parents = [-1 for _ in range(n)] 9 | visited = [False for _ in range(n)] # 标记已确定好最短花销的点 10 | t = [] # 已经确定好最短花销的点列表 11 | while len(t) < n: 12 | # 从costs里面找最短花销(找还没确定的点的路径),标记这个最短边的顶点,把顶点加入t中 13 | minCost = 99999 14 | minNode = None 15 | for i in range(n): 16 | if not visited[i] and costs[i] < minCost: 17 | minCost = costs[i] 18 | minNode = i 19 | t.append(minNode) 20 | visited[minNode] = True 21 | 22 | # 从这个顶点出发,遍历与它相邻的顶点的边,计算最短路径,更新costs和parents 23 | for edge in graph[minNode]: 24 | if not visited[edge[0]] and minCost + edge[1] < costs[edge[0]]: 25 | costs[edge[0]] = minCost + edge[1] 26 | parents[edge[0]] = minNode 27 | return costs, parents 28 | 29 | 30 | # 主程序 31 | 32 | # Data 33 | data = [ 34 | [1, 0, 8], 35 | [1, 2, 5], 36 | [1, 3, 10], 37 | [1, 6, 9], 38 | [2, 0, 1], 39 | [0, 6, 2], 40 | [3, 6, 5], 41 | [3, 4, 8], 42 | [0, 5, 4], 43 | [5, 6, 7], 44 | [5, 3, 8], 45 | [5, 4, 5] 46 | ] 47 | n = 7 # 结点数 48 | 49 | # 用data数据构建邻接表 50 | graph = [[] for _ in range(n)] 51 | for edge in data: 52 | graph[edge[0]].append([edge[1], edge[2]]) 53 | graph[edge[1]].append([edge[0], edge[2]]) 54 | # for edges in graph: 55 | # print(edges) 56 | 57 | # 从1开始找各点到1的最短路径(单源最短路径) 58 | # costs: 各点到店1的最短路径 59 | # parents: 各点链接的父结点,可以用parents建立最短路径生成树 60 | costs, parents = dij(1, graph) 61 | print('costs') 62 | print(costs) 63 | print('parents') 64 | print(parents) 65 | 66 | # 结果: 67 | # costs 68 | # [6, 0, 5, 10, 15, 10, 8] 69 | # parents 70 | # [2, -1, 1, 1, 5, 0, 0] 71 | 72 | -------------------------------------------------------------------------------- /greedy_algorithm/Kruskal.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 给定一个无向图G=(V,E),如果它的生成子图是连通无圈的,那么我们就称这个生成子图为生成树(Spanning Tree)。 3 | 如果是带权值的无向图,那么权值之和最小的生成树,我们就称之为最小生成树(MST, Minimum Spanning Tree)。 4 | 5 | Kruskal算法原理 6 | Kruskal算法是基于贪心的思想得到的。首先把所有的边按照权值从小到大排列,接着按照顺序选取每条边, 7 | 如果这条边的两个端点不属于同一棵树(即:不会形成圈),那么就将它们合并;如果这条边的两个端点属于 8 | 同一棵树(即:会形成圈),就舍去这条边,考虑下条边。以此类推,直到所有的点都属于同一棵树为止, 9 | 这棵树就是最小生成树。Kruskal算法是所有最小生成树算法中最为简单理解的一个,这里充分体现了贪心算法的精髓。 10 | 11 | ''' 12 | import time 13 | start = time.perf_counter() #开始计时 14 | class DisjointSet(dict): 15 | '''不相交集''' 16 | 17 | def __init__(self, dict): 18 | pass 19 | 20 | def add(self, item): 21 | self[item] = item 22 | 23 | def find(self, item): 24 | if self[item] != item: 25 | self[item] = self.find(self[item]) 26 | return self[item] 27 | 28 | def unionset(self, item1, item2): 29 | self[item2] = self[item1] 30 | 31 | def Kruskal(nodes, edges): 32 | '''基于不相交集实现Kruskal算法''' 33 | forest = DisjointSet(nodes) 34 | MST = [] 35 | for item in nodes: 36 | forest.add(item) 37 | edges = sorted(edges, key=lambda element: element[2]) 38 | num_sides = len(nodes)-1 # 最小生成树的边数等于顶点数减一 39 | for e in edges: 40 | node1, node2, _ = e 41 | parent1 = forest.find(node1) 42 | parent2 = forest.find(node2) 43 | if parent1 != parent2: 44 | MST.append(e) 45 | num_sides -= 1 46 | if num_sides == 0: 47 | return MST 48 | else: 49 | forest.unionset(parent1, parent2) 50 | pass 51 | 52 | def main(): 53 | nodes = set(list('ABCDE')) 54 | edges = [("A", "B", 1), ("A", "C", 7), 55 | ("A", "D", 3), ("B", "C", 6), 56 | ("B", "E", 4), ("C", "D", 8), 57 | ("C", "E", 5), ("D", "E", 2)] 58 | print("\n\nThe undirected graph is :", edges) 59 | print("\n\nThe minimum spanning tree by Kruskal is : ") 60 | print(Kruskal(nodes, edges)) 61 | 62 | if __name__ == '__main__': 63 | main() 64 | end = time.perf_counter() 65 | print('Running time: %f seconds'%(end-start)) 66 | import time 67 | start = time.perf_counter() 68 | class DisjointSet(dict): 69 | '''不相交集''' 70 | 71 | def __init__(self, dict): 72 | pass 73 | 74 | def add(self, item): 75 | self[item] = item 76 | 77 | def find(self, item): 78 | if self[item] != item: 79 | self[item] = self.find(self[item]) 80 | return self[item] 81 | 82 | def unionset(self, item1, item2): 83 | self[item2] = self[item1] 84 | 85 | def Kruskal(nodes, edges): 86 | '''基于不相交集实现Kruskal算法''' 87 | forest = DisjointSet(nodes) 88 | MST = [] 89 | for item in nodes: 90 | forest.add(item) 91 | edges = sorted(edges, key=lambda element: element[2]) 92 | num_sides = len(nodes)-1 # 最小生成树的边数等于顶点数减一 93 | for e in edges: 94 | node1, node2, _ = e 95 | parent1 = forest.find(node1) 96 | parent2 = forest.find(node2) 97 | if parent1 != parent2: 98 | MST.append(e) 99 | num_sides -= 1 100 | if num_sides == 0: 101 | return MST 102 | else: 103 | forest.unionset(parent1, parent2) 104 | pass 105 | 106 | def main(): 107 | nodes = set(list('ABCDEFG')) 108 | edges = [("A", "B", 7), ("A", "D", 5), 109 | ("B", "C", 8), ("B", "D", 9), ("B", "E", 7), 110 | ("C", "E", 5), ("D", "E", 15), ("D", "F", 6), 111 | ("E", "F", 8), ("E", "G", 9), ("F", "G", 11)] 112 | print("\n\nThe undirected graph is :", edges) 113 | print("\n\nThe minimum spanning tree by Kruskal is : ") 114 | print(Kruskal(nodes, edges)) 115 | 116 | if __name__ == '__main__': 117 | main() 118 | end = time.perf_counter() #结束计时 119 | print('Running time: %f seconds'%(end-start)) #程序运行时间 120 | 121 | -------------------------------------------------------------------------------- /greedy_algorithm/Prim.py: -------------------------------------------------------------------------------- 1 | #File Name : 最小生成树prim算法.py 2 | 3 | from heapq import * 4 | class Node(object): 5 | pass 6 | class UnionFindSet(object): 7 | def __init__(self,nodes): 8 | self.fatherDict = {} 9 | # key node value father 一层一层向上找 10 | self.sizeDict = {} 11 | # key 节点 value 节点所在集合共有多少个节点 12 | for node in nodes: 13 | self.fatherDict[node]= node 14 | self.sizeDict[node] = 1 15 | #每个节点的父亲是自己 并且所在的集合为个数为1 16 | #因为要少挂多 ,所以要找节点数目 17 | def FindHead(self,node): 18 | stack = [] 19 | father = self.fatherDict[node] 20 | while father!=node: 21 | stack.append(node) 22 | node = father 23 | father = self.fatherDict[node] 24 | while stack: 25 | self.fatherDict[stack.pop()] = father 26 | return father 27 | def isSameSet(self,a,b): 28 | return self.FindHead(a) == self.FindHead(b) 29 | def uion(self,a,b): 30 | if a is None or b is None: 31 | return 32 | aHead = self.FindHead(a) 33 | bHead = self.FindHead(b) 34 | if aHead!=bHead: 35 | asize = self.sizeDict[aHead] 36 | bsize = self.sizeDict[bHead] 37 | if asize<=bsize: 38 | self.fatherDict[aHead] = bHead 39 | self.sizeDict[bHead] = asize+bsize 40 | else: 41 | self.fatherDict[bHead] = aHead 42 | self.sizeDict[aHead] = asize+bsize 43 | 44 | class Node(object): 45 | def __init__(self,value=None): 46 | self.value = value #节点的值 47 | self.come = 0 #节点入度 48 | self.out = 0 #节点出度 49 | self.nexts = [] #节点的邻居节点 50 | self.edges = [] #在节点为from的情况下,边的集合 51 | class Edge(object): 52 | def __init__(self,weight=None,fro,to): 53 | self.weight = weight # 边的权重 54 | self.fro = fro # 边的from节点 55 | self.to = to #边的to节点 56 | def __lt__(self, other): 57 | return self.weight0: 98 | edge = heappop(heapq) 99 | tonode = edge.to 100 | if tonode not in set1: 101 | set1.add(tonode) 102 | res1.add(edge) 103 | for nextedge in tonode.edges: 104 | heappush(heapq,nextedge) 105 | return res1 106 | -------------------------------------------------------------------------------- /quick_sort.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int Partition (int *a,int p,int r) 5 | { 6 | int x=a[r],q; 7 | int i,j,temp; 8 | i=p-1; 9 | for(j=p;j