排序的概念

排序,就是重新排列表中的元素,使表中的元素按照关键字有序的过程。
我所了解的 表 多半是顺序表,因为顺序表实现较为简单,但是链表结构同样可以实现很多排序算法。
定义中的元素一般指什么元素呢?
一般可分为两大类 基本类型 自定义类的类型

基本类型指的就是整型,浮点型,字符型这些属于语言基本类型的东西,比如在js中基本类型就包括 string number bool object symbol,undefined,null
自定义类一般就是 语言中封装的结构体或者类,对象等,不同编程语言可能有些差别,C语言中就是struct结构体 js中就是包含相同子段的对象的集合。

上图展示C语言中的结构体,一个Student结构体中包括了name,
age,score三个字段。

我们为什么需要对排序的元素做这样的划分呢?

排序的稳定性

回答上面的问题牵涉到排序算法的稳定性。首先给出排序算法稳定性的一个拗口的定义:

假设待排序表中有两个元素Ri和Rj,其对应的关键字相同即keyi = keyj,且在排序前Ri在Rj之前,若使用某一算法排序后,Ri仍在Rj之前,则称这个排序算法是稳定的,反之则不稳定。

注意,此时的排序算法是针对关键字key的。那么这段定义到底表述的是什么意思呢?我们可以先把目光集中到上面定义的Student结构体中。

假设我们现在有个关于Student的顺序表,对于关键字age来说,顺序表中的结构体是无序的,因为我们期待的是age从小到大排列,实际情况却是从大到小。
那么如果一个排序算法要针对上述age字段进行排序,我们可以发现的一点是张三和李四的年龄是一样的,并且张三在李四的前面,排序算法按照上述定义如果是稳定的那么排完序之后,王二到了第一位,因为他年龄最小,并且张三和李四的前后相对位置不能发生改变。
排序的稳定性有何意义?
它可以记录数据排列之前的状态,举一个实际的例子,假设我们一张表,表中记录了一个学校全部学生的高考成绩,字段包括姓名,班级,分数。
一开始表中数据状态是散乱的,首先我们按照成绩进行从大到小排序,我们会得到一张新表,表中的记录是按照成绩的高低从大到小依次展示的。 然后我们再按照班级来进行排序,那么结果会是怎么样的呢?
如果我们使用的排序算法是稳定的话,表中的记录会是这样的:一班同学全体在表的开始,然后是二班,三班。。。
并且每班同学的成绩是从高到低依次排列的
现在大家应该可以理解排序算法稳定性的重要性意义了。
我们回到最开始的问题,排序元素为什么要分为基础数据和自定义类呢?
要知道基础数据是长得一模一样的,那么排序的稳定性就不需要关注了,可是自定义类就不一样了,就向上面所举的例子,因为一条记录包含不同的字段,实际过程中不可能有两条一模一样的记录。

排序的分类

内部排序

排序期间元素全部放在内存中的排序

外部排序

指排序期间元素无法全部同时存放在内存中,必须在排序的过程中根据要求不断在内外存之间移动的排序。

主要内容

我们研究的排序算法主要是内部排序,内部排序包括 插入排序,交换排序,选择排序,归并排序,基数排序等。下面分块总结

排序总结

插入排序

插入排序包括三种排序方法 直接插入排序,折半插入排序, 希尔排序。

直接插入排序


思路:
(1)假设我们有一个序列List,它的前一小部分已经是有序的了,后面的部分还是无序的。
我们从无序的部分中拿出第一个元素 A ,将他与前面的有序部分的最后一个元素进行 S 比较,如果A比S大,那么不需要改变A的位置,插入结束。如果 A 比 S小,那么就需要将A与S交换位置,然后一直比较下去,直到找到第一个小于等于他的数字为止,交换结束,插入完毕。
(2)第二种思路,找到L(i)在L[0…n]中的插入位置k,将L[k…i-1]中的所有元素后移一个位置,将L(i)复制到前面已经排好的序列中去。

