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. 線性規划