排序算法

1.冒泡排序

步骤遍历列表并比较相邻的元素对。如果元素顺序错误,则交换它们。重复遍历列表未排序部分的元素,直到完成列表排序。因为冒泡排序重复地通过列表的未排序部分,所以它具有最坏的情况复杂度O(n^2)。

def bubble_sort(arr):
    def swap(i,j):
        arr[i],arr[j] = arr[j],arr[i]
    
    n = len(arr)
    swapped = True
    
    x = -1
    while swapped:
        swapped = False
        x = x+1
        for i in range(1,n-x):
            if arr[i-1] > arr[i]:
                swap(i-1,i)
                swapped = True

    return arr

2.选择排序

选择排序常常优于冒泡排序,我们将输入列表/数组分为两部分:已经排序的子列表和剩余要排序的子列表,它们构成了列表的其余部分,不断地获取最小的未排序元素,并将其按排序顺序放置在排序的子列表中。此过程将重复进行,直到列表完全排序。

def select_sort(arr):
    for i in range(len(arr)):
        minimum = i
        
        for j in range(i+1,len(arr)):
            # select the smallest value
            if arr[j]<arr[minimum]:
                minimum = j
        
        arr[minimum],arr[i] = arr[i],arr[minimum]
        

    return arr

3.插入排序

插入排序比冒泡排序和选择排序既快又简单。有趣的是,有多少人在玩纸牌游戏时会整理自己的牌!在每个循环迭代中,插入排序从数组中删除一个元素。然后,它在另一个排序数组中找到该元素所属的位置,并将其插入其中。它重复这个过程,直到没有输入元素。

 

def insertion_sort(arr):
    for i in range(len(arr)):
        cursor = arr[i]
        pos = i
        
        while pos > 0 and arr[pos-1] > cursor:
            arr[pos] = arr[pos-1]
            pos = pos - 1            
            arr[pos] = cursor

    return arr

4.归并排序

归并排序是分而治之算法的完美例子。它简单地使用了这种算法的两个主要步骤:

(1)连续划分未排序列表,直到有N个子列表,其中每个子列表有1个“未排序”元素,N是原始数组中的元素数。

(2)重复合并,即一次将两个子列表合并在一起,生成新的排序子列表,直到所有元素完全合并到一个排序数组中。


def merge_sort(arr):
    if len(arr)<=1:
        return arr
    mid = len(arr)//2
    
    left,right = merge_sort(arr[:mid]),merge_sort(arr[mid:])

    return merge(left,right,arr.copy())

def merge(left,right,merged):
    left_cursor,right_cursor=0,0
    while left_cursor < len(left) and right_cursor < len(right):
        
        if left[left_cursor] <= right[right_cursor]:
            merged[left_cursor + right_cursor] = left[left_cursor]
            left_cursor += 1
        else:
            merged[left_cursor + right_cursor] = right[right_cursor]
            right_cursor += 1

    for left_cursor in range(left_cursor,len(left)):
        merged[left_cursor + right_cursor]=left[left_cursor]

    for right_cursor in range(right_cursor,len(right)):
        merged[left_cursor + right_cursor]=left[right_cursor]

    return merged

5.快速排序

快速排序也是一种分而治之的算法,如归并排序。虽然它有点复杂,但在大多数标准实现中,它的执行速度明显快于归并排序,并且很少达到最坏情况下的复杂度O(n) 。它有三个主要步骤:

(1)我们首先选择一个元素,称为数组的基准元素(pivot)。

(2)将所有小于基准元素的元素移动到基准元素的左侧;将所有大于基准元素的元素移动到基准元素的右侧。这称为分区操作。

(3)递归地将上述两个步骤分别应用于比上一个基准元素值更小和更大的元素的每个子数组。

def quick_sort(L):
    return q_sort(L,0,len(l)-1)

def q_sort(L,left,right):
    if left<right:
        pivot=Partition(L,left,right)  ### 因为partition函数返回的是比较的基准价,也就是在最中间了
        q_sort(L,left,pivot-1)
        q_sort(L,pivot+1,right)
    return L

def Partition(L,left,right):
    pivotkey = L[left]

    while left<right:
        while left<right and L[right]>pivotkey:
            right -= 1
        L[left]=L[right]
        
        while left<right and L[left]<pivotkey:
            left += 1
        L[right]=L[left]
        
    L[left] = pivotkey  ### 把基准放在中间位置
    return left

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值