代码解释:首先我们定义了一个swap的方法,这个方法就是为了交换一个数组中指定位置的两个数。内部排序算法多半就基于比较和交换的,所以我们在其他的排序算法中同样会使用swap方法,到时候就不再赘述。
上面的直接排序算法是根据思路1写出,思路2的代码本人认为不够简洁以及容易理解,在此不再赘述。

空间复杂度:O(1)
时间复杂度:O(n²)
排序稳定性:为稳定的排序算法,因为只有插入项小于比较项的时候才会发生交换。
适用性:适用于顺序表和链表。

折半插入排序

折半插入排序就是在寻找插入位置的时候不是一个个向前比较,而是利用二分法迅速的找到我们需要插入的位置,但是我们需要向后移动元素的个数并没有减少,所以折半插入排序的时间复杂度依然是O(n²)

总之折半直接插入算法,就是直接插入算法的基础上加入了二分查找法。

希尔排序

直接插入算法适用于基本有序的排序表和数据量不大的排序表。也就是说数组越有序,那么希尔排序的效率越高,因为他所需要移动的元素越少。
又有一位比较牛逼的科学家 Donald Shell提出了一个观点,要是可以把待排序表分割成若干组长度较小的序表,然后对各个子表进行直接插入排序,当整个表中的元素已呈基本有序,再对全体记录进行一次直接插入排序。
通俗点说我们 可以理解为表中各个小的地方都有序了,那么整体自然更加的趋向有序。
那么具体操作过程是什么?我们怎么去选择子序列?
希尔提出,假设我们的数组长度是n 我们第一次取d1 = [n / 2]
所有距离为d1倍数的元素被分在了一组。
如果我们的数组长度为10,{0,1,2,4,5,6,7,8,9},那么第一次取d1 = 5,则数组中的分组为
【0 5】 【1 6】 【2 7】 【3 8】 【4 9】
我们先在这些个子序列中利用直接插入排序把他弄有序,然后缩短步长,取d2 = [d1 / 2] = 3(注意这里是向上取整)
那么此时的分组就是
【0 3 6 9】 【1 4 7】 【2 5 8】
注意d等于几我们就分成了几组
最后一组d一定是1,因为我们需要对整个数组进行插入排序

代码解析:希尔排序的代码并不是那么好理解,首先我们取步长
d为 length / 2 说明我们要分d组 ,所以第一层for循环表示的是,每次循环表示一个分组。内层循环表示遍历这个组的所有数,一个某个数满足插入的条件进行交换。循环结束后改变步长为 d / 2;d最小为1,比1小就跳出循环。
稳定性:希尔排序不是稳定的排序算法

插入排序的一些注意点

  • 对n个不同的数据元素进行直接插入排序,最多需要的比较次数为 n(n - 1)/ 2,最小的比较次数为 n - 1
  • 待排序的元素序列基本有序的前提下,直接插入排序的时间复杂度接近O(n),且空间复杂度极低
  • 折半插入排序和直接插入排序的区别仅仅在于元素之间的比较次数

交换排序

概念

王道教材上交换排序是指序列中两个元素关键字的比较结果来对换这两个记录在序列中的位置。主要排序算法是冒泡排序和快速排序。其实我觉得这个分类并不够准确,因为插入排序也可以实现为交换排序,就跟我上面思路一实现的代码一模一样。

冒泡排序

冒泡排序很简单,但是实际做项目里面也很少会用得到。
思路:从后往前(或者从前往后)两两比较相邻元素的值,若为逆序则交换他们,直到序列比较完。第一趟冒泡的结果总是将最小的元素交换到待排序列的第一个位置(或者是把最大的元素交换到待排序列的最后一个位置)。
代码实现
1.我见过最简单的一种冒泡,对于长度为n的序列来说,需要经过n -1次冒泡,每次固定住一个元素的位置。

