穩定的排序和非穩定的排序


參考文章鏈接:http://wuchong.me/blog/2014/02/09/algorithm-sort-summary/

穩定的

冒泡排序(bubble sort) — O(n2)
插入排序 (insertion sort)— O(n2)
歸並排序 (merge sort)— O(n log n)
  

不穩定

選擇排序 (selection sort)— O(n2)
希爾排序 (shell sort)— O(n log n)
堆排序 (heapsort)— O(n log n)
快速排序 (quicksort)— O(n log n)

冒泡排序(相鄰交換)

基本原理

1.比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。
2.對第0個到第n-1個數據做同樣的工作。這時,最大的數就“浮”到了數組最后的位置上。
3.針對所有的元素重復以上的步驟,除了最后一個。
4.持續每次對越來越少的元素重復上面的步驟,直到沒有任何一對數字需要比較。
某一趟遍歷如果沒有數據交換,則說明已經排好序了,因此不用再進行迭代了。用一個標記記錄這個狀態即可。

#冒泡排序
def bubble_sort(arry):
    n = len(arry)
    for i in range(n-1,0,-1):
        flag = 1
        for j in range(0,i):
            if arry[j] > arry[j+1]:
                arry[j],arry[j+1] = arry[j+1],arry[j]
                flag = 0
        if flag:
             break
    return arry
if __name__ == '__main__':
    disorder_arry  = [10,9,8,7,6,5,4,3,2,1]
    order_arry = bubble_sort(disorder_arry)
    print(order_arry)
#某一趟遍歷如果沒有數據交換,則說明已經排好序了,因此不用再進行迭代了。用一個標記記錄這個狀態即可。

選擇排序(選擇最小交換)

#選擇排序
def select_sort(arry):
    n = len(arry)
    for i in range(0,n):
        min = i
        for j in range(i+1,n):
            if arry[j] < arry[min]:
                min = j
        arry[min],arry[i] = arry[i],arry[min]
    return arry

if __name__ == '__main__':
    disorder_arry  = [3,2,1]
    order_arry = select_sort(disorder_arry)
    print(order_arry)

插入排序(將元素插入到有序數組中)

基本原理

1.從第一個元素開始,該元素可以認為已經被排序
2.取出下一個元素,在已經排序的元素序列中從后向前掃描
3.如果被掃描的元素(已排序)大於新元素,將該元素后移一位
4.重復步驟3,直到找到已排序的元素小於或者等於新元素的位置
5.將新元素插入到該位置后
6.重復步驟2~5

#插入排序
def insert_sort(arry):
    n = len(arry)
    for i in range(1,n):
        if arry[i] < arry[i-1]:
            temp = arry[i]
            index = i
            for j in range(i-1,-1,-1):
                if arry[j] > temp:
                    arry[j+1] = arry[j]
                    index = j
                else:
                    break
            arry[index] = temp
    return arry

if __name__ == '__main__':
    disorder_arry  = [3,2,1,4]
    order_arry = insert_sort(disorder_arry)
    print(order_arry)

希爾排序

基本原理

希爾排序,也稱遞減增量排序算法,實質是分組插入排序。由 Donald Shell 於1959年提出。希爾排序是非穩定排序算法。

希爾排序的基本思想是:將數組列在一個表中並對列分別進行插入排序,重復這過程,不過每次用更長的列(步長更長了,列數更少了)來進行。最后整個表就只有一列了。將數組轉換至表是為了更好地理解這算法,算法本身還是使用數組進行排序。

例如,假設有這樣一組數[ 13 14 94 33 82 25 59 94 65 23 45 27 73 25 39 10 ],如果我們以步長為5開始進行排序,我們可以通過將這列表放在有5列的表中來更好地描述算法,這樣他們就應該看起來是這樣:

13 14 94 33 82
25 59 94 65 23
45 27 73 25 39
10
然后我們對每列進行排序:

10 14 73 25 23
13 27 94 33 39
25 59 94 65 82
45
將上述四行數字,依序接在一起時我們得到:[ 10 14 73 25 23 13 27 94 33 39 25 59 94 65 82 45 ]。這時10已經移至正確位置了,然后再以3為步長進行排序:

10 14 73
25 23 13
27 94 33
39 25 59
94 65 82
45
排序之后變為:

10 14 13
25 23 33
27 25 59
39 65 73
45 94 82
94
最后以1步長進行排序(此時就是簡單的插入排序了)。

def shell_sort(ary):
    n = len(ary)
    gap = round(n/2)       #初始步長 , 用round四舍五入取整
    while gap > 0 :
        for i in range(gap,n):        #每一列進行插入排序 , 從gap 到 n-1
            temp = ary[i]
            j = i
            while ( j >= gap and ary[j-gap] > temp ):    #插入排序
                ary[j] = ary[j-gap]
                j = j - gap
            ary[j] = temp
        gap = round(gap/2)                     #重新設置步長
    return ary

歸並排序(遞歸拆分數組,然后合並)

def merge_sort(ary):
    if len(ary) <= 1 : return ary
    num = int(len(ary)/2)       #二分分解
    left = merge_sort(ary[:num])
    right = merge_sort(ary[num:])
    return merge(left,right)    #合並數組

def merge(left,right):
    '''合並操作,
    將兩個有序數組left[]和right[]合並成一個大的有序數組'''
    l,r = 0,0           #left與right數組的下標指針
    result = []
    while l<len(left) and r<len(right) :
        if left[l] < right[r]:
            result.append(left[l])
            l += 1
        else:
            result.append(right[r])
            r += 1
    result += left[l:]
    result += right[r:]
    return result

快速排序

def quick_sort(arry):
    return qsort(arry,0,len(arry)-1)

def qsort(arry,left,right):#[3,2,1,4]
    if left >= right:
        return arry
    key = arry[left]#3
    lp = left#0
    rp = right#3
    while lp < rp:
        while arry[rp] >= key and lp < rp:
            rp -=1
        while arry[lp] <= key and lp <rp:
            lp +=1
        arry[lp],arry[rp] = arry[rp],arry[lp]
    arry[left],arry[lp] = arry[lp],arry[left]
    qsort(arry,left,lp-1)
    qsort(arry,rp+1,right)
    return arry
if __name__ == '__main__':
    disorder_arry  = [3,2,1,4]
    order_arry = quick_sort(disorder_arry)
    print(order_arry)

堆排序

def heap_sort(ary) :
    n = len(ary)
    first = int(n/2-1)       #最后一個非葉子節點
    for start in range(first,-1,-1) :     #構造大根堆
        max_heapify(ary,start,n-1)
    for end in range(n-1,0,-1):           #堆排,將大根堆轉換成有序數組
        ary[end],ary[0] = ary[0],ary[end]
        max_heapify(ary,0,end-1)
    return ary


#最大堆調整:將堆的末端子節點作調整,使得子節點永遠小於父節點
#start為當前需要調整最大堆的位置,end為調整邊界
def max_heapify(ary,start,end):
    root = start
    while True :
        child = root*2 +1               #調整節點的子節點
        if child > end : break
        if child+1 <= end and ary[child] < ary[child+1] :
            child = child+1             #取較大的子節點
        if ary[root] < ary[child] :     #較大的子節點成為父節點
            ary[root],ary[child] = ary[child],ary[root]     #交換
            root = child
        else :
            break


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM