美文网首页算法与数据结构
排序算法详解以及实现

排序算法详解以及实现

作者: 不会编程的程序猿甲 | 来源:发表于2020-03-23 13:46 被阅读0次

    参考博客:https://blog.csdn.net/liangjiubujiu/article/details/82810605

    一.各排序算法复杂度概述:

    各排序算法复杂度.png

    备注:
    稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面;
    不稳定:如果a原本在b的前面,而a=b,排序之后a可能会出现在b的后面;

    内排序:所有排序操作都在内存中完成;
    外排序:由于数据太大,因此把数据放在磁盘中,而排序通过磁盘和内存的数据传输才能进行;

    时间复杂度: 一个算法执行所耗费的时间。 空间复杂度:运行完一个程序所需内存的大小。

    希尔排序是插入排序的升级版,堆排序是简单选择排序的升级版,快速排序是冒泡排序的升级版

    各排序算法详解

    动画演示参考链接: https://www.zhihu.com/question/28580777
                       https://github.com/MisterBooo/LeetCodeAnimation

    1.冒泡排序:
    共遍历n-1趟,每趟相邻两两元素相比,大的or小的后沉。
    例:第一趟:相邻两个元素相比,大的往后沉,遍历完后最后一个元素最大;
    第二趟:相邻两个元素相比,大的后沉,最后一个不用比,以此类推。
    改进:如果一趟中遍历完所有元素都没有进行交换顺序,则停止遍历,完成排序。

    代码实现:

    # 冒泡排序
    def bubble_sort(array):
        for i in range(len(array)-1): #外层循环控制遍历次数,共需要n-1次
            count = 0
            for j in range(len(array)-i-1): #控制每次的交换次数,n-1-i次
                if array[j] > array[j+1]:
                    array[j],array[j+1] = array[j+1],array[j]
                    count += 1
            if count ==0:             # 改进:如果在一次遍历后没有进行交换,说明已经有序
                break
    #测试
    a=[1,2,5,4,6,9,8,5,6]
    bubble_sort(a)
    print(a)
    #out  [1, 2, 4, 5, 5, 6, 6, 8, 9]
    

    2.选择排序
    每次从待排序的数据元素中选出最小(最大)的元素,放到序列起始的位置直至排完。

    代码实现:

    #选择排序
    def select_sort(array):
        for i in range(len(array)-1): #遍历n-1次
            min = i                   #每次遍历中的第一个元素
            for j in range(i+1, len(array)):
                if array[j] < array[min]:
                    min = j           #找出当前最小的元素
            array[i], array[min] = array[min], array[i] #将最小的元素放到遍历的第一个元素位置去
    
    a=[1,2,5,4,6,9,8,5,1,10]
    #b = bubble_sort(a)
    bubble_sort(a)
    print(a)
    # out [1, 1, 2, 4, 5, 5, 6, 8, 9, 10]
    

    备注:选择排序不稳定,即相同两个值的元素排序之后的相对位置有可能会改变,如上述代码中的两个'5'在遍历过程中,第一个 '5'会到原始列表得'1'位置,最终排序后的结果这两个'5'的相对顺序会发生改变,因此说选择排序不稳定。

    3.插入排序
    列表被分为有序区和无序区,最初有序区只有一个元素,依次从无序区选择一个元素插入到有序区的适当位置,直到无序区变空。(类似于摸牌)

    代码实现:

    # 插入排序
    def insert_sort(array):
        for i in range(1,len(array)): # 待摸的牌是从第二个到最后一个
            min = array[i]            # 待插入的数(摸上来的牌)
            j = i - 1                 #从i前面的一个元素开始比较
            while j >= 0 and array[j] > min:  #从有序的最后一个开始和当前min比较,且需要保证索引大于等于0
                array[j+1] = array[j]         # 如果min更小则对应的元素后移一位
                j -= 1                        #元素位置递减
            array[j+1] = min                  #将待排序的数字放到最后一个满足上述条件迭代后的位置(完成排序)
    a=[1,2,5,4,6,9,8,5,6,10]
    insert_sort(a)
    print(a)
    # out: [1, 2, 4, 5, 5, 6, 6, 8, 9, 10]
    

    4.希尔排序
    原理:希尔排序是直接插入排序的改进版本,是一种不稳定的排序方法,Shell排序通过将数据分成不同的组,先对每一组进行排序,然后再对所有的元素进行一次插入排序,以减少数据交换和移动的次数。

    代码实现

    #希尔排序是插入排序的分组形式
    def shell_sort(array):
        gap = int(len(array) / 2)
        while gap > 0:
            for i in range(gap,len(array)):
                tmp = array[i]
                j = i- gap
                while j >=0 and array[j]> tmp:
                    array[j + gap] = array[j]
                    j = j-gap
                array[j+gap] = tmp
            gap = int(gap / 2)
    
    a=[1,2,5,4,6,9,8,5,6,100]
    shell_sort(a)
    print(a)
    # out : [1, 2, 4, 5, 5, 6, 6, 8, 9, 100]
    
    1. 快速排序
      思想:
      找到一个基准值(通常为第一个元素),将其余元素归位,左边列表为小于等于基准值,右边列表为大于基准值,第一次排序之后为【左边列表】+基准值 + 【右边列表】,然后再递归对子列表进行归位排序。

    代码实现:(方法二图解链接:https://blog.csdn.net/yao_guang/article/details/82899355)

    #1 思路更加简便,时间复杂度为nlog(n) 但是空间复杂度为O(n),因为分配了两个临时数组放左右部分
    def quick_sort(array):
        if len(array) < 2:
            return array    #基准条件
        else:
            pivot = array[0]  #选取第一个为基准值
            less = [i for i in array[1:] if i <= pivot]    #左列表
            bigger = [i for i in array[1:] if i > pivot]   #右列表
            return quick_sort(less) + [pivot] + quick_sort(bigger)
    a=[1,2,5,4,6,9,8,5,6,100]
    b =quick_sort(a)
    print(b)
    
    #2 不分配临时数组的代码
    # 快速排序 -算法导论中思想
    
    def quick_sort_stand(array, left, right):
        if left < right:     #注意结束条件,需要保证左指针小于右指针,否则将会无限递归
            pivot_p = partion(array,left,right)     # 划分区域,pivot_p 左边的元素都小于等于该基准值,右边都大于基准值
            quick_sort_stand(array,left,pivot_p-1)  #对左边区域递归排序
            quick_sort_stand(array,pivot_p+1,right) #对右边元素递归排序
    
    
    def partion(array,left, right):
        tmp = array[right]            #基准值为最后一个元素
        i = left - 1                  # i 用来标记基准值最终所在的索引位置
        for j in range(left,right):   
            if array[j] <= tmp:       #如果元素小于等于基准值小于基准值的索引位置后移, 并且将大于基准的第一个数和该元素互换位置
                i += 1
                array[i],array[j] = array[j],array[i]
        array[i+1],array[right] = array[right],array[i+1] 
        #遍历完一次之后确定主元的位置,i代表的位置就是小于等于基准值的最大索引,i+1位置应该为基准值的正确位置
        return i+1                   #返回主元的索引
    
    s = [1,3,8,5,4,6,4,9,2]
    quick_sort_stand(s,0,len(s)-1)
    print(s)
    # out [1, 2, 3, 4, 4, 5, 6, 8, 9]
    
    

    6.归并排序
    1.思想:
    给定待排序的数组 data_list,长度为 n ,设置首尾两个游标 p,q,初始状态,p = 0,q = n,先不纠结是 n 还是 n-1 。
    分解: 取中间值 r = (p + q)/2 ,将数组分成左部分 data_list[p,r],右部分 data_list[r+1,q] 。
    对上述左右部分递归调用分解。
    归并左部分和右部分的结果。
    退出条件是 p>=q

    2.代码实现

    #归并排序
    #对于递归的理解,首先将一个数组分为左右两边,然后递归一直分组,左边递归完右边递归,到最底层的时候合并一次,这时合并完之后返回上一层的状态,继续进行归并,直到最后整个数组有序。
    def merge_sort(array,left,right):
        while left < right:
            mid = int((left+right)/2)  #首先找到中间位置
            merge_sort(array,left,mid) #对左边递归分组
            merge_sort(array,mid+1,right) #对右边递归分组
            merge(array,left,mid,right) #进行合并
    
    def merge(array,left,mid,right):
        tmp = []
        i = left
        j = mid + 1
        while i<= mid and j <=right:
            if array[i]<array[j]:
                tmp.append(array[i])
                i+=1
            else:
                tmp.append(array[j])
                j+=1
        while i<=mid:
            tmp.append(array[i])
            i+=1
        while j<=right:
            tmp.append(array[j])
        array[left:right+1]=tmp
    
    m = [1,8,5,6,4,3]
    merge_sort(m,0,len(m)-1)
    print(m)
    

    相关文章

      网友评论

        本文标题:排序算法详解以及实现

        本文链接:https://www.haomeiwen.com/subject/vpnsnctx.html