这种算法有个明显的缺陷,那就是比较次数,就算是序列本身已经是有序的了,还是需要比较,这就说明比较次数是和数据状态无关的。
2.第二种代码对上面代码进行了改进,如果在某躺冒泡中,我们发现元素并没有进行交换了,那么说明此时序列已经排完了,可以跳出循环。

一个简单的实验,用一个count变量记录第一种冒泡和第二种冒泡对于一个正序序列(长度为7)进行比较的次数,我们发现第一种count等于21,第二种为6.
时间复杂度:最好情况O(n),最坏情况O(n²)
空间复杂度:O(1)
比较次数:最好情况 n -1,最坏情况 n(n -1)/2
稳定性:稳定的排序算法。

快速排序

快速排序是所有内部排序算法中性能最优的排序算法,并且也是最不容易理解的一种排序算法。
思路
快排是我们接触的第一种基于分治法的算法,他将一个大问题划分成了两个规模更小的小问题。我们首先从排序表中找到一个基准元素(pivot)通过一趟排序将待排序表分为独立的两部分,前半部分小于pivot,后半部分大于等于pivot。然后递归这两个子部分,直到每部分只有一个元素或者空为止。
现在出现了一个主要问题,如何使得待排序表能够被划分成两部分,其中一部分小于pivot,另一部分大于等于pivot?这个过程我们把它称为partition。

上述图的过程很清晰的展现了快速排序一个partition的过程。
代码实现:

快速排序的性能分析较为复杂,由于快速排序是递归的(实际上所有的递归算法都可以变化成非递归),需要借助一个递归工作栈来保存每层递归调用的必要信息,其容量应与递归调用的最大深度一致。最好情况下为O(log2n),最坏情况下为O(n)
时间复杂度:最佳情况为O(n * logN),提升快排算法的方法,pivot尽量选择为中间大小的数字,使得能够平分两个子过程。
稳定性:快速排序算法是不稳定的。

快速排序算法的partition思想特别重要,它可以在排序的同时,准确定位到排序表中特定位置的元素,划分算法一定要想到快速排序的思想,下面举一个题目的例子。
找出一个无序表中第k小的元素

选择排序

基本思想:每一趟(第i躺),在后面n - i + 1个待排序元素中选取关键字最小的元素,作为有序子序列的第i个元素,直到n - 1躺做完,待排序元素只剩一个,排序结束。
选择排序和冒泡排序的差不多,都是在,每一趟中网有序子序列中添加一个元素。

简单选择排序

思路:假设我们有排序表L[1…n],第 i 躺排序从L[i…n]中选出一个最小的,将其与第 i 位交换,每一趟都可以确定一个元素的最终位置,并且保证已排的子序列有序。
代码实现:

时间效率:我们可以发现,简单选择排序的比较次数与序列的初始状态无关,始终为n (n - 1) / 2
空间效率:O(1)
稳定性:不稳定

堆排序

堆排序可以说是和快速排序同样重要的一种排序。
堆排序将一个数组看成一棵完全二叉树(关于完全二叉树的定义请自行百度,篇幅有限,不再赘述)。第i个结点的左孩子的序号是2i + 1,
右孩子的序号为2i + 2,他的双亲结点的序号为(i - 1)/ 2.
一个特殊的结点为数组中序号为0的结点,它的双亲结点还是自己,所以能够和其他结点之间进行区分。

知道了堆以后,还需要明白两个概念:大根堆和小根堆
大根堆:所有子树的根结点都是最大的
L[i] >= L[2i + 1] && L[i] >= L[2i + 2]
小根堆:所有子树的根结点都是最小的
L[i] <= L[2i + 1] && L[i] <= L[2i + 2]

