算法

1.算法基础

算法(Algorithm):一个计算过程,解决问题的方法

递归回顾

递归式不能用函数装饰器的!如果你强用递归一次会执行一次你的幻术装饰器

避免这种情况可以在你使用的函数上加一层函数


例如:
import functools
import random
import time
import sys
import os
# 设置系统的最大递归限制
sys.setrecursionlimit(1000000)


def run_time(func):
    """
    为了装饰别的函数,统计函数执行的时间统计
    :param func:
    :return:
    """
    @functools.wraps(func)
    def wrapper(*args,**kwargs):
        # 开始时间
        start_time = time.time()
        # 调用被装饰的函数
        res = func(*args,**kwargs)
        # 结束时间
        end_time = time.time()
        # 打印输出,更佳的方法是将其写入到log中
        print( "%s 函数的执行时间为: %s s" %(func.__name__,end_time - start_time))
        return res
    return wrapper


@run_time
def fast_sort_1(data_list):
    """
    因为快排包含递归,所以不能直接被装饰,套一层外壳
    :param data_list:
    :return:
    """
    return fast_sort_basic1(data_list)


def fast_sort_basic1(data_list):
    """简单的快速排序,消耗内存,空间复杂度略高"""
    if len(data_list) == 0:
        # 如果传过来的数据为[],直接返回
        return [ ]
    else:
        # 把第一个数据拿出来,
        # 比它小的数据放在左边,再次调用本函数                        +   第一个数据   +    比它小的数据放在右边,再次调用本函数
        return fast_sort_basic1([i for i in data_list[1:] if i < data_list[0]]) +  [data_list[0]] +  fast_sort_basic1([i for i in data_list[1:] if i > data_list[0]])
友情提示 递归使用函数装饰器
递归 红色预警
 1 使用递归完成 (抱着抱着我的小鲤鱼的我的我)
 2 def output(cod,code=''):
 3     if cod==0:
 4         code += '我的小鲤鱼'
 5     else:
 6         code +='抱着'
 7         code=output(cod - 1, code)
 8 
 9         code += '的我'
10     return code
11 
12 
13 
14 
15 re=output(2,'')
16 print(re)
递归

2.时间复杂度

时间复杂度是用来估计算法运行时间的一个式子(单位)。
一般来说,时间复杂度高的算法比复杂度低的算法慢
常见的时间复杂度(按效率排序)
O(1)<O(logn)<O(n)<O(nlogn)<O(n2)<O(n2logn)<O(n3)
不常见的时间复杂度(看看就好) O(n!) O(2n) O(nn) …
如何一眼判断时间复杂度?
  循环减半的过程O(logn)
  几次循环就是n的几次方的复杂度
 print('Hello World')
