python之算法

python之算法

这个合格程序员还是需要熟练掌握一些算法的,今天主要介绍一些排序算法

递归是算法中一个比较核心的概念,有三个特点,

  • 1 调用自身  

  • 2 具有结束条件  

  • 3 代码规模逐渐减少

以下四个函数只有两个为递归

这里需要注意一些 fun3和fun4输出的结果是不一样的

fun3:5,4,3,2,1

fun4:1,2,3,4,5

也只有3和4是递归

两个概念:时间复杂度和空间复杂度

时间复杂度:用于体现算法执行时间的快慢,用O表示。一般常用的有:几次循环就为O(n几次方)  循环减半的O(logn)

空间复杂度:用来评估算法内存占用大小的一个式子,通常情况下会选择使用空间换时间

e.g 列表查找:从列表中查找指定元素

    输入:列表、待查找元素

    输出:元素下标或未查找到元素 

    version 1 顺序查找:从列表中的第一个元素开始,顺序进行搜索,直到找到为止,复杂度为O(n)

       version 2 二分查找:从有序列表中,通过待查值与中间值比较,以减半的方式进行查找,复杂度为O(logn)

    代码如下:     

list = [1,2,3,4,5,6,7,8,9]
element = 7
def ord_sear(list,element):
    for i in range(0,len(list)):
        if list[i] == element:
            print(‘list[{0}]={1}‘.format(i,element))
            return i
    else:
        print(‘not found‘)

def bin_sear(list,element):
    low = 0
    high = len(list)-1
    while low<=high:
        mid = (low+high)//2
        if element == list[mid]:
            print(‘list[{0}]={1}‘.format(mid,element))
            return mid
        elif element > list[mid]:
            low =mid +1
        else:
            high =mid -1
    return None

i = bin_sear(list,element)
j = ord_sear(list,element)

  二分查找虽然在时间复杂度上优于顺序查找,但是有比较苛刻的条件,即列表必须为有序的。下面将介绍列表排序:

首先介绍的是最简单的三种排序方式:(low B三人组)

  • 1 冒泡排序

  • 2 选择排序

  • 3 插入排序

写一个计算时间的装饰器

import time

def cal_time(func):
    def wrapper(*args , **kwargs):
        t1 = time.time()
        result = func(*args , **kwargs)
        t2 = time.time()
        print("%s running time : %s secs " %(func.__name__ , t2-t1))
        return result
    return wrapper

冒泡排序:时间复杂度:   O(n²)

(思路):首先,列表每俩个相邻的数,如果前面的比后面的大,那么交换这俩个数.......

from cal_time import cal_time

@cal_time
def bubble_sort(li):
    for i in range(0 , len(li)-1):
        # i 表示第i趟 有序区有i个数
        for j in range(0 , len(li)-i-1):
            if li[j] > li[j+1]:
                li[j],li[j+1] = li[j+1] , li[j]

import random
li = list(range(1000))
random.shuffle(li)
bubble_sort(li)
print(li)

小优化一下

如果冒泡排序中执行一趟而没有交换,则列表已经是有序状态,可以直接结束

