• 常用排序算法


    一、冒泡排序

    1.原理

    1.比较相邻的元素。如果第一个比第二个大,就交换它们两个
    2.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数
    3.针对所有的元素重复以上的步骤,除了最后一个
    4.重复步骤1~3,直到排序完成
    

    2.算法分析

    冒泡排序的时间复杂度最好情况下为O(n),最坏情况下为O(n^2),平均时间复杂度为 O(n^2)
    空间复杂度为O(1)
    

    3.代码实现

    #单个排序
    def sort(alist):
        for i in range(0,len(alist)-1):#循环n-1次,n就是列表元素的个数
            if alist[i] > alist[i+1]:
                alist[i],alist[i+1] = alist[i+1],alist[i]
        print(alist)
    
    alist = [3,8,5,7,6]
    sort(alist)
    #输出结果 [3,5,7,8]
    
    
    # 完整版
    def sort(alist):
        for j in range(0,len(alist)-1):
            for i in range(0,len(alist)-1-j):#循环n-1次,n就是列表元素的个数
                if alist[i] > alist[i+1]:
                    alist[i],alist[i+1] = alist[i+1],alist[i]
        return alist
    
    alist = [3,8,5,7,6]
    print(sort(alist))
    # 输出结果 [3,5,6,7,8]
    

    二、选择排序

    1. 原理

    首先在未排序序列中找到最小(大)元素,存放到排序序列的起始(末尾)位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
    

    2. 算法分析

    插入排序的时间复杂度最好情况下为O(n2),最坏情况下为O(n2),平均时间复杂度为 O(n^2)
    空间复杂度为O(1)
    

    3.代码实现

    # 我这里是将最大值 放置列表末尾
    
    # 单个排序
    def sort(alist):
        max_index = 0 #最大值的下标,一开始假设第0个元素为最大值
        for i in range(0,len(alist)-1):#为了找出最大值的下标
            if alist[max_index] < alist[i+1]:
                max_index = i+1
        alist[max_index],alist[len(alist)-1] = alist[len(alist)-1],alist[max_index]
        return alist
    
    alist = [3,8,5,7,6]
    print(sort(alist))
    # 输出结果
    [3, 6, 5, 7, 8]
    
    #将上述操作在逐步的作用(n-1次)
    def sort(alist):
        for j in range(0,len(alist)-1):
            max_index = 0 #最大值的下标,一开始假设第0个元素为最大值
            for i in range(0,len(alist)-1-j):#为了找出最大值的下标
                if alist[max_index] < alist[i+1]:
                    max_index = i+1
            alist[max_index],alist[len(alist)-1-j] = alist[len(alist)-1-j],alist[max_index]
        return alist
    
    alist = [3,8,5,7,6]
    print(sort(alist))
    # 输出结果
    [3, 5, 6, 7, 8]
    

    三、插入排序

    1. 原理

    从第一个元素开始,该元素可以认为已经排好序,取下一个,在已经排好序的序列中向前扫描,有元素大于这个新元素,将已经在排好序中的元素移到下一个位置,依次执行。
    

    2. 算法原理

    插入排序的时间复杂度最好情况下为O(n),最坏情况下为O(n^2),平均时间复杂度为 O(n^2)
    空间复杂度为O(1)
    

    3. 代码实现

    #有序序列只有一个元素,无序序列元素个数为n-1
    i = 1 
    #alist[i-1]:有序序列的最后一个元素
    #alist[i]:无序序列的第一个元素
    if alist[i]  <  alist[i-1]:
        alist[i],alist[i-1] = alist[i-1],alist[i]
        
        
        
    
    i = 2 #有序序列有两个元素
    #alist[i]:无序序列的第一个元素
    #alist[i-1]:有序序列的最后一个元素
    while i >= 1:
        if alist[i] < alist[i-1]:
            alist[i],alist[i-1] = alist[i-1],alist[i]
            i -= 1
        else:
            break
            
    
            
    #完整代码:自动处理i(1:len-1)
    def sort(alist):
        for i in range(1,len(alist)):
            while i >= 1:
                if alist[i] < alist[i-1]:
                    alist[i],alist[i-1] = alist[i-1],alist[i]
                    i -= 1
                else:
                    break
        return alist
    
    
    alist = [49,38,65,97,76,13,27]
    print(sort(alist))
    # 输出结果
    [13, 27, 38, 49, 65, 76, 97]
    

    四、希尔排序

    1.原理

     希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本,该方法的基本思想是:先将整个待排元素序列分割成若干个子序列(由相隔某个“增量(gap)”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率比直接插入排序有较大提高。
    

    2. 算法原理

    希尔排序的时间复杂度最好情况下为O(nlog2n),最坏情况下为O(n2),平均时间复杂度为 O(nlogn)
    空间复杂度为O(1)
    

    3.代码实现

    # 第一次分组
    def sort(alist):
        gap = len(alist)//2 #分组
        #将下属所有的1换成gap
        for i in range(gap,len(alist)):
            while i >= gap:#判断条案件
                if alist[i] < alist[i-gap]:#判断组里两个值就行排序
                    alist[i],alist[i-gap] = alist[i-gap],alist[i]
                    i -= gap
                else:
                    break
        return alist
    alist=[49,38,65,97,76,13,27]
    sort(alist)
    # 输出结果
    [27, 38, 13, 49, 76, 65, 97]
    
    
    
    #完整代码
    #缩减增量
    def sort(alist):
        gap = len(alist)//2
        
        while gap >= 1:
            #将下属所有的1换成gap
            for i in range(gap,len(alist)):
                while i >= gap:
                    if alist[i] < alist[i-gap]:
                        alist[i],alist[i-gap] = alist[i-gap],alist[i]
                        i -= gap
                    else:
                        break
            gap //= 2 #缩减增量
        return alist
    
    alist = [49,38,65,97,76,13,27]
    print(sort(alist))
    # 输出结果
    [13, 27, 38, 49, 65, 76, 97]
    

    五、快速排序

    1. 原理

    定义一个数组,找X,然后将数组跟X比大小排列。我没有研究哪一个当标杆好,不如就选第一个数字吧。

                                       选择第一个数字为“标杆数”
    

    下面我们就要依据“标杆数”,也就是数字“5”(其序数为0),对其余部分进行分堆了。我们想分为“<=5”与“>5”的两部分,并使前者位于左侧,后者位于右侧,操作步骤如下:

    1. 命名左侧序数为 i,初始 i = 1;命名右侧序数为 j,初始 j = len(data)-1(即最后一位)。

    ​ 初始化i、j

    2. 让j开始移动并进行判断:

    • 若j所在的数字<=5,则让i开始向右移动,直到i所在的数字>5,接着交换data中i, j所对应的数字,即:
    data[i], data[j] = data[j], data[i]
    

    • 若j所在数字>5,则忽略,继续向左移动。

    3.j == i 时,意味着交换结束,列表除了首位的“标杆数”,其余部分分为<=5和>5两堆,那么我们还应该把“5”放到这两堆中间,让列表看上去更有序。即:

    data[0], data[j] = date[j], data[0]
    

    注意:如果j此时不在列表中间呢,比如由于数据特殊,j最终停在在首、尾处呢?

    不能交换

    可以交换

    考虑到这一点,我们就可以意识到,要做的是把一开始找的标杆放到应有的位置上,即最后一个<=5的数的位置。因此,我们在交换前加一个判断:

    if data[j] <= data[0]:
        data[0], data[j] = data[j], data[0]
    

    4. 结束操作,返回此时的data。

    以上部分讲的是单次排序的(啰嗦)细节,整个快速排序是若干次单次排序的递归,下面讲解一下递归部分:

    首先简化模型,我们把不直观的“数字比大小”转换为直观的“图形排序”,将data中的“标杆数5”及<=5的数替换为“☻”,将>5的数替换为“█”,则有:

    接着,用上述的i,j排序规则操作一遍之后,得到:

    是不是清晰许多?

    进行递归,我们要做的就是把分大小排序的data拆分为两个data,分界线即为“标杆数”,然后分别对两个拆分data排序,直至抵达递归的回归条件(len(data) <= 1即终止)。
    对示例列表进行快速排序的原理如下:

    2.算法原理

     快速排序的时间复杂度最好情况下为O(nlogn),最坏情况下为O(n^2),平均时间复杂度为 O(nlogn)
     
      空间复杂度为O(logn)
    

    3.代码实现

    #将基数放置到合适的位置:基数左侧为比基数小的数值,基数右侧为比基数大的数值
    # 传入 数组、初始值、终值
    def sort(alist,start,end):
        #头
        low = start
        #尾
        high = end
        # 如果头大于尾 结束
        if low > high:#结束递归的条件
            return
        # 标杆
        mid = alist[low]#基数
        while low < high:# 头小于尾
            while low < high:# 头小于尾
                if alist[high] > mid:# 如果尾大于标杆
                    high -= 1#high向左偏移
                else:
                    # 否则 将头和尾互换
                    alist[low] = alist[high]
                    break
            while low < high:# 头小于尾
                if alist[low] < mid:# 如果头小于标杆
                    low += 1# 向右移动
                else:
                    # 否则 将头和尾互换
                    alist[high] = alist[low]
                    break
        if low == high:# 如果头尾相等
            alist[low] = mid#标杆为 中间值
            
        #递归
        sort(alist,start,high-1)#处理基数左部分的乱序序列
        sort(alist,low+1,end)#处理基数右部分的乱序序列
        return alist
    
    alist = [49,38,65,97,76,13,27]
    print(sort(alist,0,len(alist)-1))
    #输出结果
    [13, 27, 38, 49, 65, 76, 97]
    
  • 相关阅读:
    20181120-1 每周例行报告
    20181113-2 每周例行报告
    20181030-4 每周例行报告
    20181023-3 每周例行报告
    第六周例行报告
    软件功能说明书final修订
    第十二周——例行报告
    PSP总结报告
    第十一周——例行报告
    PSP Daily软件beta版本——基于NABCD评论,及改进建议
  • 原文地址:https://www.cnblogs.com/zhangdadayou/p/12070672.html
Copyright © 2020-2023  润新知