上述图展现了一个大根堆,所有树的根结点必然最大,并且左右孩子结点的大小不定。
那么知道啥叫大根堆以后,我们又如何来根据这一特殊的结构来进行排序呢?
首先我们拿到一个顺序表,将其转化成一个大根堆,那么我们可以发现大根堆的根结点一定是最大的元素(这点极其重要!!!)
然后我们将大根堆的堆顶(就是根结点)和最后一个元素交换,将这个位置固定。此时,我们看上图,假设我们将100和7交换位置,那么此时的堆就不再是大根堆了,需要将其再次转换成大根堆,但是注意的是100的位置我们就不需要去动了。
也就是说,堆排序一趟排序确定了当前堆中最大的元素,并将其放到堆的最后一个位置,n - 1躺过后必然已经称为一个有序的数组。
现在有两个问题:

  1. 我们如何将一个数组初始化为一个大根堆?
  2. 当大根堆的堆顶元素发生改变后我们又怎么将其重新转换成大根堆?

    上述代码中heapSort中使用了一个for循环,这个for循环的作用是,将第i位元素添加到堆中,并且保证堆是一个大根堆。
    代码的灵魂在于heapHelper方法,当新加入的元素比自己的双亲结点大的时候,将其互换,一直持续到,自己的某个双亲结点不必自己大了,就跳出循环。
    这里有个特殊的点是0,当index = 0的时候,我们发现(index - 1)/2
    依旧是0,所以二者相等,跳出循环。

好了,至此,我们已经掌握了一个数组转化成大根堆的方法了。
接下来的问题就是将堆顶元素与堆中最后一个元素交换以后,怎么将它再次的变成一个大根堆。

这里我们着重论述一下heapify的过程,heaplify有三个参数,第一个是待排序的数组,第二个是开始大根堆化的根结点index(一般都是0),第三个是标识当前堆大小的heapSize。
首先获取当前结点的左孩子结点left(通过对应的序号关系就可以得到),当left并未超过当前堆长度的时候,我们开始循环。
思路是找到index结点的左右孩子中较大的那个,给largest赋值的这句长代码就是完成了这个任务。
第二步比较 index根结点 与 左右孩子结点中较大值 之间的大小 并重新给largest赋值
第三步 做判断 如果largest就等于index根结点,说明 index根结点本身就是最大的,不需要往下交换了。否则,就需要和较大结点之间做交换 ,并且给index重新赋值,进行下一次循环。

上面的代码我觉得是较容易理解的版本了,逻辑和变量语义化来看都非常好。

关于堆排我们已经完成了最主要的两个任务了,下面是堆排序的完整代码。

值得注意的是,当我们每次将根结点(最大值)swap到最后的时候,需要通过–heapSize使得堆的长度减1来固定这个最大值。

空间效率:O(1)
时间效率:O(n * logn)
稳定性:不稳定的排序算法

堆排序的一些常考的注意点

堆排建堆的时间效率不会超过4n(虽然我也不知道咋算出来的)。
在尾部插入一个元素或者从堆顶弹出一个元素都是 logN的时间效率。
当我们需要在大量数据中找出k个最大或者最小的元素时都采用堆排序。

归并排序与基数排序

归并排序的思想独树一帜,它是将长度为n的待排序列表看成 n 个小组,两两和并 使其有序,这样我们就获得了【n / 2】(向上取整)个有序的小组,这个过程被称为一趟2路归并,直到合并成长度为n的有序序列。

空间效率:需要空间为n的辅助数组O(n)
时间效率:O(n * logN)
稳定性:稳定的排序算法

基数排序

基数排序较为奇特,一般是基于链表来实现的一种排序,它不基于移动和比较,而是将单个关键字转换成多个关键字进行排序的方法
比如对于一群小于1000的数字来说,每个数字可以看成有个,十,百三个关键字组成。于是我们可以把数字一个关键字,拆分成个,十,百三个关键字。
基数排序包含两种方法,第一种是最高位优先(MSD)法,按关键字位权重递减一次逐层划分成若干更小的子序列,最后将子序列依次连接。第二种最低位优先法,与上个方法是相反的过程。
那么基数排序具体如何操作呢?下面以最低位优先法举例。
First,先定一个基数r,这个基数r代表了拆分出来的关键字集合(如上述的个,十,百位)中可能取值的个数。比如个,十,百,他们的取值可能都是0 ~ 9,所以取值个数为10,那么就把r定为十。
Second,定义r个队列,并将他们置空。
Then,进行分配和收集。
啥叫分配和收集?
我们有多少个拆分出来的关键字,就需要多少回分配和收集。
一次分配的过程如下:一一扫描线性表中的结点,发现了关键字与队列对应的取值相等,那么就将该结点添加进这个队列。比如我们首先开始个位数关键字的分配,总共r(r = 10)个队列分别对应0 ~ 9,我们扫描链表中的结点的时候,发现个位数等于5那么就加到对应5的队列中去。
一次收集的过程如下:将刚刚被分配完毕的队列依次首尾相连获得一个新的队列。
一次收集和分配也被称为一趟排序的过程。

