计算机最早的排序算法源于人的生活和经验,那么我们人是怎么排序的呢?
如果只有三五个数字,我们可以扫一眼就排完了序。但如果到几十个数字,这就有点麻烦了,因为如果没有一个必须严格遵守的流程,排完序经常会有些小错误。
问题:如何给班上50个同学的成绩排序?
在没有计算机的年代,可能就只有两种笨办法:
用这两种方法排50个人的成绩,工作量并不算小。
其实,早期的计算机科学家比普通人也强不到哪里去,他们提出的排序算法就是上面两种。
接下来怎么提高计算机算法的效率呢?
以冒泡排序为例,之所以慢,是因为每一次选出一个最大的数,都要和其它所有的数字相比,其实并不需要这么麻烦,要想提高效率,就要减少数据之间的相互比较。
最早对冒泡排序的改进是一种叫做归并排序的算法,它就利用了少做事情的思想,归并排序的思想大致如下:
后面还有科学家优化了归并排序,优化的地方是充分利用现实世界待排序数据力,很多序列是已经排好序的不需要再重新排序,利用这个特性并且加上合适的合并规则可以更加高效的排序剩下的待排序序列。
这种思想就是分而治之,在分治思想下的排序算法不止归并排序,还有快速排序,快速排序是基于比较中最快的排序算法了,排序速度是比较类排序算法的极限。
它还是强调少做事情,其原理大致是这样的:
我们可以在一个例子中,对比一下这几种排序:
快速排序是通常情况下最好的算法,但是,在极端的情况下,它的复杂度是N平方,和冒泡排序一样糟糕。而归并排序,即使在最坏的情况下,也能保证N乘以log(N)的复杂度,所以,我们在学习排序时,主要是把精力花在快速排序上,特别是对快速排序的优化上。
随着科技的进一步进步,有没有可能发明一种比快速排序更好的算法?从科学上讲,答案是否定的。因为从数学上可以证明N个任意随机数的排序,复杂度不可能比N乘以log(N)更低,这是数学给出的极限,或者边界,因此有点头脑的人都知道别在这方面瞎费工夫。
具体的证明过程:
从算法分析角度来看,降低复杂度的方法无非种:
比较排序算法的极限是O(N logn),而归并、快速排序恰是这个极限速度,说明分治思想把基于比较的排序算法优化到极限了。
所有人的成绩无非是 0-100,那我们买101个桶,按照次序一字排开,桶的排列顺序分别代表了具体的分数,第1个桶是0分,第2个桶是1分···第101个桶是100分。
假如小明考了82分,那就把小明的名片放进第83号桶,有多个人就放多少次即可,直接就没有比较的过程,速度是O(N)。
如果要把一个集合排序,那贪心的话,就是只看局部(紧邻的俩个元素)。
如果我们要把这个集合,弄成从小到大。
局部就俩种情况:
那我们可以把第二种改成第一种,这样若干个局部叠加起来就组成了有序的整体了。
于是,就产生了【冒泡】、【地精】排序。
俩种排序的思想是一样的(贪心),只不过策略不同。
地精排序的策略是比较朴素的,所以也被称为“愚蠢排序”。
比如,集合「8,24,5」。
这个交换的过程就是【地精排序】的核心。
地精排序策略:攘外必先安内。
这时这个集合就划分成了 2 部分:
-「第 n 个元素到最后一个元素」
比如上面的例子,排序集合「8,24,5」。
地精排序的过程:
优化思路,如果退了很多步,那回到原位置,要一步步加进去。这里做了很多无用功,我们可以直接设置一个变量来定位,实现瞬间移动。
冒泡排序类似,只不过冒泡的策略是:一直攘外。
上面这俩步和地精一样。
地精第三步是【回过头】检查,等内部完全排序好了,再继续和外面的比较。
冒泡第三步是【一直攘外】,交换好了就好了,至于局部是什么样的以后再说,而后继续往前比较,直到比较完。
冒泡排序相信,排序完后,局部的有效性会得到改善。
经过一趟一趟的迭代,就会产生一个不变性,经过 i 次迭代,最大的 i 的元素必然已经排好序,问题规模就变成了 len - i。
经过 len 趟迭代后,就排好序了。
锦标赛排序,顾名思义,是受体育比赛的启发想出来的。
锦标赛排序的好处是,它并非要等到所有的排序工作都做完的时候,才知道谁是第一名,而是可以只排出前几名。
这种赛制的合理性来自下面一个假设:
只要上面这种胜负的传递性成立,通过这种比赛的结果得到的冠军,一定是最好的选手。
但是,第二名是否如此,就难说了。因为冠军一路打下来,被他刷掉的选手可能水平都不差,只是运气不好,提前遇到他了,在决赛之前被淘汰了。
比如说在某次比赛中,A半决赛赢了B,决赛赢了C。
因此,如果真要较真,就需要把被冠军淘汰下来的人放到一个组里再相互比赛,才能知道谁是亚军。
这就是锦标赛排序的步骤了:
第二步,是锦标赛排序的难点,恰好高盛有一道面试题,如果您懂第二步,就可以做出了。
高盛面试题:假定有二十五名短跑选手比赛竞争金银铜牌,赛场上有五条赛道,因此一次可以有五个人同时比赛。比赛并不计时,只看相应的名次。假如选手的发挥是稳定的,也就是说如果张三比李四跑得快,李四比王五跑得快,那么张三一定比王五跑得快。最少需要几组比赛才能决出前三名?
第一步,将25名选手分为五个组,每组五个人,为了便于说明,我们不妨把这25人根据所在的组进行编号,A1-A5在A组,B1-B5在B组……最后E1-E5在最后的E组。
而后让每个组分别比赛,排出各组的名次来。我们假设他们的名次就是他们在小组中的编号,即A组的名次是A1、A2、A3、A4、A5,B组和其它组的名次也是类似(如下图):
第二步,让各组的第一名,也就是A1、B1、C1、D1、E1再比一次,上图中是第一排红颜色的,这样就能决出第一名。不失一般性,我们假设A1在这次比赛中获胜,这样我们就知道了第一名。
由于A1是第一名,根据我们前面讲的淘汰赛的问题,A2可能也很厉害,只是运气不好,小组赛遇到了A1,当A1已经获得冠军了,他就应该作为亚军的候选。接下来,就进入第三步。
第三步,A2和另外四个组的第一名竞争亚军。如果这一次A2赢了,他显然是亚军,就由A3递进参加争夺第三名的比赛。我在下图中用红色圈定了这种情况下参加第八次比赛的五位选手。如果A2没有赢,另四个组的某个第一名赢了,那个赢的人是亚军,就由那个组下一位选手递进,决逐第三名。
第四步,如上图选出的五个人进行第三名的比赛,至此,前三名全部产生。
如果你在面试中告诉对方上面这种方法,表现可能算是中规中矩,但不算完美。
那么这个问题最好的答案是什么呢?
那么谁还会是第二名的候选呢?
接下来我们要问,除了A2和B1,谁还会是第三名的候选呢?
因此,第二、三名的候选人一共只有五个,即A2、A3、B1、B2和C1(下图中的红色选手),刚好凑一组。
前六次,得到第一名。
第七次,让他们五个人再跑一次即可同时得到第二、三名。
这样加上前六次,只需要赛七组,这是最佳的方法。
再本篇文章中,我们将通过实操一个小题目,来理解与运用冒泡排序冒泡排序是什么,怎么工作的?冒泡排序是一种排序算法,它可以将一堆无序/乱序的元素,排列成有序的元素。它的工作方式就和在水底吐泡泡一样:一次吐一个泡泡,泡泡吐出来后向上冒,而当这个泡泡向上冒的运动结束时,它的位置处于当前水的最高处(水面上)的。如图:我们每一次冒泡的过程中,都会从第一个数开始,不断地向后进行比较。以排升序(从小到大排)为列:
排序算法之计数排序的优化
在这里,我们将根据几个因素比较各种排序算法。时间复杂度空间复杂性稳定/不稳定实际测试时间复杂度比较一个表格,其中显示了一些最常用的 Sorting Algorithms(排序算法)的时间复杂度。时间复杂度是比较两种排序算法时需要检查的第一件事。时间复杂度越低越好。排序算法平均大小写最佳案例最坏情况冒泡排序O(n2)O(n)O(n2)插入排序O(n2)O(n)O(n2)选择排序O(n2)O(n2)O
一、冒泡排序已知一组无序数据a[1]、a[2]、……a[n],需将其按升序排列。首先比较a[1]与a[2]的值,若a[1]大于a[2]则交换两者的值,否则不变。再比较a[2]与a[3]的值,若a[2]大于a[3]则交换两者的值,否则不变。再比较a[3]与a[4],依此类推,最后比较a[n-1]与a[n]的值。这样处理一轮后,a[n]的值一定是这组数据中最大的。再对a[1]~a[n-1]以相同方
分而治之是计算机领域非常常用的一种思想。在排序中,将数组拆分成不同的组,此为分,每组数据分别在各自组内进行排序,此为治。分治可以很好的利用多处理器的并行计算能力,提高排序效率。今天介绍两种基于分治思想的经典排序算法:快速排序和归并排序。快速排序快速排序的基本思路是,首先选取一个基准值,然后根据基准值,将数组拆分为左右两部分,使得基准值左侧的元素,都比基准值小,右侧的元素,都比基准值大。随后,对左右两部分数组进行同样的操作:选取基准值,做划分处理。一直分到不能再分,数组就整体有序了。每经过一轮排序,该轮基
排序算法思想描述---qpz一、直接选择排序法a) 核心思想:在无序区间寻找最值与无序区
希尔排序基本思想: 先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组。所有距离为d1的倍数的记录放在同一个组中
1. 基本思想: 每一趟从待排序的数据元素中选出最小(或最大)的一个元素,
这一系列博客的特点就是——给出每趟排序的结果本来想着好好写一下过程,弄个图片什么的,不过觉得网上的解析太多了,都比较好,所以这些博客就算是对自己的总结吧。#include <stdio.h>#include <limits.h>#include <malloc.h>int a[10]={2,8,5,7,4,3,1,
一、冒泡排序算法个人理解主要是以两个形成嵌套的for循环来完成的。外层的for循环以索引ix的值来逐个访问序列中的每个元素,ix的值由0开始增加到size(sequence) - 1,当外部的for循环迭代完成后,由ix索引取出的元素已经被放在正确的位置上了。放元素的操作是由内层的for循环来实现的,内层for循环的索引的值jx从ix+1依次递增到size(sequence) - 1为止,它比...
一、选择排序算法个人理解如果有N个元素需要排序,首先从N个元素中找到最小的那个元素,然后与索引ix=0位置上的元素进行交换(如果没有比原来索引ix=0位置上的元素小就不用交换),接着再从剩下的N-1个元素中找出最小的元素,再与索引ix=1位置上的元素进行交换;之后,再从剩下的N-2个元素中找出最小的元素,再与索引ix=2位置上的元素进行交换,…重复上面的操作,一直到完全排序完成为止。具体排序过...
1.概述:堆排序是简单选择排序的改进算法,简单选择排序在待排序的个数据中选择一个最小的元素需要进行n-1次的比较,但是并没有将每一次循环的结果保存下来,在下一次循环中,有很多比较已经在上一次的循环中做过了,但由于上一次循环时没有保存这些比较结果,所以下一次循环时又要重复这些比较操作,隐藏数据的比较次数较多。2.大顶堆与小顶堆从上面的两幅图可以看出,它们都是完全二叉树。下面给出堆的定义:...
1.原理:希尔排序是对直接插入排序的改进,建立在直接排序的基础上实现的。因为直接插入排序适合那些数据本身就是基本有序的或者数据量比较小的情况。但是,实际中数据量小或数据基本有序属于特殊情况,这就是直接插入排序的局限性。希尔排序的基本思想就是当有大量的数据需要排序时,可以将大量的数据分组成若干子序列,此时每个子序列的数据比较少,可以对每个子序列使用直接插入排序。当整个序列基本有序时(基本有序:小的...
1.概述快速排序是冒泡排序的改进算法。它也是通过不断比较和移动交换来实现排序的,只不过它的实现增大了记录的比较和移动的距离,将关键字较大的元素从前面直接放到后面,关键字较小的元素直接从后面放到前面,从而减小了比较次数和交换次数。2.原理通过一趟排序将待排序数据分割成独立的两个子序列,其中左边的子序列均比右边的子序列中的元素小,然后分别对左右两个子序列继续进行排序,达到整个序列有序的...
1、堆排序概述堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组的特点快速定位指定索引的元素。堆分为大根堆和小根堆,是完全二叉树。大根堆的要求是每个节点的值都不大于其父节点的值,即A[PARENT[i]] >= A[i]。在数组的非降序排序中,需要使用的就是大根堆,因为根据大根堆的要求可知,最大的值一定在堆顶。2、堆排序思想(大根
常见的排序算法之Java代码解释 一 简要介绍 一般排序均值的是将一个已经无序的序列数据重新排列成有序的 常见的排序分为: 插入类排序 对于一个已经有序的序列中,插入一个新的记录。它包括:直接插入排序,折半插入排序和希尔排序 交换类排序 每次比较都要“交换”,在每一趟排序都会两两发生一系列的“交换”排序,但是每一趟排序都会让一个记录排序到它的最终位置上。它包括:起泡
索引是经常用到的技术,但有些程序员对索引的原理了解不深,发现数据查询性能有问题立刻就想起建索引,但效果常常也不尽人意。那么到底什么时候该用索引以及该怎么用?我们来分析索引清理背后的技术原理就知道了。基本原理索引技术的初衷是为了快速从一个大数据集中找出某个字段等于确定值(比如按身份证号找出某个人)的记录。一个规模(行数)为N的数据集,用遍历查找则需要比较N次,而如果数据是按该字段值(在索引中称为键值
BP算法推导BP算法(BackPropagation)反向传播算法又叫误差逆传播算法(error BackPropagation),它是迄今最成功的神经网络学习算法。 现在从神经网络训练的角度推导BP算法。 给定训练集D={(x1,y1),(x2,y2),⋯,(xm,ym)},xi∈Rd,yi∈Rl D =
前言GO语言在WEB开发领域中的使用越来越广泛,Hired 发布的《2019 软件工程师状态》报告中指出,具有 Go 经验的候选人是迄今为止最具吸引力的。平均每位求职者会收到9 份面试邀请。想学习go,最基础的就要理解go是怎么做到高并发的。那么什么是高并发?高并发(High Concurrency)是互联网分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计保证系统能够同时并行处理很多请
Open WebUI 使用 searXNG 搜索出现空值的解决办法
P9129 [USACO23FEB] Piling Papers G 不怎么常规的数位 DP。 下文中我们规定一个数的最高位为第 \(1\) 位。 下标和值域的限制都可以差分转成前缀求解。 因此我们需要解决的转化为:对于 \(a\) 的某个前缀,其 \(\le t\) 的方案数是多少? 先考虑只有 ...
由于产品是塑料件的原因,在注塑机中处于熔融状态,在填充入模具前与冷却后会发生收缩,在设计模具时必须对其乘缩水率那么,工作中我们如何对产品进行缩水的设置?1先用UG软件打开一个产品2 我们首先要了解这个产品的材料,比如产品具体是abs,pp,pom....不同的塑性材质其变形量也是不一样。3我们确定材料后,可以通过客户或资料确定其变形量,也就是缩水率。4 通过ug软件的变换功能对产品进行缩放比的设