10.排序


一.冒泡排序

代碼示例:

#將亂序列表中最大元素排列到列表末尾位置
def m_sort(alist):
    for j in range(0,len(alist)-1):
        if alist[j] > alist[j+1]:
            temp = alist[j]
            alist[j] = alist[j+1]
            alist[j+1] = temp
    return alist
def m_sort_final(alist):
    for i in range(0,len(alist)-1):
        for j in range(0,len(alist)-i-1):
            if alist[j] > alist[j+1]:
                temp = alist[j]
                alist[j] = alist[j+1]
                alist[j+1] = temp
    return alist

二.選擇排序

 - 選擇排序改進了冒泡排序,每次遍歷列表只做一次交換。為了做到這一點,一個選擇排序在他遍歷時尋找最大的值,並在完成遍歷后,將其放置在正確的位置。

def selectionSort(alist):
   for i in range(len(alist)-1,0,-1):
       positionOfMax=0
       for location in range(1,i+1):
           if alist[location]>alist[positionOfMax]:
               positionOfMax = location

       temp = alist[i]
       alist[i] = alist[positionOfMax]
       alist[positionOfMax] = temp

alist = [54,26,93,17,77,31,44,55,20]
selectionSort(alist)
print(alist)

  - 對於冒泡排序來講選擇排序由於交換數量的減少,選擇排序通常在基准研究中執行得更快。

三.插入排序

  - 插入排序的主要思想是每次取一個列表元素與列表中已經排序好的列表段進行比較,然后插入從而得到新的排序好的列表段,最終獲得排序好的列表。比如,待排序列表為[49,38,65,97,76,13,27,49],則比較的步驟和得到的新列表如下:(帶有背景顏色的列表段是已經排序好的,紅色背景標記的是執行插入並且進行過交換的元素)

 - step_1:

def sort(alist):
    i = 1
    if alist[i] < alist[i-1]:
        alist[i],alist[i-1] = alist[i-1],alist[i]

- step_2:

def sort(alist):
    i = 2
    while i > 0:
        if alist[i] < alist[i-1]:
            alist[i],alist[i-1] = alist[i-1],alist[i]
            i -= 1

- 完整代碼:

def sort(alist):
    for i in range(1,len(alist)):
        while i > 0:
            if alist[i] < alist[i-1]:
                alist[i],alist[i-1] = alist[i-1],alist[i]
                i -= 1
            else:
                break
    return alist

 

 

 四.希爾排序

  - 希爾排序(Shell Sort)是插入排序的一種。也稱縮小增量排序,是直接插入排序算法的一種更高效的改進版本,該方法的基本思想是:先將整個待排元素序列分割成若干個子序列(由相隔某個“增量(gap)”的元素組成的)分別進行直接插入排序,然后依次縮減增量再進行排序,待整個序列中的元素基本有序(增量足夠小)時,再對全體元素進行一次直接插入排序。因為直接插入排序在元素基本有序的情況下(接近最好情況),效率是很高的,因此希爾排序在時間效率比直接插入排序有較大提高。

- step_1:

def sort(alist):
    gap = len(alist) // 2
    #將插入排序當做增量為1的希爾排序
    for i range(1,len(alist)):
        while i > 0 :
            if alist[i] < alist[i-1]:
                alist[i],alist[i-1] = alist[i-1],alist[i]
                i -= 1
            else:
                break

- step_2:

def sort(alist):
    gap = len(alist) // 2
    #將增量設置成gap
    for i range(gap,len(alist)):
        while i > 0 :
            if alist[i] < alist[i-gap]:
                alist[i],alist[i-gap] = alist[i-gap],alist[i]
                i -= gap
            else:
                break

- 完整代碼:

#繼續縮小增量
def sort(alist):
    gap = len(alist) // 2
    while gap >= 1:
        #將增量設置成gap
        for i in range(gap,len(alist)):
            while i > 0 :
                if alist[i] < alist[i-gap]:
                    alist[i],alist[i-gap] = alist[i-gap],alist[i]
                    i -= gap
                else:
                    break
        gap //= 2
    return alist

 