基数排序刚刚接触可能觉得有点奇怪,但是把上面的图看懂了以后应该就能大致理解,基数排序到底在干什么了。
基数排序代码实现一般不会考察,我们只需要它的过程就可以。
空间复杂度:O®,r个队列
时间复杂度:d躺分配收集O(d),一次分配是O(n),一次收集是O®
所以时间复杂度是O(d(n + r))
稳定性:因为队列先入先出的特点,是稳定的排序算法。

总结

八大内部排序算法内容还是不少的,在记忆时,应着重于原理时间复杂度空间复杂度算法稳定性适用场景几个方面进行记忆。
下面进行一个总结。

冒泡排序算法总结

原理:两两比较相邻的记录,向左或者向右冒泡,一趟排序可以确定一个元素的最终位置。
时间效率:冒泡排序的时间效率是和待排序列的初始状态有关的。
最好的情况下,初始列表有序:
比较次数为n - 1次,移动次数为0次,时间复杂度为O(n)
最坏情况下,初始列表无序:
比较次数:第i趟排序需要比较n - i次 i从1 到n - 1求和为 n(n - 1) / 2
移动次数:3n(n - 1)/2 移动次数是比较次数的三倍
时间复杂度:O(n²)
空间效率:O(1)
算法稳定性:因为每次比较,如果两个元素相等,那么就不会发生交换,所以是稳定的排序算法。
适用场景:冒泡排序是和待排序列的初始条件有关的,所以当待排序列几乎是有序的,那么冒泡排序的时间是线性的,可以使用。

快速排序算法总结

原理:快排的基本思想是基于分治的,从待排序列中挑出一个基准,将整个序列分成小于基准的,大于等于基准的两部分。一趟排序可以确定一个元素的最终位置。快速排序对于划分数组来说有奇效,比如我要找一个数组中第k大的数字,相当于就把数组划分成了比k小的部分和比k大的部分。再比如把数组较小的一半和较大的一半分开等等。
时间效率:快排的时间效率是和partition分不开的,究其根本就是pivot的选定问题,如果partition能使得划分出的两部分均一,那么时间效率就会较高。
最坏情况:pivot选的太大或者太小此时的时间复杂度为O(n²)
最好情况:pivot选的正中间,此时的时间复杂度为O(n * log n)
空间效率:快排的空间效率同样和pivot的选定有关
最坏情况:调用栈的深度为O(n)
最好情况:调用栈的深度为O(n * log n)
算法稳定性:不稳定
适用场景:当n较大,关键字趋近于随机分布,不要求稳定性的时候,那么用的一定是快排,因为快排被认为是效率最高的内部排序算法。

插入排序算法总结

原理:子序列已经排好,插入排序就是把无序序列中的元素,往前面排好的子序列里面插入。直接插入与折半插入的区别在于定位插入的位置,也就是比较元素的次数不同。希尔排序规定了步长,在对应步长的子序列中应用直接插入排序,并一步步缩短步长直至为1.