def bubble_sort2(li):
    for i in range(0 , len(li)-1):
        # i 表示第i趟 有序区有i个数
        exchange = False
        for j in range(0 , 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:
            return

选择排序:时间复杂度:   O(n²)

一趟遍历记录最小的数,放到第一个位置

再一趟遍历剩下列表中最小的数,继续放置:

from cal_time import cal_time

@cal_time
def select_sort(li):
    for i in range(len(li)-1):
        # 第i趟 , 有序区li[0:i] 无序区li[i : n]
        min_loc = i
        for j in range(i+1, len(li)):
            if li[min_loc] > li[j]:
                min_loc = j
        li[min_loc], li[i] = li[i], li[min_loc]

import random
li = list(range(10000))
random.shuffle(li)
select_sort(li)
print(li)

插入排序 时间复杂度:   O(n²)

列表被分为有序区和无序区俩个部分,最初的有序区只有一个元素.

每次无序区选择一个元素,插入到有序区的位置,直到无序区变空

from cal_time import cal_time

@cal_time
def insert_sort(li):
    for i in range(1 , len(li)):
        # i 既表达趟数, 又表达摸到排的下标
        j  = i - 1
        tmp = li[i]
        while j >=0 and li[j] > tmp:
            li[j+1] = li[j]
            j = j -1
        li[j + 1] = tmp

import random
li = list(range(10000))
random.shuffle(li)
insert_sort(li)
print(li)

牛逼三人组

  • 快速排序
  • 堆排序
  • 归并排序

快速排序

快速排序思路

  • 取一个元素p(第一个元素),使得元素p归位
  • 列表被p分成俩部分,左边都比p小, 右边都比p大
  • 递归完成排序
from cal_time import cal_time

def _quick_sort(li , left , right):
    if left < right:
        mid = partition(li , left , right)
        _quick_sort(li, left, mid-1)
        _quick_sort(li, mid+1 , right)

@cal_time
def quick_sort(li):
    _quick_sort(li , 0 , len(li)-1)

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

import random
li = list(range(10000))
random.shuffle(li)
quick_sort(li)
print(li)

堆排序

树:

树是一种数据结构(比如目录),树是一种可以递归的数据结构,相关的概念有根节点、叶子节点,树的深度(高度),树的度(最多的节点),孩子节点/父节点,子树等。

在树中最特殊的就是二叉树(度不超过2的树),二叉树又分为满二叉树和完全二叉树,见下图:

知道了树就可以说说堆了,堆分为大根堆和小根堆,分别的定义为:一棵完全二叉树,满足任一节点都比其孩子节点大或者小。

堆排序过程:

  • 建立堆
  • 得到堆顶元素,为最大元素
  • 去掉堆顶,将堆最后一个元素放到堆顶,此时可以通过一次调整重新使堆变的有序
  • 堆顶元素为第二大元素
  • 重复步骤3,直到堆变空
from cal_time import cal_time

def sift(li, low, high):
    tmp = li[low]# 原省长
    i = low
    j = 2 * i + 1
    while j <= high: #第二种退出条件: j > high
        if j < high and li[j+1] > li[j]: # 如果左孩子存在大于右孩子
            j += 1
        if tmp < li[j]:
            li[i] = li[j]
            i = j
            j = 2 * i + 1
        else: # 第一种退出条件:li[j] <=tmp
            li[i] = tmp
            break
    li[i] = tmp

@cal_time
def heap_sort(li):
    n = len(li)
    #1 建堆
    for i in range(n // 2 - 1, -1, -1):
        sift(li , 0 , i-1)
    # 2 挨个出数
    for i in range(n-1, -1, -1): #i  表示此时堆的high的位置
        li[0], li[i] = li[i], li[0] # 退休 + 旗子
        sift(li , 0 , i-1)

import random
li = list(range(10000))
random.shuffle(li)
heap_sort(li)
print(li)

内置模块

归并排序:

假设列表中可以被分成两个有序的子列表,如何将这两个子列表合成为一个有序的列表成为归并

原理

from cal_time import cal_time

# 一次归并
def merge(li , low , mid , high):
    i = low
    j = mid + 1
    ltmp = []
    while i <= mid and j <= high:
        if li[i] <= li[j]:
            ltmp.append(li[i])
            i += 1
        else:
            ltmp.append(li[j])
            j += 1
    while i <= mid:
        ltmp.append(li[i])
        i += 1
    while j <= high:
        j += 1
    li[low:high+1] = ltmp

@cal_time
def merge_sort(li, low , high):
    if low > high:
        mid = (low + high) // 2
        merge_sort(li , low , mid)
        merge_sort(li,mid+1 , high)
        merge(li ,low , mid, high)

快排,堆排,归并的总结:

  • 时间复杂度都是O(nlogn)
  • 快排<归并<堆排(一般情况)
  • 快排的缺点:极端情况效率较低,可到O(n^2),归并则是需要额外的开销,堆排则在排序算法中相对较慢

原文地址:https://www.cnblogs.com/Zhao--C/p/10274112.html

时间: 2024-10-09 03:52:11

python之算法的相关文章

python排序算法实现(冒泡、选择、插入)

python排序算法实现(冒泡.选择.插入) python 从小到大排序 1.冒泡排序: O(n2) s=[3,4,2,5,1,9] #count = 0 for i in range(len(s)): for j in range((i+1),len(s)): s[i],s[j]=min(s[i],s[j]),max(s[i],s[j]) #print count print s 2.选择排序: O(n2) s=[3,4,2,5,1,9] #count = 0 for i in range(l

Python基础算法综合:加减乘除四则运算方法

#!usr/bin/env python# -*- coding:utf-8 -*-#python的算法加减乘除用符号:+,-,*,/来表示#以下全是python2.x写法,3.x以上请在python(打印放入括号内) 例如:print('1+1=',1+1)print '*-----------------------------------------------------*分割符'print "1+1=",1+1 #打印加法1+1的结果2print "2-1=&quo

Python KNN算法

机器学习新手,接触的是<机器学习实战>这本书,感觉书中描述简单易懂,但对于python语言不熟悉的我,也有很大的空间.今天学习的是k-近邻算法. 1. 简述机器学习 在日常生活中,人们很难直接从原始数据本身获得所需信息.而机器学习就是把生活中无序的数据转换成有用的信息.例如,对于垃圾邮件的检测,侦测一个单词是否存在并没有多大的作用,然而当某几个特定单词同时出现时,再辅以考虑邮件的长度及其他因素,人们就可以更准确地判定该邮件是否为垃圾邮件. 机器学习分为监督学习和无监督学习,其中: (1)监督学

要继续看Python写算法的内容请到那里去

因为在这里发文章的时候,莫名其妙的出现发布出去的问题,客服告知是因为链接或者敏感词. 能不能告诉我哪里出了问题?我可以修改,以便再发. 但是,没有人告诉我,只是告诉我不能发. 另外,能不能公布一下敏感词?以后我在遣词造句的时候,才可以避免. 但是,没有看到敏感词列表. 以后我的文章将发布在https://www.github.com/qiwsir/algorithm里面,有兴趣的可以到那里阅读. 要继续看Python写算法的内容请到那里去,布布扣,bubuko.com

python经典算法

# 非波拉锲数列 def fibs(num): the_list=[] a,b,i=0,1,1 for i in range(num-1): a,b=b,a+b print b fibs(10) python经典算法,布布扣,bubuko.com

python去噪算法

<programming computer vision with python >中denoise 算法有误,从网上好了可用的代码贴上,以便以后使用. 书中错误的代码: def denoise(im,U_init,tolerance=0.1,tau=0.125,tv_weight=100): m,n = im.shape U = U_init Px = im Py = im error = 1 while (error > tolerance): Uold = U GradUx = r

python小算法

1.长度为m的字符串a,长度为n的字符串b,(m>n) 判断b中的字母是否全在a中? O(n)最小. class Num(object): def getNum(self, m): numList = filter(lambda x: not [x%i for i in range(2,x) if x%i==0], range(2,500)) return numList[0:m] def getSizeDict(self, string): numList = self.getNum(len(

Python神经网络算法与深度学习视频教程人工智能算法机器学习实战视频教程

38套大数据,云计算,架构,数据分析师,Hadoop,Spark,Storm,Kafka,人工智能,机器学习,深度学习,项目实战视频教程 视频课程包含: 38套大数据和人工智能精品高级课包含:大数据,云计算,架构,数据挖掘实战,实时推荐系统实战,电视收视率项目实战,实时流统计项目实战,离线电商分析项目实战,Spark大型项目实战用户分析,智能客户系统项目实战,Linux基础,Hadoop,Spark,Storm,Docker,Mapreduce,Kafka,Flume,OpenStack,Hiv

python kayb算法之从一组序列当中获取一组与目标值最接近的算法

python  kayb算法之从一组序列当中获取一组与目标值最接近的算法 思想:1.考虑所有序列当中的所有元素相遇的情况进行迭代2.在迭代过程当中维护一个与目标数值的最小差值3.在迭代完之后剩余的那一项 即为与目标值最接近的元素序列注意: 1.如果总和大于目标数需要判断此时大于目标数的和与前一个值总和哪个差值最小 2.考虑初始序列元素与目标值的最小差值 3.考虑序列当中所有元素的总和比目标值小问题: 1.是否有最小可以接受的范围 可以大大提高时间 1 # -*- coding:utf-8 -*-