python中的排序算法

python heapq模块可以实现归并排序!
(首先import heapq;然后list(heapq.merge([1,3,5,7], [0,2,4,8], [5,10,15,20], [], [25])) ,可一次合并多个有序数组)
(nlargest(4, a)可以找出a数组中最大的4个元素;nsmallest(4, a)找出a数组中最小的4个元素;)
(最主要是堆排序,heapq.heappush(h,2)…heapq.heappop(h)…一开始h=[],即一个一个元素构造堆以及弹出;)
(也可以一次性构造堆,heapq.heapify(list)即把一个list变为堆;)
(heapq.heapreplace(list,99)弹出一个元素同时添加一个元素;)

归并排序时间复杂度nlogn,插入排序n*n;
(归并排序在数据量小的时候不如插入排序,但超过一定数量后,会超过后者;)

快排和归并一样都是分治思想;
(分治思想有多种应用,如排序、查找、求最值等;)

分治法和动态规划是类似的;区别在于子问题是否独立;
(分治法大都采用递归形式;但二分搜索也可以使用while代替递归;)

插入排序和打牌时整理牌的做法类似;是原地排序的;(只需要记录一个当前关键字)
(左手一开始是空的,右手一张一张插入左边;无论何时,左手的牌都是有序的;)
(或者把左手看成只有一张牌,且是拍好序的;右手每次拿一张去找到合适的插入位置;)
(左手和右手的牌看成是原数组的左右两部分;用下标A[0,j-1]、A[j,len-1]表示;随着插入的进行,左边越来越多,右边变为0;)
(如果把每次查找和插入换成二分查找,而不是逐个对比,那时间复杂度会不会从nn下降为n * logn?最坏情况仍是n * n!平均也是n * n!)
(但二分查找的最坏时间复杂度仍是logn!!!)
(注意:平均时间复杂度通常和最坏时间复杂度一样!)
(插入排序是稳定的;空间复杂度为O(1);)
(插入排序分为直接插入排序、链表插入排序、二分插入排序?)
(插入排序、选择排序、冒泡排序都是n
n,哪个更好、更快?)
(插入排序的哨兵是什么,有什么作用?可以省略循环判定条件,如j是否越界;)
(注意:一切为简化边界条件而引入的附加结点(元素)均可称为哨兵;单链表中的头结点也是一个哨兵;)
(哨兵对排序算法是非常重要的,因为任何一点时间节省都是宝贵的,特别是对记录数较大的排序;)
(插入排序采用的方法叫增量法,和分治法对等;)
(插入排序也有递归版本!)

归并排序可看成把两堆已排序的牌,合并为一堆;直到一堆为空,另一堆余下的牌依次放入即可;
(同样,为避免每次检查一堆牌是否为空,底部放置哨兵牌;用无穷大表示;)
(MERGE方法将A[p,q]、A[q+1,r]按序合并;记n1=q-p+1,n2=r-q;创建数组L、R分别存储两部分,长度分别为n1+1、n2+1;即最后都有一个哨兵,存放无穷大;)
(注意:L、R都是各自有序的;自底向上可以保证有序性;比如A[p,q]、A[q+1,r]都只有一个元素时,是有序的,合并后的两个元素也是有序的;)
(可以控制循环次数,即这段区间的元素个数,来保证程序及时结束,而不会把哨兵复制进去;)
(MERGE-SORT方法是入口函数,递归调用自己及MERGE方法;它的参数为p、r;通过p、r的平均值取下整得到q;也就是说最底层一定是p=q、p+1=r;)
(p=q、p+1=r的情况可以被MERGE方法处理;即将两个一元素的数组合并;)
(递归调用可以用递归式或递归方程表示;时间复杂度可以用递归树解析得到;也可以用主定理直接得到;)
(归并排序分为自顶向下和自底向上;算法导论的是自顶向下;自底向上的不能叫分治法吧?)
(自顶向下和自底向上使用同一个MERGE方法,只不过后者把递归改为双重循环;)
(TimSort是归并排序的终极优化版本;)
(归并排序比较占内存,但却是一种效率高且稳定的算法;)
(多路归并如何实现?多路归并也包括自顶向下和自底向上两种?)