时间效率:关于直接插入排序的比较次数和移动次数我是存在疑虑的,在严蔚敏的教材里把哨兵的比较也算了进去,至于什么是哨兵其实我也不太理解。但是我认为直接插入排序的时间效率是和冒泡的情况类似的。
最好的情况下,初始列表有序:
比较次数为n - 1次,移动次数为0次,时间复杂度为O(n)
最坏情况下,初始列表无序:
比较次数:第i趟排序需要比较n - i次 i从1 到n - 1求和为 n(n - 1) / 2
移动次数:3n(n - 1)/2 移动次数是比较次数的三倍
时间复杂度:O(n²)
空间复杂度:O(1)

算法的稳定性:稳定的

适用场景:n较小或者待排数列基本有序,仔细分析算法的化,直接插入排序肯定是比冒泡排序好的,所以遇到两个都可以用的时候,要选直接排序。此外直接排序可以用链表结构实现,当所含记录数据量庞大,移动记录耗费大量时间,采用链表作为存储结构。

简单选择排序算法总结

原理:第i趟在后面n - i + 1个待排序元素中选取关键字最小的元素,作为有序子序列的第i个元素,直到n - 1趟完成。简单选择排序同样也是每一趟排序就能确定一个元素的最终位置。

时间效率:比较次数是一定的,与数据原始状态无关,为n(n - 1)/2.元素移动次数不定。最好情况下,待排序列有序,无序移动。
最坏情况下,待排序列逆序,移动次数3* (n - 1),所以时间复杂度始终是O(n²)

稳定性:因为每次找到最小值以后需要交换位置,可能会把数字相同在前的换到后面去。,所以是不稳定的。

适用场景:简单排序移动元素的次数少,所以当n比较小的时候,元素的信息量较大,那么就可以使用简单选择排序。

堆排序算法总结

原理:堆排序是把数组按照下标的关系视作了一棵完全二叉树,我们排序所用到的堆是大根堆。使用堆排序对数组进行排序的时候首先将数组转化成大根堆,从第一个非叶子节点开始筛选,直至变成大根堆。获得大根堆以后,每次将堆顶的元素与最后的元素交换位置,重新的构造大根堆。堆排序每次可以确定最后一位元素的位置。

时间效率:建堆的时间为O(n),添加新元素,弹出堆顶,调整大根堆的时间都是O(logn),最好,最坏和平均情况都是O(N * logN)

空间效率:O(1)

稳定性:不稳定的排序

适用场景:通常,取一大堆数据中k个最大或最小元素时都优先采用堆排序

归并排序算法总结

原理:我们说的归并排序一般都是2路归并排序,归并排序一般是将两个有序表归并为一个有序表,所有用归并排序的思想可以解决两个两个有序表合并的问题。归并排序每个数都可以找到比自己大的数,所以还可以用来解决小和逆序对问题。

时间效率:每次归并的时间复杂度是O(n),与原始状态无关,需要进行【logn】次归并(向上取整),所以时间复杂度就是O(n * logN)

空间效率:O(N)

稳定性:当左右两边元素相等的时候,右边的先入辅助表,所以不改变元素之间的相对位置,是稳定的。

适用场景:当n较大的时候,需要使用O(n * logN)排序算法,如果还要求稳定性,这个时候可以使用归并算法。

基数算法总结

基数算法上面的总结的很到位了,这里做个补充,当n很大的时候,关键字位数较烧且可以分解的时候,我们可以采用基数排序。如按照出生日期的月,日来给中国人排序。