O(
1for i in range(n):
  print('Hello World') O(n)
O(n2) for i in range(n):
  print('Hello World') O(n3) while n > 1:
  print(n)
n = n // 2 O(logn)

3.递归二分查找:

# 原理:必须是有序时间复杂长度O(lognn)
# 1.循环取最数列最中间的数据
# 同查找数据进行比较 如果比找的数据小,则把最后一个数据的位置提到中间位置-1,
# 同查找数据进行比较 如果比找的数据大,则把最后一个数据的位置提到中间位置+1
# 2.如果第一个位置的数据大于最后一个 执行完毕 没有找到
# 如果中间查找到终止

def bin_search(list_data, num):
l = 0
r = len(list_data) - 1
mid = (l + r) // 2
if list_data[mid] == num:
return mid
elif list_data[mid] > num:
high = mid - 1
else:
l = mid + 1

4.低级排序

1.冒泡排序(时间复杂度O(n2))常用
'''
冒泡排序原理:
    一个指针指向当前数,如果当前数比下一个数据大 ,交换位置,指针往下走一帧
    当前数比下一个数小,则指针往下走,当前数为指针所指向当数,和下一个数据比较
    直到最后一个产生至少一个有序数据
    指针再次回到第一个数据,重复动作
'''

def bubble_sort(list_data):
    for i in range(len(list_data)-1):
        flag=True
        for j in range(len(list_data)-i-1):
            if list_data[j]>list_data[j+1]:
                list_data[j],list_data[j+1]=list_data[j+1],list_data[j]
                flag =False
        if flag:
            return 
View Code
2.选择排序(时间复杂度O(n2))
'''
选择排序原理:
先把左边第一个数当成最小的一个
进行便利所有的数据只要遇到比他小的就进行调换,直到完成一轮第一个最小
下一个依旧这样从当前的下一个进行便利调换
'''
def select_sort(li):
    for i in range(len(li)-1):
        min_loc=i
        for j in range(i+1,len(li)):
            if li[j]<li[min_loc]
                min_loc=j
        if min_loc !=i:
            li[i],li[min_loc]=li[min_loc],li[i]
View Code
3.插入排序(时间复杂度O(n2))
'''
插入排序原理:
数据中从左到右分为有序和无序区
先把第一个数当做有序的
下个数据从当前位置向前依次比较 遇到比自己小的第一个进行调换位置
依次编程有序的
'''

def insert_sort(list_data):
    for i in range(1,len(list_data)):
        tep=list_data[i]
        j=i-1
        while j>=0 and tep <list_data[j]:
            list_data[j+1]=list_data[j]
            j=j-1
        list_data[j+1]=tep
View Code

 5.快排

option 1


import functools
import random
import time
import sys
import os
# 设置系统的最大递归限制
  sys.setrecursionlimit(1000000)

def fast_sort(list_data):
    '''原理用内存还速度简单的快速排序,消耗内存,空间复杂度略高
        以第一个数据为分界线 分为两部分左边 比中间的小 右边的比中间的大第一波下来找到最中间的值,并且分开大小
        把左边的列表再次执行,分为三部分你, 右边的同样执行
    '''
    if len(list_data) == 0:
        return []
    else:
        # 比它小的数据放在左边,再次调用本函数                        +   第一个数据   +    比它小的数据放在右边,再次调用本函数
        return fast_sort([i for i in list_data[1:] if i < list_data[0]]) + list_data[0] + fast_sort(
            [i for i in list_data[1:] if i > list_data[0]])


import random

if __name__ == '__main__':
    a = list(range(33))

    random.shuffle(a)
    # print(a)
    c = fast_sort_basic1(a)
    print(c)

option 2 不消耗内存

def fast_sort2(data,left,right):

    if left<right:
        # 调用partiton函数 mid 处为第一个元素应该待的地方
        mid =partition(data,left,right)

        # 对左边的数据继续做快速排序
        fast_sort2(data,left,mid-1)
        # 对右边的数据继续做快速排序
        fast_sort2(data,mid+1,right)
    return data



def partition(data,left,right):
    """
    找中间值
    将数据的左边的第一个数据,数据调整为自己应该待的位置
    [5,2,1,4,3]      从第一个数字开始,把它放在它应该在的位置,什么叫它应该在的位置,就是左边的数字都比它小,右边的数字都比它大

    1、从最右边开始找,找到第一个比它小的数 和 它 交换位置,把第一个数字放到新的位置
    2、然后从这个新的位置, 左边开始找比它大的数字,和它大小比较,然后和新的位置交换
    3、不断重复,就会使第一个数字出现在它应该出现的位置
    那么这个数字所在的位置就是有序区

    """
    # 找到左边的第一个数据
    tmp = data[left]
    # 一直循环直到这个数据待在它自己该待的位置
    while left < right:
        # 从右边开始找数据
        while data[right] > tmp and left < right:
            # 找不到,继续往左找
            right = right -1
        # 右边找到一个比它小,赶紧交换位置
        data[left] = data[right]
        # 从左边开始找数据
        while data[left] < tmp and left < right:
            # 找不到继续往右找
            left = left + 1
        # 左边找到一个比它大的赶紧交换位置
        data[right] = data[left]
    # 此时此刻左边和右边完全相同
    # 这个数据已经待在它该待的位置
    data[left] = tmp
    return left


import random

if __name__ == '__main__':
    a = list(range(12))

    random.shuffle(a)
    print(a)
    c = fast_sort2(a,0,len(a)-1)
    print(c)
原文地址:https://www.cnblogs.com/honglingjin/p/6865800.html