https://www.cnblogs.com/nullzx/p/5968170.html
https://www.cnblogs.com/wangprince2017/p/7663457.html
https://blog.youkuaiyun.com/brahmsjiang/article/details/78904644

比较排序的最坏情况下界为nlogn,所以堆排序和归并排序都是渐近最优的;
(插入排序、快排最坏都是n^2;)
(计数排序、基数排序、桶排序都不是比较排序,它们可以突破这个极限,达到线性时间;)

原地排序有插入排序、堆排序、快排;

快排平均性能很好,为nlogn且系数很小;
(快排和自顶向下归并一样,都是分治思想;区别是快排是原地的,后者不是;)
(快排是每次有两堆,第一堆比枢纽小,第二堆比枢纽大,逐渐细分到一个元素,即一个元素成一堆,就能保证所有元素有序;)
(归并是‘堆内有序’,即每堆的元素各自有序,但没有一堆比另一堆完全大;而快排是‘堆间有序’,即每堆内不一定有序,但一堆比另一堆完全大;)
(快排将A[p,r]划分为两部分,A[p,q-1]、A[q+1,r],其中前者都小于A[q],后者都大于A[q];下标q在每步计算得到;)
(核心是Partition方法,对A[p,r]就地重排,同时计算出q;)
(Partition将数组分为4个区域;比枢纽小的元素、比枢纽大的元素、未划分的元素、枢纽元素;其中i之前是第一部分;i~ j是第二部分;j~r是第三部分;r是第四部分;)
(准确来说是分别是A[p,i]、A[i+1,j-1]、A[j,r-1]、A[r];)
(注意:j每轮都会更加1,i只在满足A[j]<=A[r]时才加1,所以j>=i;)
(其中枢纽不一定得是最后一个元素;可以作为枢纽的条件是,左边比它小、右边比它大?)
(快排取决于划分是否对称;或者说与枢纽元素有关;若对称,和归并一样快;若不对称,和插入排序一样慢;)
(注意:当完全有序时,插入排序是O(n),而快排是O(n^2);即快排适合‘混乱’的场景;)
(好消息:快排的平均时间复杂度与最佳情况接近;而不是最坏;即9:1或任意常数比的对称度也与1:1差不多!)
(快排的随机化版本,即每次随机选取枢纽而不是最后一个,比原始版本更好?)

堆排序是原地的;(二叉)堆基于完全二叉树实现;堆从左到右、从上到下(除了最后一排,其他层都是满的);
(子函数parent、left、right分别计算父节点、左孩子、右孩子;)
(堆分为大根堆和小根堆,分别对应升序排序和降序排序;)
(堆排序的子函数较多,最重要的是保持堆性质的MAX-HEAPIFY;对以i为根的子树调整满足堆性质,即不断将孩子与父节点交换;是递归函数,也可用迭代代替;)
(BUILD-MAX-HEAP是建堆函数,对数组每个元素执行MAX-HEAPIFY;注意,是自底向上的,即坐标从大到小减为1,对除叶子节点之外的其他节点;)
(HEAP-SORT函数是外层排序函数,首先调用BUILD-MAX-HEAP,然后每弹出一个元素,执行堆调整MAX-HEAPIFY;属于堆的元素逐渐减少,最终得到的数组就是有序的;)

排序算法稳定性:
堆排序、快排、希尔排序、直接选择排序不是稳定的排序算法;
基数排序、冒泡排序、直接插入排序、折半插入排序、归并排序是稳定的排序算法;

sorted内部实现是TimSort?sort采用混合排序,规模小的时候采用binary insertion,规模大的时候采用sample sort?
(TimSort既是稳定的,也是原地的;)
https://en.wikipedia.org/wiki/Samplesort)
https://www.cnblogs.com/clement-jiao/p/9243066.html)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值