python pivot多层索引调换顺序_python常用排序算法

论坛 期权论坛 编程之家     
选择匿名的用户   2021-5-31 00:37   11   0
力扣(LeetCode):常用的排序算法总结zhuanlan.zhihu.com
a9a27b5e8e1d048e2ee34d7bbdb09dab.png
WoodenRobot:常见排序算法 Python 实现及舞蹈展示zhuanlan.zhihu.com
fb354fcca9de0327198bf5d05a727cfe.png

da15a12d247b41447a9a13387fe95034.png

7c054ee438dcd33114dc401dd1100ee5.png

4c5260ee540708de29f22fa733f8b36b.png

2f4c0dba0f8bb5a1ba736c05d489f0ab.png
def bubble_sort(alist):
    """冒泡排序"""
    n = len(alist)
    for i in range(n-1): #外层循环次数
        for j in range(n-1-i): #这里 记得要 -i
            if alist[j] > alist[j+1]:
                alist[j], alist[j + 1] = alist[j+1], alist[j]


def bubble_sort_2(alist): #优化
    """冒泡排序"""
    n = len(alist)
    for i in range(n-1): #外层循环次数
        count = 0
        for j in range(n-1-i): #这里 记得要 -i
            if alist[j] > alist[j+1]:
                alist[j], alist[j + 1] = alist[j+1], alist[j]
                count += 1

        if 0 == count:
            return

''' 原理: 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,
    再从剩余未排序元素中继续寻找最小(大)元素
   ,然后放到已排序序列的末尾, 以此循环'''
def select_sort(alist):
    """选择排序"""
    n = len(alist)
    for i in range(n - 1):  # 外层循环次数
        min_ind = i
        for j in range(i+1,n):
            if alist[min_ind] > alist[j]:
                min_ind = j

        #找到最小值索引,下面进行交换,这样i每变化一次就确定一个数的位置了
        #alist[i], alist[min_ind] = alist[min_ind], alist[i] #推荐用下面的
        if i != min_ind:
            alist[i], alist[min_ind] = alist[min_ind], alist[i]


#理解其思想: i从1开始,i为无序序列 中的第一个元素索引,i-1为有序序列 中的第最后一个元素索引
def insert_sort(alist):
    """插入排序"""
    n = len(alist)
    #从第二个位置,即下标为i的元素开始向前插入
    for i in range(1, n):
        #从第i个元素开始向前比较,如果小于前一个元素,交换位置
        for j in range(i, 0, -1):
            if alist[j] < alist[j-1]:
                alist[j], alist[j - 1] = alist[j - 1], alist[j]
            # 如果不小于的化,就可以退出本次循环, 因为i-1为有序序列的最后一个元素索引,所以前面都是有序的
            else:
                break

'''思想:快排是一种分而治之的策略,快排的工作过程其实比较简单,三步走::
   1) 选择基准值 pivot 将数组分成两个子数组:小于基准值的元素和大于基准值的元素。
   2) 对这两个子数组进行快速排序。
   3) 合并结果
'''

def quick_sort_v1(alist):
    if len(alist)<2: #递归结束条件
        return alist
    
    #用分治法解决
    pivot = alist[0] #假设数组的第一个元素为pivot
    less_pivot = [i for i in alist[1:] if i <=pivot]
    more_pivot = [i for i in alist[1:] if i > pivot]
    
    return quick_sort_v1(less_pivot) + [pivot] + quick_sort_v1(more_pivot)

#总结:
#第一是它需要额外的存储空间,不是inplace 原地排序。
#第二是它的 partition 操作每次都要两次遍历整个数组

def quick_sort(alist, start, end):
    """快速排序"""
    if start >= end: # 递归结束条件
        return

    pivot = alist[start] # 假设基准值
    low = start
    high = end

    while (low < high):
        # 必须 high先左移
        while (low < high) and alist[high] >= pivot:
            high =high -1
        alist[low] = alist[high] # 改变low的值

        while (low < high) and alist[low] < pivot:
            low =low + 1
        alist[high] = alist[low] # 改变high的值

    # 从循环退出时,low==high, 这样就找到了pivot应该在的位置
    alist[low] = pivot

    # 对low左边的列表执行快速排序
    quick_sort(alist, start, low - 1)

    # 对low右边的列表排序
    quick_sort(alist, low + 1, end)


'''归并排序把数组递归成只有单个元素的数组,之后再不断两两 合并,最后得到一个有序数组。
   1)分解:将待排序的 n 个元素分成各包含 n//2 个元素的子序列
   2)解决:使用归并排序递归排序两个子序列
   3)合并:合并两个已经排序的子序列以产生已排序的答案
'''
def merge(left_li,right_li):
    res = [] #新的已排序好的列表
    i, j =0, 0
    #对2个列表中的元素 两两对比,将较小的追加到res中,并对当前列表下标加1
    while( i<len(left_li) and j<len(right_li) ):
        if left_li[i] <= right_li[j]:
            res.append(left_li[i])
            i += 1
        else:
            res.append(right_li[j])
            j += 1

    #退出循环后 至少有1个列表遍历完了
    res += left_li[i:]  #a = [1,2,3] ---> a[3:] ---> []
    res += right_li[j:]

    return res

def merge_sort(alist):
    """归并排序"""
    n = len(alist)
    if n < 2 :
        return alist

    mid = n // 2

    # left 采用归并排序后形成的有序的新的列表
    left_li = merge_sort(alist[:mid])

    # right 采用归并排序后形成的有序的新的列表
    right_li = merge_sort(alist[mid:])

    #d对排序好的两个列表合并,产生一个新的排序好的列表
    return merge(left_li, right_li)
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP