zoukankan      html  css  js  c++  java
  • 算法基础

    介绍:

    什么是算法?

    算法(Algorithm):解决问题的精确步骤。

    复习:递归

    递归的两个特点:

    • 调用自身
    • 结束条件

    看下面几个函数,哪个是递归,区别是什么:

    def func1(x):
        print(x)
        func1(x-1)
    
    def func2(x):
        if x>0:
            print(x)
            func2(x+1)
    
    def func3(x):
        if x>0:
            print(x)
            func3(x-1)
    
    def func4(x):
        if x>0:
            func4(x-1)
            print(x)
    
    # func3和func4是递归
    func3 是先打印再递归,func4是先递归再打印。
    print(func3(3)) 输出:3 2 1 None
    print(func4(3)) 输出:1 2 3 None

    递归,练习:

    def func(depth):
        if depth == 0:
            print("我的小鲤鱼", end="")
        else:
            print("抱着", end="")
            func(depth - 1)
            print("的我", end="")
            
    func(3)
    代码实现

    有序区:有的地方的数据已经完全变得有顺序,我们把这部分区域的数据成为有序区
    无序区:有的地方的数据依旧无序,我们把这部分数据成为无序区

    时间复杂度和空间复杂度:
    时间复杂度是用来估计算法运行时间的一个式子(单位)。


    一般来说,时间复杂度高的算法比复杂度低的算法慢。
    常见的时间复杂度(按效率排序)
    O(1)<O(logn)<O(n)<O(nlogn)<O(n2)<O(n2logn)<O(n3)
    不常见的时间复杂度(看看就好)
    O(n!) O(2n) O(nn) …

    时间复杂度:
    类比生活中的一些时间,估计实现:
    
    眨一下眼			一瞬间/几毫秒
    口算“29+68”		几秒
    烧一壶水			几分钟
    睡一觉			几小时
    完成一个项目		几天/几星期/几个月
    飞船从地球飞出太阳系	几年

    如何一眼判断时间复杂度?

    1. 循环减半的过程 O(logn)
    2. 几次循环就是n的几次方的复杂度

    空间复杂度:是用来评估算法内存占用大小的一个式子。

    生产环境中,一般只考虑时间复杂度,很少考虑空间复杂度。
    “空间换时间”,增加空间复杂度,能减少时间复杂度。

    注:普通电脑计算能力是10的7次方到8次方之间。

     一、冒泡排序

     冒泡排序思路:

    首先,列表每两个相邻的数,如果前边的比后边的大,那么交换这两个数...

    代码关键点:

    1. 无序区

    注:趟表示从头到尾走一遍,趟是从0趟开始得。

    总结:

    1. 优化,如果冒泡排序中执行一趟而没有交换,则列表已经是有序状态,可以直接结束算法。
    2. 冒泡时间复杂度:O(n^2) 
      • 最好情况复杂度 O(n)
      • 平均情况复杂度 O(n^2)
      • 最坏情况复杂度 O(n^2)
    import random as rd
    import time
    import copy
    import sys
    
    def cal_time(func):
        def wrapper(*args, **kwargs):
            t1 = time.time()
            x = func(*args, **kwargs)
            t2 = time.time()
            print("%s running time %s secs." % (func.__name__, t2 - t1))
            return x
        return wrapper
    
    
    @cal_time
    def bubble_sort(li):
        for i in range(len(li) -1):
            for j in range(len(li) -i -1):
                if li[j] > li[j+1]:
                    li[j], li[j+1] = li[j+1], li[j]
        return li
    
    
    @cal_time
    def sys_sort(li):
        li.sort()
        return li
    
    
    li = list(range(10000))
    rd.shuffle(li)
    print(li)
    li1 = copy.deepcopy(li)
    li2 = copy.deepcopy(li)
    li3 = copy.deepcopy(li)
    
    bubble_sort(li1)
    sys_sort(li2)

    执行结果:

    dubble_sort running time 0.013000726699829102 secs.
    sys_sort running time 0.008000373840332031 secs.

    优化代码:

    def bubble_sort(li):
    for i in range(len(li) -1):
    exchange = False
    for j in range(len(li) -i -1):
    if li[j] > li[j+1]:
    li[j], li[j+1] = li[j+1], li[j]
    exchange = True
    if not exchange:
    break
    return li

    二、选择排序

    选择排序思路:

    一趟遍历记录最小的数,放到第一个位置;
    再一趟遍历记录剩余列表中最小的数,继续放置;
    ……

    三、插入排序

    列表被分为有序区和无序区两个部分。最初有序区只有一个元素。
    每次从无序区选择一个元素,插入到有序区的位置,直到无序区变空。

    四、快排

    快速排序突出一个字快,是好写的排序算法里最快的,快的排序算法里最好写得。

    快排算法关键点:

    1. 归位
    2. 递归

    快排思路:

    1. 取一个元素P(第一个元素),使元素p归位。
    2. 列表被p分成两部分,左边都比p小,右边都比p大。
    3. 递归完成排序。

      

     总结,问题:

    1. 最坏情况,复杂度增加 O(n^2)
    2. 递归(递归限制)
    import random as rd
    import time
    import sys
    import copy
    
    设置递归限制
    sys.setrecursionlimit(100000)
    
    
    def cal_time(func):
        def wrapper(*args,**kwargs):
            t1 = time.time()
            x = func(*args,**kwargs)
            t2 = time.time()
            print("%s running time %s secs." % (func.__name__, t2 - t1))
            return x
        return wrapper
    
    
    @cal_time
    def sys_sort(li):
        li.sort()
        return li
    
    def _quick_sort(data, left, right):
        if left < right:
            mid = partition(data, left, right)
            _quick_sort(data, left, mid-1)
            _quick_sort(data, mid + 1, right)
    
    
    def partition(data, left, right):
        tmp = data[left]
        while left < right:
            while left < right and data[right]>=tmp:
                right-=1
            data[left]=data[right]
            while left < right and data[left]<=tmp:
                left+=1
            data[right]=data[left]
        data[left]=tmp
        return left
    
    @cal_time
    def quick_sort(data):
        return _quick_sort(data, 0, len(data)-1)
    
    
    li = list(range(100000))
    rd.shuffle(li)
    li1 = copy.deepcopy(li)
    li2 = copy.deepcopy(li)
    quick_sort(li1)
    sys_sort(li2)
    快排代码

     五、希尔排序

    希尔排序思路:

    注:希尔排序每趟并不使某些元素有序,而是使整体数据越来越接近有序;最后一趟排序使得所有数据有序。

    时间复杂度:

    O((1+τ)n) ,τ表示在0到1之间
    O(1.3n)
    

    代码实现:

    def insert_sort_gap(li, gap):
        for i in range(gap, len(li)):
            tmp = li[i]
            j = i - gap
            while j >= 0 and tmp < li[j]:
                li[j + gap] = li[j]
                j = j - gap
            li[j + gap]  = tmp
    
    def shell_sort(li):
        d = len(li) // 2
        while d > 0:
            insert_sort_gap(li, d)
            d = d //2
        return li
    li=[3,4,5,1,2,9,8,11]
    print(shell_sort(li))

    优化代码:

    def shell_sort(li):
    gap = len(li) // 2
    while gap > 0:
    for i in range(gap, len(li)):
    tmp = li[i]
    j = i - gap
    while j >=0 and tmp < li[j]:
    li[j + gap] = li[j]
    j -= gap
    li[j + gap] = tmp
    gap = gap // 2
    return li

    li=[3,4,5,1,2,9,8,11]
    print(shell_sort(li))

     排序小结:

  • 相关阅读:
    prometheus,alertmanager 报警配置详解
    使用 kubeadm 搭建 kubernetes1.10 集群
    kibana-sentinl-监控报警
    ELK集群模式部署
    mongo 误操作恢复数据
    mongo 实时同步工具 mongosync
    移动端巨坑——iphone6Plus默认设置不使用sessionStorage
    iphone6 Plus seesionStorage失效
    移动端手势拖拽排序神器Sortable.js
    vue使用swiper(转)
  • 原文地址:https://www.cnblogs.com/luchuangao/p/7441917.html
Copyright © 2011-2022 走看看