• 排序算法之快速排序


    一、快速排序的思路

    • 从序列中取出第一个元素E,并使其归位
    • 序列被元素E分成左右两个部分
    • 使用递归完成排序

    关键点

    • 归位

      如何完成对元素E的归位,元素E将序列分成左右两部分,左边的部分比E元素小,右边的部分比E元素大,这样左边和右边排序后,中间的E元素位置未变,而且左边和右边使用同样的归位方式进行排序。

      (1)加入现在有一列数据需要排序:

      (2)快排先取出第一个数:

      (3)此时第一个数的位置是空的,就需要从右边将小于4的数取出放置在左侧的空位置

      (4)右侧的空位置就循环左侧的数,将大于4的数填在右侧的空位置

      (5)然后右侧继续循环填补左侧的空位置,当左侧与右侧的位置相同时,这就是取出左侧第一个数4的位置

      

    这样就完成了一次归位,同理左侧与右侧都用相同的方式进行归位,完成排序。

    二、实现

    def partition(li,left,right):
        temp=li[left]#表示从左边取出的第一个元素
        while left<right:
            while left < right and li[right]>=temp: #从右边开始循环,寻找比归位元素小的元素放到左边空的位置
                right-=1
            li[left]=li[right]
            while left<right and li[left] <= temp:#从左边开始循环,寻找比归位元素大的元素放到右边空的位置
                left+=1
            li[right]=li[left]
        li[left]=temp #跳出循环说明左右两个位置重合了left=right,此时放temp元素
        return left
    
    def quickSort(li,left,right):
    
        if left<right:#至少两个元素才能进行快排
            mid=partition(li,left,right) #返回归位元素的位置
            quickSort(li,left,mid-1) #左边元素进行排序
            quickSort(li,mid+1,right) #右边元素进行排序
    
    li=[2,9,5,7,6,12,25,48,36]
    quickSort(li,0,len(li)-1)
    print(li)#[2, 5, 6, 7, 9, 12, 25, 36, 48]

    三、扩展

      快排中隐含的问题就是时间复杂度最坏情况就是o(n2),一般情况是o(nlogn),当出现序列中的元素全部是降序,但是你要进行升序排列时,会出现这种情况,那么,如何解决这种问题呢?可以在选取temp元素时,随机的选一个元素与temp元素进行交换,避免这类情况的发生。

    import random
    
    
    def partition(li, left, right):
        swap = random.randint(left, right)  # 产生随机的位置索引
        li[swap], li[left] = li[left], li[swap]  # 将第一个元素与随即产生的元素进行交换
        temp = li[left]  # 表示从左边取出的第一个元素
        while left < right:
            while left < right and li[right] >= temp:  # 从右边开始循环,寻找比归位元素小的元素放到左边空的位置
                right -= 1
            li[left] = li[right]
            while left < right and li[left] <= temp:  # 从左边开始循环,寻找比归位元素大的元素放到右边空的位置
                left += 1
            li[right] = li[left]
        li[left] = temp  # 跳出循环说明左右两个位置重合了left=right,此时放temp元素
        return left
    
    
    def quickSort(li, left, right):
    
        if left < right:  # 至少两个元素才能进行快排
            mid = partition(li, left, right)  # 返回归位元素的位置
            quickSort(li, left, mid - 1)  # 左边元素进行排序
            quickSort(li, mid + 1, right)  # 右边元素进行排序
    
    
    li = [2, 9, 5, 7, 6, 12, 25, 48, 36]
    quickSort(li, 0, len(li) - 1)
    print(li)  # [2, 5, 6, 7, 9, 12, 25, 36, 48]

    上面都是按照升序排列的,如果需要进行降序排列,只需要修改两个地方即可:

    ...
       
     while left < right:
            while left < right and li[right] <= temp:  # 从右边开始循环,寻找比归位元素大的元素放到左边空的位置
                right -= 1
            li[left] = li[right]
            while left < right and li[left] >= temp:  # 从左边开始循环,寻找比归位元素小的元素放到右边空的位置
                left += 1
            li[right] = li[left]
    
    ...
  • 相关阅读:
    [Windows] 重新安装/卸载桌面版OneDrive / Reinstall/ Uninstall Desktop Version OneDrive
    [Linux] 关闭防火墙以及开放端口
    [Java] Properties类
    [Linux] 文档编辑搜索
    [Dababase
    etymological
    [JavaScript] 表单验证不通过不提交的JS写法
    Lyrics来源
    [Maven
    [ Servlet / JSP ] J2EE Web Application 中的 JSESSIONID 是什么?
  • 原文地址:https://www.cnblogs.com/shenjianping/p/11096853.html
Copyright © 2020-2023  润新知