我在B站学python之排序算法2

1.希尔排序

在上一篇,我们讲了插入排序, 也是一种基于比较的排序。其实还有一个大佬提出一种改进的插入排序:希尔排序(shell sort)。
希尔排序的思想是:

先对序列进行分组,每次寻求一个gap:例如:
2 1 3 5 9 1 6 8
length = 8
gap = length / 2 = 4
就分成4组: 然后对每一组进行插入排序。

例如:
2 1 3 5 9 1 6 8
然后对每一组进行插入排序:

2       9         --- 插入排序
  1       1       --- 插入排序
    3       6     --- 插入排序
      5       8   --- 插入排序
2 1 3 5 9 1 6 8 

虽然每一组字面上来说,根本不需要排序。
接着,gap = gap / 2,如此继续执行上述操作。

这样做,可以减少插入排序的次数

算法复杂度和稳定性:

希尔排序的时间复杂度是: O ( n l o g n )   O ( n 2 ) O(nlogn) ~ O(n^2) O(nlogn) O(n2) 最好情况: O ( n 1 − 3 ) O(n^{1-3)} O(n13) 最坏情况: O ( n 2 ) O(n^2) O(n2) 不需要占用多余的空间,空间复杂度O(1);是不稳定排序。
python版本的实现:

def shell_sort(self, list):
    """
    希尔排序,希尔排序基于插入排序,不过是先对序列进行分组
    然后对分组执行插入排序
    :return: 插入排序的结果
    """
    n = len(list)
    gap = n // 2
    while gap >= 1:
        ## 插入排序
        for i in range(0, n - gap):
        		## 让间隔gap的元素为一组
            j = i + gap
            while j > 0:
                if list[j] < list[j - gap]:
                    (list[j - gap], list[j]) = (list[j], list[j - gap])
                    j -= gap
                else:
                    break
        ## gap折半,直至1
        gap = gap // 2
    ## 返回结果
    return list

2. 快速排序

快速排序的思想是一种基于分治的思想:

先找一个枢点,把序列分成两部分,一部分全都不小于该枢点,一部分全都大于该枢点。
然后对这两部分再进行快排

这个过程中,就采用了分而治之思想,化复杂为简单。

快排的时间复杂度是: O ( n l o g n ) O(nlogn) Onlogn) 他的排序过程,就不再演示了。这里直接给出算法复杂度分析:

算法复杂度和稳定性:

希尔排序的时间复杂度是 O ( n l o g n ) O(nlogn) O(nlogn) 最好情况, O ( n l o g n ) O(nlogn) O(nlogn) 最坏情况: O ( n 2 ) O(n^2) O(n2) 不需要占用多余的空间,空间复杂度O(1);是不稳定排序。

python版本的代码实现:

def quick_sort(self, list, first, end):
    """
    快速排序 基于分治的思想,找到一个值,把比这个元素小的,分成左边部分;
    把比这个元素大的,分成右边部分。
    接着对左边部分和右边部分,分别进行快速排序
    :param list:
    :param first:
    :param end:
    :return:
    """
    low = first
    high = end
    pivot = list[low]

    if low >= high:
        return

    while low < high:
        while low < high and list[high] >= pivot:
            high -= 1
        list[low] = list[high]

        while low < high and list[low] < pivot:
            low += 1
        list[high] = list[low]
    ## 此时,low == high, 把elment放在low指向的元素
    list[low] = pivot
    print(list)
    self.quick_sort(list, first, low - 1)
    self.quick_sort(list, low + 1, end)

3.归并排序

归并排序的思想是:先拆分序列,直到不能拆分的单个元素;然后把每个元素当作一个序列,他们分别都是有序的。那么两两合并,非常容易,因为是有序序列:

例如:5 8 1 2,拆分成4个数组: [5], [8] ,[1], [2]。接着两两合并成:

[5 8]

[1 2]

接着,就复杂一点,两个索引:up, down,分别指向 5, 1:

up 
|
5   8                  

down
|
1   2
合并结果: 【1】
   
down
|
5  8

  up
   | 
   2

结果: 【1,2】
把剩余5和8放入数组,结果:【1,2,5,8】
算法复杂度和稳定性:

希尔排序的平均时间复杂度是 O ( n l o g n ) O(nlogn) O(nlogn) 最好情况, O ( n l o g n ) O(nlogn) O(nlogn) 最坏情况: O ( n l o g n ) O(nlogn) O(nlogn) 需要占用最多长度为n的空间,空间复杂度 O ( n ) O(n) O(n)
希尔排序是稳定排序。

python版本的代码实现:

def merge_sort(self, list):
    """
    归并排序的实现
    :param self:
    :param list:
    :return:
    """
    n = len(list)
    if n == 1:
        return list
    mid = n // 2
    print("mid:", mid)
    left = self.merge_sort(list[:mid])
    right = self.merge_sort(list[mid:])
    print("left list:", left)
    print("right list:", right)
    result = self.merge(left, right)

    return result

def merge(self, left_list, right_list):
    """
    合并两个列表
    :param right_list:
    :return:
    """
    list = []
    left = 0
    right = 0
    left_len = len(left_list)
    right_len = len(right_list)

    print("merge, left len:", left_len, "right_len:", right_len)
    while left < left_len and right < right_len:
        if left_list[left] < right_list[right]:
            list.append(left_list[left])
            left += 1
        else:
            list.append(right_list[right])
            right += 1

    ## 把剩余的元素移动到list中
    if left < left_len:
        while left < left_len:
            list.append(left_list[left])
            left += 1

    if right < right_len:
        while right < right_len:
            list.append(right_list[right])
            right += 1
    return list

总结

各种算法的分析和总结:

排序算法平均情况最好情况最坏情况辅助空间稳定性
冒泡排序 O ( n 2 ) O(n^2) O(n2)O(n) O ( n 2 ) O(n^2) O(n2)O(1)稳定
选择排序 O ( n 2 ) O(n^2) O(n2) O ( n 2 ) O(n^2) O(n2) O ( n 2 ) O(n^2) O(n2)O(1)不稳定
插入排序 O ( n 2 ) O(n^2) O(n2)O(n) O ( n 2 ) O(n^2) O(n2)O(1)稳定
希尔排序O(nlogn) ~ O ( n 2 ) O(n^2) O(n2) O ( n 1 − 3 ) O(n^{1-3)} O(n13) O ( n 2 ) O(n^2) O(n2)O(1)不稳定
堆排序O(nlogn)O(nlogn)O(nlogn)O(1)稳定
归并排序O(nlogn)O(nlogn)O(nlogn)O(n)稳定
快速排序O(nlogn)O(nlogn) O ( n 2 ) O(n^2) O(n2)O(nlogn) ~ O(n)不稳定
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值