五.歸並排序

  - 歸並排序采用分而治之的原理:

    - 將一個序列從中間位置分成兩個序列;

    - 在將這兩個子序列按照第一步繼續二分下去;

    - 直到所有子序列的長度都為1,也就是不可以再二分截止。這時候再兩兩合並成一個有序序列即可。

      - 如何合並?

        下圖中的倒數第三行表示為第一次合並后的數據。其中一組數據為 4 8  ,  5 7。該兩組數據合並方式為:每一小組數據中指定一個指針,指針指向每小組數據的第一個元素,通過指針的偏移指定數據進行有序排列。排列情況如下:

      1. p1指向4,p2指向5,p1和p2指向的元素4和5進行比較,較小的數據歸並到一個新的列表中。經過比較p1指向的4會被添加到新的列表中,則p1向后偏移一位,指向了8,p2不變。

      2.p1和p2指向的元素8,5繼續比較,則p2指向的5較小,添加到新列表中,p2向后偏移一位,指向了7。

      3.p1和p2指向的元素8,7繼續比較,7添加到新列表中,p2偏移指向NULL,比較結束。

      4.最后剩下的指針指向的數據(包含該指針指向數據后面所有的數據)直接添加到新列表中即可。

 

def merge_sort(alist):
    n = len(alist)
    #結束遞歸的條件
    if n <= 1:
        return alist
    #中間索引
    mid = n//2

    left_li = merge_sort(alist[:mid])
    right_li = merge_sort(alist[mid:])

    #指向左右表中第一個元素的指針
    left_pointer,right_pointer = 0,0
    #合並數據對應的列表:該表中存儲的為排序后的數據
    result = []
    while left_pointer < len(left_li) and right_pointer < len(right_li):
        #比較最小集合中的元素,將最小元素添加到result列表中
        if left_li[left_pointer] < right_li[right_pointer]:
            result.append(left_li[left_pointer])
            left_pointer += 1
        else:
            result.append(right_li[right_pointer])
            right_pointer += 1
    #當左右表的某一個表的指針偏移到末尾的時候,比較大小結束,將另一張表中的數據(有序)添加到result中
    result += left_li[left_pointer:]
    result += right_li[right_pointer:]

    return result

alist = [3,8,5,7,6]
print(merge_sort(alist))

 六.快速排序

  • 將列表中第一個元素設定為基准數字,賦值給mid變量,然后將整個列表中比基准小的數值放在基准的左側,比基准到的數字放在基准右側。然后將基准數字左右兩側的序列在根據此方法進行排放。
  • 定義兩個指針,low指向最左側,high指向最右側
  • 然后對最右側指針進行向左移動,移動法則是,如果指針指向的數值比基准小,則將指針指向的數字移動到基准數字原始的位置,否則繼續移動指針。
  • 如果最右側指針指向的數值移動到基准位置時,開始移動最左側指針,將其向右移動,如果該指針指向的數值大於基准則將該數值移動到最右側指針指向的位置,然后停止移動。
  • 如果左右側指針重復則,將基准放入左右指針重復的位置,則基准左側為比其小的數值,右側為比其大的數值。

- 第一次排序:將將比基准小的排列在基准左側,比基准大的排列在基准右側

def sort(alist):
    low = 0
    high = len(alist)-1
    #基准:最左側的數值
    mid = alist[low]
    #low和high的關系只能是小於,當等於的時候就要填充mid了
    while low < high:
        while low < high:
            if alist[high] > mid:
                high -= 1
            else:
                alist[low] = alist[high]
                break
        while low < high:
            if alist[low] < mid:
                low += 1
            else:
                alist[high] = alist[low]
                break
        
        #當low和high重復的時候,將mid填充
        if low == high:
            alist[low] = mid #or alist[high] = mid  
            break
    return alist
    
    
    

- 完整代碼:

def sort(alist,start,end):
    low = start
    high = end
    #遞歸結束的條件
    if low > high:
        return
    #基准:最左側的數值
    mid = alist[low]
    #low和high的關系只能是小於,當等於的時候就要填充mid了
    while low < high:
        while low < high:
            if alist[high] > mid:
                high -= 1
            else:
                alist[low] = alist[high]
                break
        while low < high:
            if alist[low] < mid:
                low += 1
            else:
                alist[high] = alist[low]
                break
        
        #當low和high重復的時候,將mid填充
        if low == high:
            alist[low] = mid #or alist[high] = mid  
            break
    #執行左側序列
    sort(alist,start,high-1)
    #執行右側序列
    sort(alist,low+1,end)
    
    return alist
    


免責聲明!

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



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