首页 > 代码库 > Python 第八阶段 学习记录之---算法
Python 第八阶段 学习记录之---算法
算法(Algorithm): 一个计算过程, 解决问题的方法
1、递归的两个特点
- 调用自身
- 结束条件
时间复杂度
- 时间复杂度是用来估计算法运行时间的一个式子(单位)
- 一般来说,时间复杂度高的算法比复杂度低的算法快
空间复杂度
用来评估算法内存占用大小的一个式子
列表查找: 从列表中查找指定元素
输入:无序
输出:有序
顺序查找:
从列表第一个元素开始,顺序进行搜索,直到找到为止。
二分查找:
从有序列表的候选区data[0:n]开始,通过对待查找的值与候选区中间值的比较,可以使候选区减少一半。
找任何一个数,次数都不会超过LOG 2 N, 2为底N的对数, 2 ** x <= n
在10**5内找一个数,那么找到它,需要找的次数 2 **x < 10**5, x = 16
列表排序:
列表排序: 将无序列表变为有序列表
应用场景:
各种榜单、表格、给二分排序用,给其它算法用
排序lowB三人组:
冒泡排序
选择排序
插入排序
快速排序
排序NB二人组:
- 堆排序
- 归并排序
没什么人用的排序:
基数排序
希尔排序
桶排序
一、LOW
时间复杂度:O(n**2)
空间复杂度:O(1)
冒泡排序:
时间复杂度:O(n**2)
random.shuffle(data) #
排序一万个数得10多秒,
首先,列表每两个相邻的数,如果前边的比后边的大,那么交换这两个数
如果冒泡排序中执行一趟而没有交换,则列表已经是有序状态,可以直接结束算法。
选择排序
一趟遍历记录最小的数,放到第一个位置;
再一趟遍历记录剩余列表中最小的数,继续放置;
找到最小的数:
if xx < xxx: xxx=xx, xx,xx=xx,xx, 小于则交换
插入排序:(打牌一样,来一个数、插入一次)
列表被分为有序区和无序区两个部份。最初有序区只有一个元素。
每次从无序区选择一个元素,插入到有序区的位置,直到无序区变空。
二、快排(快速排序)
快速排序:
好写的排序算法里最快的
快的排序里最好写的
快排思路:
取一个元素P(第一个元素), 使P归位;
列表被P分成两部分,左边都比P小,右边都比P大;
递归完成排序
效率:
快排相比冒泡快了多少?
问题:
最坏情况
递归
最好情况 一般情况 最坏情况
快排 O(nlogn) O(nlogn) O(n^2)
冒泡 O(n) O(n^2) O(n^2)
代码实现:
堆
树是一种数据结构 比如:目录结构
树是一种可以递归定义的数据结构
树是由n个节点组成的集合:
如果n=0,那这是一棵空树;
如果n>0,那存在1个节点作为树的根节点,其他节点可以分为m个集合,每个集合本身又是一棵树。
一些概念
根节点、叶子节点
树的深度(高度)
树的度: 有几个子结点(下一层,)
孩子节点/父节点
子树
二叉树:度不超过2的树(节点最多有两个叉)
满二叉树
完全二叉树
二叉树的存储方式:
链式存储方式
顺序存储方式(列表)
父节点和左孩子节点的编号下标有什么关系?
i -> 2*i + 1
父节点和右孩子节点的编号下标有什么关系?
i -> 2i+2
比如,我们要找根节点左孩子的左孩子
x = 2*(2*0+1)+1 = 3, list_[3]
最后一个有子结点的堆
x = n // 2 - 1 # n = len()
二叉树是度不超过2的树
满二叉树与完全二叉树
(完全)二叉树可以用列表来存储,通过规律可以从父亲找到孩子或从孩子找到父亲
堆
大根堆:一棵完全二叉树,满足任一节点都比其孩子节点大
小根堆:一棵完全二叉树,满足任一节点都比其孩子节点小
假设:节点的左右子树都是堆,但自身不是堆
当根节点的左右子树都是堆时,可以通过一次向下的调整来将其变换成一个堆
堆排序过程:
建立堆
得到堆顶元素,为最大元素
去掉堆顶,将堆最后一个元素放到堆顶,此时可通过一次调整重新使堆有序。
堆顶元素为第二大元素。
重复步骤3,直到堆变空。
归并:
- 假设现在的列表分成两段有序, 如何将其合成为一个有序列表
- 从两边分别取,取最小的 ===> 这个过程就叫归并
肯定有一边先取完,剩下的就不必再比较,直接取下来,xx[:] = xxx[:]
有了归并如何使用?
分解: 将列表越分越小,直至分成一个元素。
一个元素是有序的
合并: 将两个有序列表归并,列表越来越大。
时间复杂度:O(nlogn)
空间复杂度:O(n)
* 三种排序算法的时间复杂度是O(nlogn)
- 一般情况下,就运行时间而言:
快速排序 < 归并排序 < 堆排序
- 三种排序算法的缺点:
- 快速排序: 极端情况下排序效率底
- 归并排序: 需要额外的内存开销
- 堆排序: 在快的排序算法中相对较慢
希尔排序:
希尔排序是一种分组插入排序算法。
首先取一个整数d1=n/2,将元素分为d1个组,每组相邻量元素之间距离为d1,在各组内进行直接插入排序;
取第二个整数d2=d1/2,重复上述分组排序过程,直到di=1,即所有元素在同一组内进行直接插入排序。
希尔排序每趟并不使某些元素有序,而是使整体数据越来越接近有序;最后一趟排序使得所有数据有序。
时间复杂度: O((1+T)n) # O(1.3n)
排序:
- 两个排序条件
姓名、年龄
排序的稳定性,
冒泡、快排、堆、归并
算法稳定性:
就是算法的稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录(有相同的元素),
若经过排序,这些记录的相对次序保持不变,
即在原序列中,ri=rj,且ri在rj之前,而在排序后的序列中,ri仍在rj之前,则称这种排序算法是稳定的;否则称为不稳定的。
练习1:
1、现在有一个列表,列表中的数范围都在0到100之间,列表长度大约为100万,设计算法在O(n)时间复杂度内将列表进行排序。
- 计数排序,统计每个数出现的次数。只能是数值型,然后再写回列表
这时使用快排等会比较慢,有大量重复数据
2、有N(n>1000000)个数,如何取出最大的前10个数?
- 取列表前10个元素建立一个小根堆。堆顶就是目前第10大的数
- 依次向后遍历原列表,对于列表中的元素,如果小于堆顶,则忽略该元素;如果大于堆顶,则将堆顶更换为该元素,并且对堆进行一次调整;
- 遍历列表所有元素后,倒序弹出堆顶。
堆----> 优先排列
练习2:
给定一个升序列表和一个整数,返回该整数在列表中的下标范围。
例如: 列表[1,2,3,3,3,4,4,5], 若查找3,则返回(2,4);若查找0,由返回(0,0)
Python 第八阶段 学习记录之---算法
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。