1. 选择排序 0(n*n)
1 //选择算法 2 void selectionSort(int arr[], int n){ 3 for(int i = 0 ; i < n ; i ++){ 4 // 寻找[i, n)区间里的最小值 5 int minIndex = i; 6 for( int j = i + 1 ; j < n ; j ++ ) 7 if( arr[j] < arr[minIndex] ) 8 minIndex = j; 9 //交换位置 10 swap( arr[i] , arr[minIndex] ); 11 } 12 }
2. 插入排序
//插入排序 void insertionSort(T arr[], int n){ for( int i = 1 ; i < n ; i ++ ) { // 寻找元素arr[i]合适的插入位置 for( int j = i ; j > 0 ; j-- ) if( arr[j] < arr[j-1] ) swap( arr[j] , arr[j-1] ); else break; return; }
3. 冒泡排序
1 // 冒泡排序 2 template<typename T> 3 void bubbleSort( T arr[] , int n){ 4 5 int newn; // 使用newn进行优化 6 7 do{ 8 newn = 0; 9 for( int i = 1 ; i < n ; i ++ ) 10 if( arr[i-1] > arr[i] ){ 11 swap( arr[i-1] , arr[i] ); 12 13 // 记录最后一次的交换位置,在此之后的元素在下一轮扫描中均不考虑 14 newn = i; 15 } 16 n = newn; 17 }while(newn > 0); 18 }
4. 归并排序
1 // 归并排序算法, 对arr[l...r]的范围进行排序 2 template<typename T> 3 void __mergeSort2(T arr[], int l, int r){ 4 5 // 对于小规模数组, 使用插入排序 6 if( r - l <= 15 ){ 7 insertionSort(arr, l, r); 8 return; 9 } 10 11 int mid = (l+r)/2; 12 __mergeSort2(arr, l, mid); 13 __mergeSort2(arr, mid+1, r); 14 15 // 对于arr[mid] <= arr[mid+1]的情况,不进行merge 16 if( arr[mid] > arr[mid+1] ) 17 __merge(arr, l, mid, r); 18 }
5. 希尔排序
// 希尔排序 template<typename T> void shellSort(T arr[], int n){ // 计算 increment sequence: 1, 4, 13, 40, 121... int h = 1; while( h < n/3 ) h = 3 * h + 1; while( h >= 1 ){ // h-sort the array for( int i = h ; i < n ; i ++ ){ // 对 arr[i], arr[i-h], arr[i-2*h], arr[i-3*h]... 使用插入排序 T e = arr[i]; int j; for( j = i ; j >= h && e < arr[j-h] ; j -= h ) arr[j] = arr[j-h]; arr[j] = e; } // 因子 h /= 3; } }
6. 自底向上的归并排序
// 使用自底向上的归并排序算法 template <typename T> void mergeSortBU(T arr[], int n){ // 对于小数组, 使用插入排序优化 for( int i = 0 ; i < n ; i += 16 ) insertionSort(arr,i,min(i+15,n-1)); for( int sz = 16; sz < n ; sz += sz ) for( int i = 0 ; i < n - sz ; i += sz+sz ) // 对于arr[mid] <= arr[mid+1]的情况,不进行merge if( arr[i+sz-1] > arr[i+sz] ) __merge(arr, i, i+sz-1, min(i+sz+sz-1,n-1) ); // Merge Sort BU 也是一个O(nlogn)复杂度的算法,虽然只使用两重for循环 }
7. 快速排序
1 // 对arr[l...r]部分进行partition操作 2 // 返回p, 使得arr[l...p-1] < arr[p] ; arr[p+1...r] > arr[p] 3 template <typename T> 4 int __partition(T arr[], int l, int r){ 5 6 T v = arr[l]; 7 8 int j = l; // arr[l+1...j] < v ; arr[j+1...i) > v 9 for( int i = l + 1 ; i <= r ; i ++ ) 10 if( arr[i] < v ){ 11 j ++; 12 swap( arr[j] , arr[i] ); 13 } 14 15 swap( arr[l] , arr[j]); 16 17 return j; 18 } 19 20 // 对arr[l...r]部分进行快速排序 21 template <typename T> 22 void __quickSort(T arr[], int l, int r){ 23 24 if( l >= r ) 25 return; 26 27 int p = __partition(arr, l, r); 28 __quickSort(arr, l, p-1 ); 29 __quickSort(arr, p+1, r); 30 } 31 32 template <typename T> 33 void quickSort(T arr[], int n){ 34 35 __quickSort(arr, 0, n-1); 36 }
8. 双路快速排序
9. 三路快速排序
1 // 递归的三路快速排序算法 2 template <typename T> 3 void __quickSort3Ways(T arr[], int l, int r){ 4 5 // 对于小规模数组, 使用插入排序进行优化 6 if( r - l <= 15 ){ 7 insertionSort(arr,l,r); 8 return; 9 } 10 11 // 随机在arr[l...r]的范围中, 选择一个数值作为标定点pivot 12 swap( arr[l], arr[rand()%(r-l+1)+l ] ); 13 14 T v = arr[l]; 15 16 int lt = l; // arr[l+1...lt] < v 17 int gt = r + 1; // arr[gt...r] > v 18 int i = l+1; // arr[lt+1...i) == v 19 while( i < gt ){ 20 if( arr[i] < v ){ 21 swap( arr[i], arr[lt+1]); 22 i ++; 23 lt ++; 24 } 25 else if( arr[i] > v ){ 26 swap( arr[i], arr[gt-1]); 27 gt --; 28 } 29 else{ // arr[i] == v 30 i ++; 31 } 32 } 33 34 swap( arr[l] , arr[lt] ); 35 36 __quickSort3Ways(arr, l, lt-1); 37 __quickSort3Ways(arr, gt, r); 38 } 39 40 template <typename T> 41 void quickSort3Ways(T arr[], int n){ 42 43 srand(time(NULL)); 44 __quickSort3Ways( arr, 0, n-1); 45 }
10. 二分查找法
1 // 用递归的方式写二分查找法 2 template<typename T> 3 int __binarySearch2(T arr[], int l, int r, T target){ 4 5 if( l > r ) 6 return -1; 7 8 //int mid = (l+r)/2; 9 // 防止极端情况下的整形溢出,使用下面的逻辑求出mid 10 int mid = l + (r-l)/2; 11 12 if( arr[mid] == target ) 13 return mid; 14 else if( arr[mid] > target ) 15 return __binarySearch2(arr, l, mid-1, target); 16 else 17 return __binarySearch2(arr, mid+1, r, target); 18 } 19 20 template<typename T> 21 int binarySearch2(T arr[], int n, T target){ 22 23 return __binarySearch2( arr , 0 , n-1, target); 24 }
9. 散列函数
1 # 创建一个book的空散列表 2 book = dict() 3 4 # 向散列表添加数据--> "apple": key 0.45: value 5 book["apple"] = 0.45 6 book["pin"] = 0.80 7 book["banana"] = 2.45 8 book["orange"] = 1.23 9 book["pee"] = 0.75 10 11 # 查询散列表 12 print(book["apple"].hex()) 13 print(book["pin"].hex()) 14 print(book["banana"].hex())
10. 广度优先搜索
1 # 寻找最短路径 2 3 # 声明一个图--> 用于存放数据 4 graph = {} 5 graph["you"] = ["alice", "bob", "claire"] 6 graph["bob"] = ["anuj", "peggy"] 7 graph["alice"] = ["peggy"] 8 graph["claire"] = ["thom", "jonny"] 9 graph["anuj"] = [] 10 graph["peggy"] = [] 11 graph["thom"] = [] 12 graph["jonny"] = [] 13 14 # 声明一个队列,可使用函数deque来创建一个双端队列 15 from collections import deque 16 search_queue = deque() 17 search_queue += graph["you"] # 将你的邻居都加入到这个搜索队列中 18 19 # 是否存在 20 def person_is_seller(name): 21 return name[-1] == 'm' 22 23 # 实现算法 24 def search(name): 25 search_queue = deque() 26 search_queue += graph[name] 27 searched = [] # 标记已经查询过的人 28 while search_queue: # search_queue: 队列不为空时 29 person = search_queue.popleft() # 取得队列第一个 30 if not person in searched: # 是否在查询过的列表中 31 if person_is_seller(person): 32 print (person + " is a mango seller!") 33 return True 34 else: 35 search_queue += graph[person] 36 searched.append(person) 37 return False 38 39 40 41 # 输出结果 42 if __name__ == '__main__': 43 search("you")
11. 深度优先搜索
12. 狄克斯特拉算法
1 # 寻找带权图的最短路径 2 3 # 声明一个散列表 4 graph = {} # 相等于 :graph = dict() 5 6 graph["start"] = {} 7 graph["start"]["a"] = 6 8 graph["start"]["b"] = 2 9 10 # 添加其他节点及其邻居。 11 graph["a"] = {} 12 graph["a"]["fin"] = 1 13 graph["b"] = {} 14 graph["b"]["a"] = 3 15 graph["b"]["fin"] = 5 16 17 # 创建终点节点--.> 没有任何的邻居 18 graph["fin"] = {} 19 20 # 用一个散列表来存储每个节点的开销。 21 infinity = float("inf") 22 costs = {} 23 costs["a"] = 6 24 costs["b"] = 2 25 costs["fin"] = infinity 26 27 # 存储父节点的散列表 28 parents = {} 29 parents["a"] = "start" 30 parents["b"] = "start" 31 parents["fin"] = None 32 33 # 数组,用于记录处理过的节点 34 processed = [] 35 36 # 寻找最小开销的节点 37 def find_lowest_cost_node(costs): 38 lowest_cost = float("inf") 39 lowest_cost_node = None 40 for node in costs: # 遍历所有的节点 41 cost = costs[node] 42 if cost < lowest_cost and node not in processed: # 如果当前节点的开销更低且未处理过 43 lowest_cost = cost # 就将其视为开销最低的节点 44 lowest_cost_node = node 45 return lowest_cost_node 46 47 # 算法实现 48 node = find_lowest_cost_node(costs) # 在未处理的节点中找出开销最小的节点 49 while node is not None: # 这个while循环在所有节点都被处理过后结束 50 cost = costs[node] 51 neighbors = graph[node] 52 for n in neighbors.keys(): # 遍历当前节点的所有邻居 53 new_cost = cost + neighbors[n] 54 if costs[n] > new_cost: # 如果经当前节点前往该邻居更近 55 costs[n] = new_cost # 就更新该邻居的开销 56 parents[n] = node # 同时将该邻居的父节点设置为当前节点 57 processed.append(node) # 将当前节点标记为处理过 58 node = find_lowest_cost_node(costs) # 找出接下来要处理的节点,并循环 59 60 61 # 输出结果 62 print(cost)
13. 贪婪算法
1 # 贪婪算法 2 3 # 总区域 4 states_needed = set(["mt", "wa", "or", "id", "nv", "ut", "ca", "az"]) 5 6 # 广播 7 stations = {} 8 stations["kone"] = set(["id", "nv", "ut"]) 9 stations["ktwo"] = set(["wa", "id", "mt"]) 10 stations["kthree"] = set(["or", "nv", "ca"]) 11 stations["kfour"] = set(["nv", "ut"]) 12 stations["kfive"] = set(["ca", "az"]) 13 14 # 输出广播集合 15 final_stations = set() 16 17 while states_needed: 18 best_station = None 19 states_covered = set() 20 for station, states in stations.items(): 21 covered = states_needed & states 22 if len(covered) > len(states_covered): 23 best_station = station 24 states_covered = covered 25 26 states_needed -= states_covered 27 final_stations.add(best_station) 28 29 print(final_stations)
14. 近似算法
15. 动态规划
16. K最近邻算法
17. SHA算法
18. 线性规划