快找工作了,該複習演算法。這裡總結一下排序演算法。供以後查詢
當初研一的時候,老師留的實驗作業就是寫快速排序。其中pivot設為隨機選擇,與非隨機選擇。然後比較效能。實際上做完實驗,發現合理的pivot會導致很平衡的劃分。我們需要故意設定乙個有序的序列(對應快排最壞的情況),選擇400000個int。效能還是差很多。將近10倍吧。
快排的思想 result = 【low】+pivot+【high】
然後對兩個子區間【low】、【high】分別遞迴呼叫即可。
時間複雜度o(nlogn)。最好o(nlogn),最壞o(n2)。
空間複雜度:依情況而定,有的是原址排序,有的是非原址的,有的是遞迴呼叫,有的是迴圈實現。
【段子】當初黃老師問起時間複雜度:我們都說是o(nlogn)。他:「」錯」。還有o(n2)的情況。遭到批評:「大學演算法誰教的?!」當然:快排之所以叫快排,是因為:只要不是待排序的陣列有序,那麼一定能達到很好的效能,上課他又舉例,還真是。而且nlogn它前面的係數很低。平均效能好像是1.44。像nlogn的排序有好幾個:堆排序,歸併排序等。但是一般都弄不過快排。尤其是待排陣列長度很大的時候。
def
partition
(seq):
pivot,seq= seq[0],seq[1:]
low=[x for x in seq if x<= pi] #小於pivot放左邊
hi=[x for x in seq if x> pi] #大於pivot放右邊
return low,pivot,hi
defquicksort
(seq):
if len(seq) <= 1: #遞迴 base case
return seq
low,pivot,hi=partition(seq) #進行一次劃分
return quicksort(low)+[pivot]+quicksort(hi) #遞迴劃分
談到堆排序,我第一反應就是,有了快排幹嘛用堆排序??!1-堆是乙個完全二叉樹,因此可以用連續記憶體表示。堆可分為:大根堆(堆頂元素最大),小根堆(堆頂元素最小)。實際 上解決大資料top-k的問題,他就派上了用場。
2-堆的表示:用陣列(c),或者vector(c++)
陣列的【】
3-這裡空出第乙個位置。就可以滿足對於節點i他的父親是i/2。他的兒子2i(左),2i+1(右)。
4-建堆(n個元素)的時間為o(n)
堆排序過程(大根堆為例)
1- 將待排序的序列構造成乙個大頂堆 #此時堆頂為最大
2- 將它移走(其實就是將它與堆陣列的末尾元素交換,此時末尾元素就是最大值)。
3- 此時,需要維護前n-1個元素堆的性質(堆調整)。第n個元素已經有序
4- 調整完,此時又是乙個n-1個元素的大根堆,再取堆頂與堆中最後乙個元素交換。
5- 此時,前需要維護陣列前n-2個元素的堆性質(調整堆)。第n-1與第n個元素已經有序。
如此反覆執行,便能得到乙個有序序列了。
結論:大根堆,排序結果是公升序,小根堆排序結果是降序演示:
# 調整堆
defadjust_heap
(lists, i, size):
lchild = 2 * i + 1
rchild = 2 * i + 2
max = i
if i < size / 2:
if lchild < size and lists[lchild] > lists[max]:
max = lchild
if rchild < size and lists[rchild] > lists[max]:
max = rchild
if max != i:
lists[max], lists[i] = lists[i], lists[max]
adjust_heap(lists, max, size)
# 建立堆
defbuild_heap
(lists, size):
for i in range(0, (size/2))[::-1]:
adjust_heap(lists, i, size)
# 堆排序
defheap_sort
(lists):
size = len(lists)
build_heap(lists, size)
for i in range(0, size)[::-1]:
lists[0], lists[i] = lists[i], lists[0]
adjust_heap(lists, 0, i)
def
merge
(left, right):
i, j = 0, 0
result =
while i < len(left) and j < len(right):
if left[i] <= right[j]:
i += 1
else:
j += 1
result += left[i:]
result += right[j:]
return result
defmerge_sort
(lists):
# 歸併排序
if len(lists) <= 1:
return lists
num = len(lists) / 2
left = merge_sort(lists[:num])
right = merge_sort(lists[num:])
return merge(left, right)
排序演算法 插入排序 Python C
插入排序是一種最簡單直觀的排序演算法,它的工作原理是通過構建有序序列,對於未排序資料,在已排序序列中從後向前掃瞄,找到相應位置並插入。插入排序的平均時間複雜度和最壞情況是 o n 最好情況為o n 空間複雜度為o 1 因為是原地排序 in place 將第一待排序序列第乙個元素看做乙個有序序列,把第...
各種排序演算法總結
注 以下所講排序,以公升序排序為例!選擇排序 作者思路 在一組數中,選擇第乙個數標記為最小值,在剩下的數中找比它小的數,若找到則交換兩數,標記新的 最小值 然後繼續往下找,這樣一趟下來就可以找到一組數中第二小的值,第二次以第二個數作為最小值,如此迴圈下去。這是最簡單 最基礎的一種排序演算法。例子 1...
各種排序演算法總結
1 插入排序 void insertsort int a,int n a j 1 key 插入排序是穩定的排序,平均和最壞時間複雜度是o n 2 最好的時間複雜度是o n 對應於全部排好序的情況。2 氣泡排序 void bubblesort int a,intn 氣泡排序是穩定的排序,平均和最壞時間...