一、二分查找算法
二分搜索是一種在有序數組中查找某一特定元素的搜索算法。搜索過程從數組的中間元素開始,若是中間元素正好是要查找的元素,則搜索過程結束;若是某一特定元素大於或者小於中間元素,則在數組大於或小於中間元素的那一半中查找,並且跟開始同樣從中間元素開始比較。若是在某一步驟數組爲空,則表明找不到。這種搜索算法每一次比較都使搜索範圍縮小一半。shell
# 返回 x 在 arr 中的索引,若是不存在返回 -1 def binarySearch (arr, l, r, x): # 基本判斷 if r >= l: mid = int(l + (r - l)/2) # 元素整好的中間位置 if arr[mid] == x: return mid # 元素小於中間位置的元素,只須要再比較左邊的元素 elif arr[mid] > x: return binarySearch(arr, l, mid-1, x) # 元素大於中間位置的元素,只須要再比較右邊的元素 else: return binarySearch(arr, mid+1, r, x) else: # 不存在 return -1 # 測試數組 arr = [ 2, 3, 4, 10, 40 ] x = 10 # 函數調用 result = binarySearch(arr, 0, len(arr)-1, x) if result != -1: print ("元素在數組中的索引爲 %d" % result ) else: print ("元素不在數組中")
二、線性查找api
性查找指按必定的順序檢查數組中每個元素,直到找到所要尋找的特定值爲止數組
def search(arr, n, x): for i in range (0, n): if (arr[i] == x): return i; return -1; # 在數組 arr 中查找字符 D arr = [ 'A', 'B', 'C', 'D', 'E' ]; x = 'D'; n = len(arr); result = search(arr, n, x) if(result == -1): print("元素不在數組中") else: print("元素在數組中的索引爲", result);
三、插入排序數據結構
插入排序(英語:Insertion Sort)是一種簡單直觀的排序算法。它的工做原理是經過構建有序序列,對於未排序數據,在已排序序列中從後向前掃描,找到相應位置並插入。app
def insertionSort(arr): for i in range(1, len(arr)): key = arr[i] j = i-1 while j >=0 and key < arr[j] : arr[j+1] = arr[j] j -= 1 arr[j+1] = key arr = [12, 11, 13, 5, 6] insertionSort(arr) print ("排序後的數組:") for i in range(len(arr)): print ("%d" %arr[i])
四、快速排序ide
快速排序使用分治法(Divide and conquer)策略來把一個序列(list)分爲較小和較大的2個子序列,而後遞歸地排序兩個子序列。函數
步驟爲:性能
遞歸到最底部的判斷條件是數列的大小是零或一,此時該數列顯然已經有序。測試
選取基準值有數種具體方法,此選取方法對排序的時間性能有決定性影響。
def partition(arr,low,high): i = ( low-1 ) # 最小元素索引 pivot = arr[high] for j in range(low , high): # 當前元素小於或等於 pivot if arr[j] <= pivot: i = i+1 arr[i],arr[j] = arr[j],arr[i] arr[i+1],arr[high] = arr[high],arr[i+1] return ( i+1 ) # arr[] --> 排序數組 # low --> 起始索引 # high --> 結束索引 # 快速排序函數 def quickSort(arr,low,high): if low < high: pi = partition(arr,low,high) quickSort(arr, low, pi-1) quickSort(arr, pi+1, high) arr = [10, 7, 8, 9, 1, 5] n = len(arr) quickSort(arr,0,n-1) print ("排序後的數組:") for i in range(n): print ("%d" %arr[i]),
五、選擇排序
選擇排序(Selection sort)是一種簡單直觀的排序算法。它的工做原理以下。首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,而後,再從剩餘未排序元素中繼續尋找最小(大)元素,而後放到已排序序列的末尾。以此類推,直到全部元素均排序完畢。
import sys A = [64, 25, 12, 22, 11] for i in range(len(A)): min_idx = i for j in range(i+1, len(A)): if A[min_idx] > A[j]: min_idx = j A[i], A[min_idx] = A[min_idx], A[i] print ("排序後的數組:") for i in range(len(A)): print("%d" %A[i]),
六、冒泡排序
冒泡排序(Bubble Sort)也是一種簡單直觀的排序算法。它重複地走訪過要排序的數列,一次比較兩個元素,若是他們的順序錯誤就把他們交換過來。走訪數列的工做是重複地進行直到沒有再須要交換,也就是說該數列已經排序完成。這個算法的名字由來是由於越小的元素會經由交換慢慢"浮"到數列的頂端。
def bubbleSort(arr): n = len(arr) # 遍歷全部數組元素 for i in range(n): # Last i elements are already in place for j in range(0, n-i-1): if arr[j] > arr[j+1] : arr[j], arr[j+1] = arr[j+1], arr[j] arr = [64, 34, 25, 12, 22, 11, 90] bubbleSort(arr) print ("排序後的數組:") for i in range(len(arr)): print ("%d" %arr[i]),
七、歸併排序
歸併排序(英語:Merge sort,或mergesort),是建立在歸併操做上的一種有效的排序算法。該算法是採用分治法(Divide and Conquer)的一個很是典型的應用。
分治法:
def merge(arr, l, m, r): n1 = m - l + 1 n2 = r- m # 建立臨時數組 L = [0] * (n1) R = [0] * (n2) # 拷貝數據到臨時數組 arrays L[] 和 R[] for i in range(0 , n1): L[i] = arr[l + i] for j in range(0 , n2): R[j] = arr[m + 1 + j] # 歸併臨時數組到 arr[l..r] i = 0 # 初始化第一個子數組的索引 j = 0 # 初始化第二個子數組的索引 k = l # 初始歸併子數組的索引 while i < n1 and j < n2 : if L[i] <= R[j]: arr[k] = L[i] i += 1 else: arr[k] = R[j] j += 1 k += 1 # 拷貝 L[] 的保留元素 while i < n1: arr[k] = L[i] i += 1 k += 1 # 拷貝 R[] 的保留元素 while j < n2: arr[k] = R[j] j += 1 k += 1 def mergeSort(arr,l,r): if l < r: m = int((l+(r-1))/2) mergeSort(arr, l, m) mergeSort(arr, m+1, r) merge(arr, l, m, r) arr = [12, 11, 13, 5, 6, 7] n = len(arr) print ("給定的數組") for i in range(n): print ("%d" %arr[i]), mergeSort(arr,0,n-1) print ("\n\n排序後的數組") for i in range(n): print ("%d" %arr[i]),
八、堆排序
堆排序(Heapsort)是指利用堆這種數據結構所設計的一種排序算法。堆積是一個近似徹底二叉樹的結構,並同時知足堆積的性質:即子結點的鍵值或索引老是小於(或者大於)它的父節點。堆排序能夠說是一種利用堆的概念來排序的選擇排序。
def heapify(arr, n, i): largest = i l = 2 * i + 1 # left = 2*i + 1 r = 2 * i + 2 # right = 2*i + 2 if l < n and arr[i] < arr[l]: largest = l if r < n and arr[largest] < arr[r]: largest = r if largest != i: arr[i],arr[largest] = arr[largest],arr[i] # 交換 heapify(arr, n, largest) def heapSort(arr): n = len(arr) # Build a maxheap. for i in range(n, -1, -1): heapify(arr, n, i) # 一個個交換元素 for i in range(n-1, 0, -1): arr[i], arr[0] = arr[0], arr[i] # 交換 heapify(arr, i, 0) arr = [ 12, 11, 13, 5, 6, 7] heapSort(arr) n = len(arr) print ("排序後") for i in range(n): print ("%d" %arr[i]),
九、計數排序
計數排序的核心在於將輸入的數據值轉化爲鍵存儲在額外開闢的數組空間中。做爲一種線性時間複雜度的排序,計數排序要求輸入的數據必須是有肯定範圍的整數
def countSort(arr): output = [0 for i in range(256)] count = [0 for i in range(256)] ans = ["" for _ in arr] for i in arr: count[ord(i)] += 1 for i in range(256): count[i] += count[i-1] for i in range(len(arr)): output[count[ord(arr[i])]-1] = arr[i] count[ord(arr[i])] -= 1 for i in range(len(arr)): ans[i] = output[i] return ans arr = "wwwrunoobcom" ans = countSort(arr) print ( "字符數組排序 %s" %("".join(ans)) )
十、希爾排序
希爾排序,也稱遞減增量排序算法,是插入排序的一種更高效的改進版本。但希爾排序是非穩定排序算法。
希爾排序的基本思想是:先將整個待排序的記錄序列分割成爲若干子序列分別進行直接插入排序,待整個序列中的記錄"基本有序"時,再對全體記錄進行依次直接插入排序。
def shellSort(arr): n = len(arr) gap = int(n/2) while gap > 0: for i in range(gap,n): temp = arr[i] j = i while j >= gap and arr[j-gap] >temp: arr[j] = arr[j-gap] j -= gap arr[j] = temp gap = int(gap/2) arr = [ 12, 34, 54, 2, 3] n = len(arr) print ("排序前:") for i in range(n): print(arr[i]), shellSort(arr) print ("\n排序後:") for i in range(n): print(arr[i]),
十一、拓撲排序
對一個有向無環圖(Directed Acyclic Graph簡稱DAG)G進行拓撲排序,是將G中全部頂點排成一個線性序列,使得圖中任意一對頂點u和v,若邊(u,v)∈E(G),則u在線性序列中出如今v以前。一般,這樣的線性序列稱爲知足拓撲次序(Topological Order)的序列,簡稱拓撲序列。簡單的說,由某個集合上的一個偏序獲得該集合上的一個全序,這個操做稱之爲拓撲排序。
在圖論中,由一個有向無環圖的頂點組成的序列,當且僅當知足下列條件時,稱爲該圖的一個拓撲排序(英語:Topological sorting):
from collections import defaultdict class Graph: def __init__(self,vertices): self.graph = defaultdict(list) self.V = vertices def addEdge(self,u,v): self.graph[u].append(v) def topologicalSortUtil(self,v,visited,stack): visited[v] = True for i in self.graph[v]: if visited[i] == False: self.topologicalSortUtil(i,visited,stack) stack.insert(0,v) def topologicalSort(self): visited = [False]*self.V stack =[] for i in range(self.V): if visited[i] == False: self.topologicalSortUtil(i,visited,stack) print (stack) g= Graph(6) g.addEdge(5, 2); g.addEdge(5, 0); g.addEdge(4, 0); g.addEdge(4, 1); g.addEdge(2, 3); g.addEdge(3, 1); print ("拓撲排序結果:") g.topologicalSort()