两个基础知识点:递归和时间复杂度

递归

递归函数的特点:自己调用自己,有结束条件,看下面例子:

  1. def fun1(x):
  2. """无结束条件,报错"""
  3. print(x)
  4. fun1(x-1)
  5. def fun2(x):
  6. """结束条件为错误条件,报错"""
  7. if x>0:
  8. print(x)
  9. fun2(x+1)
  10. def fun3(x):
  11. """打印倒序"""
  12. if x>0:
  13. print(x)
  14. fun3(x-1)
  15. def fun4(x):
  16. """打印正序"""
  17. if x > 0:
  18. fun4(x-1)
  19. print(x)
  20. fun3(7)
  21. fun4(7)

结果:

  1. 7
  2. 6
  3. 5
  4. 4
  5. 3
  6. 2
  7. 1
  8. *******
  9. 1
  10. 2
  11. 3
  12. 4
  13. 5
  14. 6
  15. 7

时间复杂度

用来评估算法运行效率的东西:

  1. print('Hello World')
  2. #时间复杂度:O(1)
  3. for i in range(n):
  4. '''时间复杂度:O(n)'''
  5. print('Hello World')
  6. for i in range(n):
  7. '''时间复杂度:O(n^2)'''
  8. for j in range(n):
  9. print('Hello World')
  10. for i in range(n):
  11. '''时间复杂度:O(n^3)'''
  12. for j in range(n):
  13. for k in range(n):
  14. print('Hello World')
  15. while n > 1:
  16. '''时间复杂度:O(log2n)或者O(logn)'''
  17. print(n)
  18. n = n // 2

小结:

  • 时间复杂度是用来估算一个算法运行时间的标准
  • 一般说来,时间复杂度高的要比时间复杂度低的算法慢
  • 常见的复杂度按效率排行:

    O(1) < O(logn) <O(n) <O(nlogn) < O(n^2) < O(n^2 logn) < O(n^3)

那么如何一样判断时间复杂度?

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

列表查找

  • 输入:列表或者待查找元素
  • 输出:元素下标或者未查到的元素

顺序查找

从元素的第一个开始,按顺序进行查找,直到找到为止

二分查找

从有序列表的候选区data[0:n]开始,通过对待查找的值与候选区中间值的比较,可以使候选区减少一半。

  1. import time
  2. #定义一个计算运行时间的装饰器
  3. def cal_time(func):
  4. def wrapper(*args,**kwargs):
  5. t1 = time.time()
  6. res = func(*args,**kwargs)
  7. t2 = time.time()
  8. print('%s:%s'%(func.__name__,t2-t1))
  9. return res
  10. return wrapper
  11. #顺序查找
  12. @cal_time
  13. def linear_search(data_set,value):
  14. for i in range(len(data_set)):
  15. if data_set[i] == value:
  16. return i
  17. #二分查找
  18. @cal_time
  19. def bin_search(data_set,value):
  20. low = 0
  21. high = len(data_set) - 1
  22. while low <= high:
  23. mid = (low + high) // 2
  24. if data_set[mid] == value:
  25. return mid
  26. elif data_set[mid] < value:
  27. low = mid + 1
  28. else:
  29. high = mid - 1
  30. ret = linear_search(list(range(100000)),99999)
  31. ret2 = bin_search(list(range(100000)),99999)

但有个问题:理论上顺序查找的时间复杂度为O(n),二分查找的为O(logn),看结果二分查找的结果为一个科学记数法,相差2个量级.

  1. linear_search:0.009849071502685547
  2. bin_search:1.5974044799804688e-05

列表排序

将无序列表变为有序列表

low逼三人组:冒泡、选择、插入

之前写过:http://www.cnblogs.com/ccorz/p/5581066.html

冒泡

序列中,相邻的两个元素比较大小,如果前面的比后面的元素大,那么交换位置,以此类推...

  1. import random
  2. data = list(range(10000))
  3. random.shuffle(data)
  4. def bubbel_sort(data):
  5. for i in range(len(data) - 1):
  6. for j in range(len(data) - i - 1):
  7. if data[j] > data[j+1]:
  8. data[j], data[j+1] = data[j+1], data[j]
  9. bubbel_sort(data)
  10. print(data)
冒泡的优化:

如果排序执行了一趟数据没有交换,那么说明列表已经是有序状态,可以直接结束算法:

  1. def bubbel_sort(data):
  2. for i in range(len(data) - 1):
  3. exchange = False
  4. for j in range(len(data) - i - 1):
  5. if data[j] > data[j+1]:
  6. data[j], data[j+1] = data[j+1], data[j]
  7. exchange = True
  8. if not exchange:
  9. break

选择

遍历一趟,选择最小的数放到第一个位置,接着遍历剩下的序列,选择其中最小的,放到剩下序列的第一个位置,如此循环.

  1. import random
  2. data = list(range(1000))
  3. random.shuffle(data)
  4. def select_sort(data):
  5. for i in range(len(data) - 1):
  6. min_loc = i
  7. for j in range(i + 1, len(data)):
  8. if data[j] < data[min_loc]:
  9. min_loc = j
  10. if min_loc != i:
  11. data[i], data[min_loc] = data[min_loc], data[i]
  12. select_sort(data)
  13. print(data)

