python实现常见算法
Posted serendipity
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python实现常见算法相关的知识,希望对你有一定的参考价值。
一、 算法是什么?
算法是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制。也就是说,能够对一定规范的输入,在有限时间内获得所要求的输出。如果一个算法有缺陷,或不适合于某个问题,执行这个算法将不会解决这个问题。不同的算法可能用不同的时间、空间或效率来完成同样的任务。一个算法的优劣可以用空间复杂度与时间复杂度来衡量。
二、 时间复杂度:
时间复杂度是用来估计算法运行时间的一个式子(单位)
一般来说*,时间复杂度高的算法比复杂度低的算法慢
常见时间复杂度单位:效率从上到下变低,
O(1) 简单的一次运算
O(logn) 循环减半
O(n) 一次循环
O(nlogn) 一个循环加一个循环减半
O(n^2) 两个循环
O(n^2logn)
O(n^3)
如何一眼判断时间复杂度?
循环减半的过程àO(logn)
几次循环就是n的几次方的复杂度
三、 空间复杂度
空间复杂度是用来评估算法内存占用大小的单位
空间换时间:如果需要增快算法的速度,需要的空间会更大
四、python实现常见的算法
1、冒泡(交换)排序
原理:列表中两个相邻的数,如果前一个数比后一个数大,就做交换。一共需要遍历列表的次数是len(lst)-1
时间复杂度:O(n^2)
1 def bubble_sort(lst): 2 for i in range(len(lst)-1): # 这是需要循环遍历多少次 3 for j in range(len(lst)-i-1): # 每次数组中的无序区 4 if lst[j] >lst[j+1]: 5 lst[j],lst[j+1] = lst[j+1],lst[j] 6 7 lst = [1, 2, 44, 3, 5] 8 bubble_sort(lst) 9 print(lst)
优化:如果在循环的时候,有一次没有进行交换,就表示数列中的数据已经是有序的
时间复杂度:最好情况是0(n),只遍历一次,一般情况和最坏情况都是O(n^2)
1 def bubble_sort(lst): 2 for i in range(len(lst)-1): # 这是需要循环遍历多少次 3 change = False # 做一个标志变量 4 for j in range(len(lst)-i-1): # 每次数组中的无序区 5 if lst[j] >lst[j+1]: 6 lst[j],lst[j+1] = lst[j+1],lst[j] 7 change = True # 每次遍历,如果进来排序的话,就会改变change的值 8 if not change: # 如果change没有改变,那就表示当前的序列是有序的,直接跳出循环即可 9 return 10 11 12 lst = [1, 2, 44, 3, 5] 13 bubble_sort(lst) 14 print(lst)
2、选择排序
原理:每次遍历找到当下数组最小的数,并把它放到第一个位置,下次遍历剩下的无序区
1 def select_sort(lst): 2 for i in range(len(lst) - 1): # 当前需遍历的次数 3 min_loc = i # 当前最小数的位置 4 for j in range(i+1, len(lst)): # 无序区 5 if lst[j] < lst[min_loc]: # 如果有更小的数 6 min_loc = j # 最小数的位置改变 7 if min_loc != i: 8 lst[i], lst[min_loc] = lst[min_loc], lst[i] # 把最小数和无序区第一个数交换交换 9 10 lst = [1, 2, 44, 3, 5] 11 select_sort(lst) 12 print(lst)
3、插入排序
原理:列表分为有序区和无序区,有序区是一个相对有序的序列,认为一开始的时候有序区有一值
每次从无序区选择一个值,放到有序区,直到无序区为空
1 def insert_sort(lst): 2 for i in range(1,len(lst)): # 从1开始遍历表示无序区从1开始,有序区初始有一个值 3 tmp = lst[i] # tmp表示拿到的无序区的第一张牌 4 j = i - 1 # j表示有序区的最后一个值 5 while j >= 0 and lst[j] > tmp: # 当有序区有值,并且有序区的值比无序区拿到的值大就一直循环 6 lst[j+1] = lst[j] # 有序区的值往后移 7 j -= 1 # 找到上一个有序区的值,然后再循环 8 lst[j+1] = tmp # 跳出循环之后,只有j+1的位置是空的,要把当下无序区的值放到j+1的位置 9 10 lst = [1, 2, 44, 3, 5] 11 insert_sort(lst) 12 print(lst)
二分插入:实际上并没有优化的效果
1 def insert_sort(lst): 2 for i in range(1, len(lst)): 3 left = 0 4 right = i - 1 5 tmp = lst[i] 6 while left <= right: 7 mid = (left + right) / 2 8 if tmp >= lst[mid]: 9 left = mid + 1 10 if tmp < lst[mid]: 11 right = mid - 1 12 for j in range(i - 1, left - 1, -1): # [i-1,left] 13 lst[j + 1] = lst[j] 14 lst[left] = tmp 15 16 return lst
4、快速排序
思路:取第一个元素,让它归位,就是放到一个位置,使它左边的都比它小,右边的都比它大,然后递归
先归位,后递归
时间复杂度:O(nlog(n))
最坏情况:
最坏情况下的事件复杂度是O(n2)
标志数的左边或者右边只有一个数
解决方法:不要找第一个元素,随机找一个元素
1 def parttion(lst, left, right): 2 i = left 3 j = right 4 tmp = lst[i] # 把此次循环的标志数存起来 5 while i < j: 6 while i < j and lst[j] > tmp: # 先从右边开始找比标志数小的,有的话跳出循环 7 j -= 1 8 lst[i] = lst[j] # 跳出循环之后,把这个比标志数小的值放到标志数的位置 9 while i < j and lst[i] < tmp: # 左边的排序方法和右边一样 10 i += 1 11 lst[j] = lst[i] 12 lst[i] = tmp # 整个排序结束之后,把一开始的标志数放回空位 13 return i 14 15 16 def quick_sort(lst, left, right): 17 if left < right: # 至少有两个元素 18 p = parttion(lst, left, right) 19 quick_sort(lst, left, p-1) 20 quick_sort(lst, p+1, right) 21 22 23 lst = [1, 2, 44, 3, 5] 24 quick_sort(a, 0, 4) 25 print(lst)
以上是关于python实现常见算法的主要内容,如果未能解决你的问题,请参考以下文章