python常用算法


常用排序算法

排序算法可以分為內部排序和外部排序,內部排序是數據記錄在內存中進行排序,而外部排序是因排序的數據很大,一次不能容納全部的排序記錄,在排序過程中需要訪問外存。常見的內部排序算法有:插入排序、希爾排序、選擇排序、冒泡排序、歸並排序、快速排序、堆排序、基數排序等。用一張圖概括:


  • 穩定性:排序后 2 個相等鍵值的順序和排序之前它們的順序相同
  • 排序方式:In-place:占用常數內存,不占用額外內存;Out-place:占用額外內存
  • n:數據規模

1. 冒泡排序

  • 效率:O(n2)
  • 原理:
    • 1.每一趟比較相鄰的元素,如果逆序(前大后小),就交換他們兩個;每一趟都把大的元素往后調。
    • n個元素最多n-1趟排序

def bubble_sort1(origin_items,comp=lambda x, y: x > y):
    items = origin_items[:]
    for i in range(len(items) - 1):
        for j in range(i, len(items) - 1 - i):
            if comp(items[j], items[j + 1]):
                items[j], items[j + 1] = items[j + 1], items[j]
# 改進1
def bubble_sort1(origin_items,comp=lambda x, y: x > y):
    items = origin_items[:]
    for i in range(len(items) - 1):
    	swapped = False  # 交換標志
        for j in range(i, len(items) - 1 - i):
            if comp(items[j], items[j + 1]):
                items[j], items[j + 1] = items[j + 1], items[j]
        if not swapped:  # 如果一趟排序中沒有交換,則說明整體有序,結束排序
        	break

# 改進版2                
def bubble_sort2(origin_items, comp=lambda x, y: x > y):
    """高質量冒泡排序(攪拌排序)"""
    items = origin_items[:]
    for i in range(len(items) - 1):
        swapped = False
        for j in range(i, len(items) - 1 - i): # 從左向右排序
            if comp(items[j], items[j + 1]):
                items[j], items[j + 1] = items[j + 1], items[j]
                swapped = True
        if swapped:
            swapped = False
            for j in range(len(items) - 2 - i, i, -1):  # 從右向左排序
                if comp(items[j - 1], items[j]):
                    items[j], items[j - 1] = items[j - 1], items[j]
                    swapped = True
        if not swapped:
            break
    return items

2. 選擇排序

  • 效率:O(n2)
  • 原理:從頭至尾掃描序列,找出最小的一個元素,和第一個元素交換,接着從剩下的元素中繼續這種選擇和交換方式,最終得到一個有序序列。

def select_sort(origin_items, comp=lambda x, y: x < y):
    """簡單選擇排序"""
    items = origin_items[:]
    for i in range(len(items) - 1):
        min_index = i
        for j in range(i + 1, len(items)):
            if comp(items[j], items[min_index]):
                min_index = j
        items[i], items[min_index] = items[min_index], items[i]
    return items

3. 插入排序

  • 效率:
  • 原理
    • 將第一待排序序列第一個元素看做一個有序序列,把第二個元素到最后一個元素當成是未排序序列。
    • 從頭到尾依次掃描未排序序列,將掃描到的每個元素插入有序序列的適當位置。(如果待插入的元素與有序序列中的某個元素相等,則將待插入元素插入到相等元素的后面。)

def insertionSort(arr):
    for i in range(len(arr)):
        preIndex = i-1
        current = arr[i]
        while preIndex >= 0 and arr[preIndex] > current:
            arr[preIndex+1] = arr[preIndex]
            preIndex-=1
        arr[preIndex+1] = current
    return arr

4. 歸並排序

歸並排序(Merge sort)是建立在歸並操作上的一種有效的排序算法。該算法是采用分治法(Divide and Conquer)的一個非常典型的應用。

作為一種典型的分而治之思想的算法應用,歸並排序的實現由兩種方法:

  • 自上而下的遞歸(所有遞歸的方法都可以用迭代重寫,所以就有了第 2 種方法);
  • 自下而上的迭代;

分治法:

  • 分割:遞歸地把當前序列平均分割成兩半。
  • 集成:在保持元素順序的同時將上一步得到的子序列集成到一起(歸並)。
   ![](https://img2020.cnblogs.com/blog/318238/202004/318238-20200412000835311-1847333125.gif)



    def merge_sort(items, comp=lambda x, y: x <= y):
        """歸並排序(分治法)"""
        if len(items) < 2:
            return items[:]
        mid = len(items) // 2
        left = merge_sort(items[:mid], comp)
        right = merge_sort(items[mid:], comp)
        return merge(left, right, comp)
    
    def merge(items1, items2, comp):
        """合並(將兩個有序的列表合並成一個有序的列表)"""
        items = []
        index1, index2 = 0, 0
        while index1 < len(items1) and index2 < len(items2):
            if comp(items1[index1], items2[index2]):
                items.append(items1[index1])
                index1 += 1
            else:
                items.append(items2[index2])
                index2 += 1
        items += items1[index1:]
        items += items2[index2:]
        return items

5. 快速排序

快速排序使用分治法(Divide and conquer)策略來把一個序列(list)分為較小和較大的2個子序列,然后遞歸地排序兩個子序列。步驟為:

  • 挑選基准值:從數列中挑出一個元素,稱為"基准"(pivot);
  • 分割:重新排序數列,所有比基准值小的元素擺放在基准前面,所有比基准值大的元素擺在基准后面(與基准值相等的數可以到任何一邊)。在這個分割結束之后,對基准值的排序就已經完成;
  • 遞歸排序子序列:遞歸地將小於基准值元素的子序列和大於基准值元素的子序列排序。
    # 快速排序 - 選擇樞軸對元素進行划分,左邊都比樞軸小右邊都比樞軸大
    def quick_sort(origin_items, comp=lambda x, y: x <= y):
        items = origin_items[:]
        _quick_sort(items, 0, len(items) - 1, comp)
        return items
    
    
    def _quick_sort(items, start, end, comp):
        if start < end:
            pos = _partition(items, start, end, comp)
            _quick_sort(items, start, pos - 1, comp)
            _quick_sort(items, pos + 1, end, comp)
    
    
    def _partition(items, start, end, comp):
        pivot = items[end]
        i = start - 1
        for j in range(start, end):
            if comp(items[j], pivot):
                i += 1
                items[i], items[j] = items[j], items[i]
        items[i + 1], items[end] = items[end], items[i + 1]
        return i + 1


免責聲明!

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



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