插入排序

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

  1. import random
  2. data = list(range(1000))
  3. random.shuffle(data)
  4. def insert_sort(data):
  5. for i in range(1,len(data)):
  6. tmp = data[i]
  7. j = i - 1
  8. while j >= 0 and data[j] > tmp:
  9. data[j+1] = data[j]
  10. j -= 1
  11. data[j+1] = tmp
  12. insert_sort(data)
  13. print(data)

快速排序(简称快排)

好些的算法里最快的,快的排序算法中最好写的。

思路:

  • 取第一个元素,是这个元素(P)归位(对的位置)
  • 列表被P元素分成两部分
  • 递归这两部分列表,以此类推

总结一句话就是:先整理,后递归

  1. import sys, random
  2. #解除python默认递归次数的限制
  3. sys.setrecursionlimit(10000)
  4. data = list(range(1000))
  5. random.shuffle(data)
  6. def quick_sort(data, left, right):
  7. if left < right:
  8. mid = partition(data, left, right)
  9. quick_sort(data, left, mid - 1)
  10. quick_sort(data, mid + 1, right)
  11. def partition(data, left, right):
  12. tmp = data[left]
  13. while left < right:
  14. while left < right and data[right] >= tmp:
  15. right -= 1
  16. data[left] = data[right]
  17. while left < right and data[left] <= tmp:
  18. left += 1
  19. data[right] = data[left]
  20. data[left] = tmp
  21. return left
  22. quick_sort(data, 0, len(data) - 1)
  23. print(data)

堆排序

二叉树

满二叉树是指这样的一种二叉树:除最后一层外,每一层上的所有结点都有两个子结点。在满二叉树中,每一层上的结点数都达到最大值,即在满二叉树的第k层上有2k-1个结点,且深度为m的满二叉树有2m-1个结点。

完全二叉树是指这样的二叉树:除最后一层外,每一层上的结点数均达到最大值;在最后一层上只缺少右边的若干结点。

二叉树的数据存储

二叉树总结
  • 二叉树是不超过2个节点的树
  • 满二叉树是完全二叉树,完全二叉树不一定是满二叉树
  • 完全二叉树可以用列表来存储,通过规律可以从父亲找到孩子,或从孩子找到父亲

大根堆:一颗完全二叉树,满足任何一节点都比其子节点大

小根堆:一颗完全二叉树,满足任何一节点都比其子节点小

堆排序

堆排序的过程:

  1. 建立堆
  2. 得到堆顶元素,假设为最大元素
  3. 去掉堆顶元素,将最后一个元素放到堆顶,此时可以通过一次调整,重新使堆有序
  4. 堆顶元素为第二大元素
  5. 重复步骤三