内部排序算法全面总结相关推荐

  1. 超详细!各种内部排序算法的比较

    先来个表格总结直观展示下: 各种内部排序算法的性质            算法种类                    时间复杂度  空间复 杂度 稳定性 最好情况 平均情况 最坏情况 插入排序 直 ...

  2. 飞鸽传书内部排序算法的性能比较

    部排序算法的性能比较 飞鸽传书内部排序算法的性能比较 1)排序的稳定性及分析: 假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,ri=r ...

  3. 数据结构之排序算法:内部排序算法的应用与比较

    排序算法:内部排序算法的应用与比较 思维导图: 比较: 应用: 思维导图: 比较: 应用:

  4. 数据结构之内部排序算法总结笔记

    内部排序算法  排序的基本概念: 把一组无序的数据元素按照关键字值递增(或递减)的顺序重新排列.  一.插入排序 思想:将序列分为[有序段]与[无序段]两段,然后依次将[无序段]中的元素插入到[有序段 ...

  5. 《数据结构》--内部排序算法比较

    题目 各种内部排序算法的时间复杂度分析结果只给出了算法执行时间的阶,或大概执行时间.试通过随机的数据比较各算法的关键字比较次数和关键字移动次数,以取得直观感受. 基本要求: (1) 从以下常用的内部排 ...

  6. 内部排序算法比较-数据结构C语言课设

    名称:内部排序算法比较 内容:在教科书中,各种内部排序算法的时间复杂的分析结果只给出了算法执行时间的阶,或大概执行时间.试通过随机数据比较各种算法的关键字比较次数和关键字移动次数,以取得直观感受. 任 ...

  7. 《内部排序算法比较》

    <内部排序算法比较> 一.[问题描述] 在教科书中,各种内部排序算法的时间复杂度分析结果只给出算法的大致执行时间.试通过随机数据比较各算法的关键字比较次数和关键字移动次数,以获得直观感受 ...

  8. 九大内部排序算法(快速排序、归并排序、堆排序、希尔排序、基数排序)

    排序(Sorting)是计算机程序设计中的一种重要操作,它的功能是将一个数据元素(或记录)的任意序列,重新排列成一个按关键字有序的序列. 文章目录 由于待排序的记录数量不同,使得排序过程中涉及的存储器 ...

  9. 《数据结构》之内部排序算法比较

    前言 各种内部排序算法的时间复杂度分析结果只给出了算法执行时间的阶,或大概执行时间.试通过随机的数据比较各算法的关键字比较次数和关键字移动次数,以取得直观感受. 基本要求: (1) 从以下常用的内部排 ...

最新文章

  1. input子系统分析之三:驱动模块
  2. 如何使用mklink命令DIY自己的Windows Live Writer——安装、保存博文到D盘
  3. python的用途实例-Python实例方法、类方法、静态方法的区别与作用详解
  4. 常用系统分析监控工具
  5. hibernate 高级查询 query 或查询 or ,Restrictions
  6. 黑龙江认识电子计算机ppt,《第22课 不断发展的现代社会》优秀教案(黑龙江县级优课).docx...
  7. make changes to the open source project?
  8. oracle函数 trunc(x[,y])
  9. 在河北当中学老师用不用考计算机,河北省教育厅出台新方案 师范生当教师也需考证...
  10. 密码中不能包含全角字符的正则表达式
  11. 教你设置eclipse自动生成的author等注释
  12. 【iPhone】缺陷检测机器视觉在制造业缺陷检测的应用情况
  13. editor.md七牛云上传图片springboot_spring boot 若依系统整合Ueditor,部署时候上传图片错误解决...
  14. python抓包与解包_python 抓包与解包
  15. python入门之排序,文件操作
  16. python汉化包放哪_python 汉化
  17. 【Shashlik.EventBus】.NET 事件总线,分布式事务最终一致性简介
  18. 微信小程序仿今日头条小程序端界面和代码演示
  19. 17.3.13 多任务学习 Multi-task learning
  20. php中文搜索工具,Laravel 下 TNTSearch+jieba-PHP 实现中文全文搜索

热门文章

  1. 人工智能-高等数学之偏导数与梯度
  2. Tableau导出sql语句和性能监控
  3. 2008 奥运会开幕式 色彩绚烂 方块太小
  4. 为什么 group by后面 必须跟selecte 后面的除了聚集函数外的所有字段
  5. Android之应用开发基础
  6. Windows创建符号链接、目录链接、硬链接
  7. EyouCMS精美简洁作文范文网站模板/易优CMS资讯类企业网站模板
  8. 日语语法(一):概述
  9. 如何在 JavaScript 中等待函数完成
  10. linux开关机 按钮 间隔60秒,解决Linux性能问题的前60秒