代码:

  1. import sys, random
  2. sys.setrecursionlimit(10000)
  3. data = list(range(100))
  4. random.shuffle(data)
  5. def sift(data,low,high):
  6. '''堆整理,选出最大的元素'''
  7. i = low
  8. j = 2*i+1
  9. k = j +1
  10. tmp = data[i]
  11. while j <= high:
  12. if j < high and data[j] < data[k]:
  13. j+=1
  14. if tmp < data[j]:
  15. data[i]=data[j]
  16. i=j
  17. j=2*i+1
  18. else:
  19. break
  20. data[i]=tmp
  21. def heap_sort(data):
  22. n = len(data)
  23. for i in range(n//2-1,-1,-1):
  24. sift(data,i,n-1)
  25. for i in range(n-1,-1,-1):
  26. data[0],data[i]=data[i],data[0]
  27. sift(data,0,i-1)
  28. heap_sort(data)
  29. print(data)

out:

  1. [0, 1, 2, 3, 12, 5, 4, 6, 7, 8, 25, 9, 10, 11, 17, 23, 13, 73, 29, 14, 15, 19, 40, 28, 44, 64, 30, 27, 18, 16, 21, 70, 22, 20, 31, 24, 34, 32, 33, 26, 35, 36, 39, 46, 37, 41, 38, 42, 86, 45, 43, 51, 62, 47, 49, 75, 72, 54, 50, 48, 57, 63, 68, 56, 87, 60, 67, 59, 55, 78, 58, 61, 69, 52, 53, 80, 83, 65, 89, 66, 94, 91, 71, 82, 92, 90, 77, 81, 74, 84, 95, 76, 85, 88, 93, 79, 96, 98, 97, 99]

python中的一些算法的更多相关文章

  1. python中super().__init__和类名.__init__的区别

    super().__init__相对于类名.__init__,在单继承上用法基本无差 但在多继承上有区别,super方法能保证每个父类的方法只会执行一次,而使用类名的方法会导致方法被执行多次 多继承时 ...

  2. 【转】你真的理解Python中MRO算法吗?

    你真的理解Python中MRO算法吗? MRO(Method Resolution Order):方法解析顺序. Python语言包含了很多优秀的特性,其中多重继承就是其中之一,但是多重继承会引发很多 ...

  3. 窥探算法之美妙——寻找数组中最小的K个数&python中巧用最大堆

    原文发表在我的博客主页,转载请注明出处 前言 不论是小算法或者大系统,堆一直是某种场景下程序员比较亲睐的数据结构,而在python中,由于数据结构的极其灵活性,list,tuple, dict在很多情 ...

  4. 你真的理解Python中MRO算法吗?[转]

    [前言] MRO(Method Resolution Order):方法解析顺序.Python语言包含了很多优秀的特性,其中多重继承就是其中之一,但是多重继承会引发很多问题,比如二义性,Python中 ...

  5. 面试中常用排序算法的python实现和性能分析

    这篇是关于排序的,把常见的排序算法和面试中经常提到的一些问题整理了一下.这里面大概有3个需要提到的问题: 虽然专业是数学,但是自己还是比较讨厌繁琐的公式,所以基本上文章所有的逻辑,我都尽可能的用大白话 ...

  6. 量化交易中VWAP/TWAP算法的基本原理和简单源码实现(C++和python)(转)

    量化交易中VWAP/TWAP算法的基本原理和简单源码实现(C++和python) 原文地址:http://blog.csdn.net/u012234115/article/details/728300 ...

  7. python中的迭代、生成器等等

    本人对编程语言实在是一窍不通啊...今天看了廖雪峰老师的关于迭代,迭代器,生成器,递归等等,word天,这都什么跟什么啊... 1.关于迭代 如果给定一个list或tuple,我们可以通过for循环来 ...

  8. Python 中的数据结构总结(一)

    Python 中的数据结构 “数据结构”这个词大家肯定都不陌生,高级程序语言有两个核心,一个是算法,另一个就是数据结构.不管是c语言系列中的数组.链表.树和图,还是java中的各种map,随便抽出一个 ...

  9. python 中md5 和 sha1 加密, md5 + os.urandom 生成全局唯一ID

    首先先来介绍一下md5 和 sha1 的概念 MD5 MD5的全称是Message-Digest Algorithm 5(信息-摘要算法).128位长度.目前MD5是一种不可逆算法. 具有很高的安全性 ...

随机推荐

  1. Codeforces C. Jzzhu and Cities(dijkstra最短路)

    题目描述: Jzzhu and Cities time limit per test 2 seconds memory limit per test 256 megabytes input stand ...

  2. 51nod 1254 最大子段和 V2

    N个整数组成的序列a[1],a[2],a[3],…,a[n],你可以对数组中的一对元素进行交换,并且交换后求a[1]至a[n]的最大子段和,所能得到的结果是所有交换中最大的.当所给的整数均为负数时和为 ...

  3. 开发环境搭建之springboot+tk.mybatis整合使用逆向工程

    一,引入xml文件: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorCo ...

  4. 《exception》第九次团队作业:Beta冲刺与验收准备(第三天)

    一.项目基本介绍 项目 内容 这个作业属于哪个课程 任课教师博客主页链接 这个作业的要求在哪里 作业链接地址 团队名称 Exception 作业学习目标 1.掌握软件黑盒测试技术:2.学会编制软件项目 ...

  5. hexo与github page搭建博客

    安装 npm i hexo-cli -g hexo init blog cd blog npm install hexo server 发布hexo到github page npm i hexo-de ...

  6. 微信小程序——<scroll-view>滚动到最底部

    最近在做个直播间,有个这样的需要,就是进入到页面,<scroll-view>需要滚动到最底部,并且发送消息之后自动的滚动到底部. 开始想着计算里面内容的高度,然后通过设置 scroll-t ...

  7. po模式

    一条测试用例可能需要多个步骤操作元素,将每一个步骤单独封装成一个方法,在执行测试用例时调用封装好的方法进行操作.PO模式可以把一个页面分为三个层级,对象库层.操作层.业务层. 对象库层:封装定位元素的 ...

  8. 关于#pragma once和#ifndef

    [1]#pragma once这个宏有什么作用? 为了避免同一个头文件被包含(include)多次,C/C++中有两种宏实现方式:一种是#ifndef方式:另一种是#pragma once方式.在能够 ...

  9. .net core 多sdk 多版本 环境切换

    在讲述.net core多版本之前,我们先理解一下.net core sdk与.net core runtime之前的联系与区别,根据官网的解释我们可以简单地理解为:sdk是在开发过程中进行使用,而r ...

  10. jsp解决大文件断点续传

    我们平时经常做的是上传文件,上传文件夹与上传文件类似,但也有一些不同之处,这次做了上传文件夹就记录下以备后用. 这次项目的需求: 支持大文件的上传和续传,要求续传支持所有浏览器,包括ie6,ie7,i ...